Per-junction medal targets, measured; fix the last unplayable junction

Medal targets are no longer one uniform 15/35/60k guess across every event.
tools/tune_junctions.gd plays each junction 12 times with varied launches and
sets bronze/silver/gold at the 35th/65th/88th percentile of actual damage, so
they now range from $4k at Cliffs Corner to $73k gold at Melbourne x Merivale.
The old numbers made half the events impossible and the other half trivial.

Grey x Glenelg scored $0 in 12/12 runs and took three fixes, each found by
measuring rather than reading:
- The launch sat on the street centreline, so the car drove cleanly BETWEEN the
  two convoy lanes -- closest pass 2.9 m, almost exactly the 2.7 m lane offset.
  It now launches in a lane. (The first attempt offset the wrong way and widened
  the pass to 5.5 m, which is how the sign error announced itself.)
- int(L / headway) floors to one car on a short clipped stream, so that junction
  fielded 9 convoy cars against the usual 20-25. Minimum 3 per stream, evenly
  spaced to fit.
Result: $0 -> $91k, convoy 9 -> 18, and 0 of 9 junctions now unplayable.

The tuner has turned out to be the event validator as much as a balance tool --
"scores nothing in every run" is an unplayable event, not a tuning problem.

Also from the review: the deformer no longer crumples det_* panels after they've
been shed onto their own body, and notes that rebuilding an ArrayMesh drops any
imported LODs.

Honest gap: Cliffs Corner and Bridge Approach show median == max at ~$4.7k --
winnable and correctly tuned, but the run ends on scenery before the convoy is
reached. Both are curved approaches; they want better crossings picked by hand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-29 00:15:05 +10:00
parent 0c13c82eac
commit aac4384c05
10 changed files with 800 additions and 687 deletions

View File

@ -42,6 +42,22 @@ Controls: WASD/arrows drive, Shift drift, Space boost, R reset (or retry after C
runs**: a second Godot instance contends for the `.godot` import lock, and a level runs**: a second Godot instance contends for the `.godot` import lock, and a level
rebuild mid-flight silently feeds it half-written levels, which reads as "this event rebuild mid-flight silently feeds it half-written levels, which reads as "this event
scores zero" rather than as an error. scores zero" rather than as an error.
The tuner is also the event *validator*. An event that scores nothing across every
run isn't badly tuned, it's unplayable, and it prints `!!` for exactly that. Three
separate causes turned up that way, none visible by reading the generator:
convoy streams clipped so wide that you thread the intersection through a 20 m gap;
a launch point on the street centreline threading cleanly *between* the two convoy
lanes; and `int(L / headway)` flooring to one car on a short stream, leaving nine
convoy cars where the working events have twenty. Re-run it after any change to the
generator, the launch geometry, or convoy spacing — all three feed the numbers.
Read the spread it prints, not just the targets. **Cliffs Corner** and **Bridge
Approach** both show median == max at a low ceiling (~$4.7k), which means the run
reliably ends on the first thing you hit and the convoy is never reached — they're
winnable and honestly tuned, but they're scenery crashes rather than pile-ups. Both
sit on curved approaches where the launch street bends away from the intersection.
Worth hand-picking better crossings for those two.
- **Race** — 3 laps vs 3 rubber-banded rivals on the level's `RacePath`. - **Race** — 3 laps vs 3 rubber-banded rivals on the level's `RacePath`.
- **Drag** — NFSU2's event, our code: a straight-line run down the level's longest - **Drag** — NFSU2's event, our code: a straight-line run down the level's longest
genuinely straight stretch of wide road (the builder finds it and drops genuinely straight stretch of wide road (the builder finds it and drops
@ -227,6 +243,18 @@ Make a folder `levels/<id>/` containing `level.glb` (or `level.tscn`). Blender c
/Applications/Godot.app/Contents/MacOS/Godot --headless --path . --script tests/smoke.gd /Applications/Godot.app/Contents/MacOS/Godot --headless --path . --script tests/smoke.gd
``` ```
Covers all seven modes (cruise, crash, junction, outrun, pursuit, drag, derby,
race) in about 30 s, printing a `.. stage` line as it enters each one.
Failures go through `_check()`, never bare `assert()`. A failed assert in a
headless `SceneTree` script halts the script but leaves the tree running, so the
process spins forever at 100% CPU instead of failing — it looks exactly like a
slow test. That cost 53 minutes of wall clock to spot once; the stage lines and
`_check()` exist so it can't happen twice.
Only one Godot instance may touch the project at a time: a second contends for
the `.godot` import lock and can kill the first mid-run.
Visual check (opens a window, saves a PNG): Visual check (opens a window, saves a PNG):
``` ```

View File

@ -2,445 +2,445 @@
{ {
"name": "Alice x George", "name": "Alice x George",
"spawn": { "spawn": {
"x": -165.3192678228276, "dx": 0.766833198312044,
"z": 159.9955423589618, "dz": -0.641846434878719,
"dx": 0.7668331983120437, "x": -163.586282448655,
"dz": -0.6418464348787193 "z": 162.065991994404
}, },
"streams": [ "streams": [
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-71.62300756706763, -71.6230075670676,
85.0918821008208 85.0918821008208
], ],
[ [
-72.10279819575109, -72.1027981957511,
85.49061753866586 85.4906175386659
], ],
[ [
-82.55345192912239, -82.5534519291224,
94.80588029839768 94.8058802983977
], ],
[ [
-104.44928325520195, -104.449283255202,
113.36472803055571 113.364728030556
], ],
[ [
-114.55295338424757, -114.552953384248,
122.93815788447793 122.938157884478
], ],
[ [
-118.63551709634598, -118.635517096346,
126.33214688818488 126.332146888185
], ],
[ [
-124.17972594270637, -124.179725942706,
130.60060399325408 130.600603993254
], ],
[ [
-132.4126578466066, -132.412657846607,
136.84137198262476 136.841371982625
], ],
[ [
-135.42619497476394, -135.426194974764,
139.13115862719584 139.131158627196
], ],
[ [
-137.0173915026139, -137.017391502614,
140.32992242527928 140.329922425279
], ],
[ [
-142.22691046279974, -142.2269104628,
144.18129435873087 144.181294358731
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-75.361941989609, -75.361941989609,
84.82292365250544 84.8229236525054
], ],
[ [
-80.93953886827424, -80.9395388682742,
78.61163770120406 78.6116377012041
], ],
[ [
-82.56599989409156, -82.5659998940916,
76.7348960854059 76.7348960854059
], ],
[ [
-115.40558143561937, -115.405581435619,
38.74155522137386 38.7415552213739
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-145.4370805808313, -145.437080580831,
139.83908204087984 139.83908204088
], ],
[ [
-140.2367304705485, -140.236730470549,
135.99450357474848 135.994503574748
], ],
[ [
-138.6871885076824, -138.687188507682,
134.82698377267795 134.826983772678
], ],
[ [
-135.67603860636424, -135.676038606364,
132.53900681717874 132.539006817179
], ],
[ [
-127.45466133363814, -127.454661333638,
126.30702760692736 126.307027606927
], ],
[ [
-121.99640893818653, -121.996408938187,
122.1055163120108 122.105516312011
], ],
[ [
-118.19749682812089, -118.197496828121,
118.9535245154313 118.953524515431
], ],
[ [
-108.01476176313997, -108.01476176314,
109.30919316947609 109.309193169476
], ],
[ [
-86.07852578965569, -86.0785257896557,
90.71517690194068 90.7151769019407
], ],
[ [
-75.68968831102165, -75.6896883110217,
81.45400766143295 81.454007661433
], ],
[ [
-75.08305996358739, -75.0830599635874,
80.94603629889595 80.9460362988959
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-111.32018174165945, -111.320181741659,
35.21033597859207 35.2103359785921
], ],
[ [
-78.48079808538708, -78.4807980853871,
73.20344791473178 73.2034479147318
], ],
[ [
-76.9072614072839, -76.9072614072839,
75.01987789888024 75.0198778988802
], ],
[ [
-71.34412554104603, -71.344125541046,
81.2149947472113 81.2149947472113
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-72.11668883510822, -72.1166888351082,
80.61865688274891 80.6186568827489
], ],
[ [
-63.31551687082244, -63.3155168708224,
85.23196646473183 85.2319664647318
], ],
[ [
-54.55178175870453, -54.5517817587045,
95.53822905343011 95.5382290534301
], ],
[ [
-39.78320194928109, -39.7832019492811,
112.96784568335697 112.967845683357
], ],
[ [
-38.24953472930413, -38.2495347293041,
114.64142478239386 114.641424782394
], ],
[ [
-37.466790819459995, -37.46679081946,
115.77089209241056 115.770892092411
], ],
[ [
-36.90754547102499, -36.907545471025,
116.86830840435711 116.868308404357
], ],
[ [
-36.64154284861633, -36.6415428486163,
117.96012844030032 117.9601284403
], ],
[ [
-36.54962586770791, -36.5496258677079,
118.92829018795193 118.928290187952
], ],
[ [
-36.58380403095183, -36.5838040309518,
120.63163096695364 120.631630966954
], ],
[ [
-36.733516672801336, -36.7335166728013,
121.77324800253669 121.773248002537
], ],
[ [
-36.949600973076684, -36.9496009730767,
122.55506784741175 122.555067847412
], ],
[ [
-37.31118692587169, -37.3111869258717,
123.40422578212599 123.404225782126
], ],
[ [
-38.02064964168787, -38.0206496416879,
124.38554265247478 124.385542652475
], ],
[ [
-39.45793344555888, -39.4579334455589,
125.80100694689808 125.801006946898
], ],
[ [
-41.96015977939887, -41.9601597793989,
127.8781767661959 127.878176766196
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-45.40767874247836, -45.4076787424784,
123.72190283402932 123.721902834029
], ],
[ [
-43.03089623055088, -43.0308962305509,
121.75206425317394 121.752064253174
], ],
[ [
-41.9792929338678, -41.9792929338678,
120.7127857471952 120.712785747195
], ],
[ [
-41.99739811738572, -41.9973981173857,
120.72105141795794 120.721051417958
], ],
[ [
-42.06268798731611, -42.0626879873161,
120.81830615252781 120.818306152528
], ],
[ [
-42.041735423545425, -42.0417354235454,
120.78187839726885 120.781878397269
], ],
[ [
-41.974164266802894, -41.9741642668029,
120.30911503284231 120.309115032842
], ],
[ [
-41.94908321684239, -41.9490832168424,
119.00484301205215 119.004843012052
], ],
[ [
-41.975684667956976, -41.975684667957,
118.80092035936316 118.800920359363
], ],
[ [
-41.94671891520851, -41.9467189152085,
118.80911519521383 118.809115195214
], ],
[ [
-42.0788310934576, -42.0788310934576,
118.57964350736775 118.579643507368
], ],
[ [
-42.38250615411705, -42.3825061541171,
118.1168452176333 118.116845217633
], ],
[ [
-43.89081206390128, -43.8908120639013,
116.47320431640294 116.473204316403
], ],
[ [
-58.67282832403665, -58.6728283240367,
99.02778134654227 99.0277813465423
], ],
[ [
-66.81772305118318, -66.8177230511832,
89.3422647349603 89.3422647349603
], ],
[ [
-74.5893786955468, -74.5893786955468,
85.41926151696784 85.4192615169678
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
} }
], ],
"targets": [ "targets": [
15000, 26500,
35000, 29000,
60000 46500
] ]
}, },
{ {
"name": "Margaret x Edward", "name": "Margaret x Edward",
"spawn": { "spawn": {
"x": 276.7158840463856, "dx": -0.742705793125526,
"z": -371.11587218595514, "dz": 0.669617879732749,
"dx": -0.7427057931255263, "x": 274.907915771107,
"dz": 0.6696178797327494 "z": -373.121177827394
}, },
"streams": [ "streams": [
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
185.8338152967176, 185.833815296718,
-292.8126451679154 -292.812645167915
], ],
[ [
193.65593395098287, 193.655933950983,
-299.88251164434115 -299.882511644341
], ],
[ [
211.37786867540518, 211.377868675405,
-315.2307257048046 -315.230725704805
], ],
[ [
216.02310568686988, 216.02310568687,
-319.25459820267537 -319.254598202675
], ],
[ [
237.6429961947087, 237.642996194709,
-338.58229333857753 -338.582293338578
], ],
[ [
239.66099718191472, 239.660997181915,
-341.2883463335457 -341.288346333546
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
179.81812157632743, 179.818121576327,
-304.16623584225226 -304.166235842252
], ],
[ [
181.35983927566346, 181.359839275663,
-302.4069925620872 -302.406992562087
], ],
[ [
184.2133034529848, 184.213303452985,
-299.1448137854387 -299.144813785439
], ],
[ [
189.71555797124375, 189.715557971244,
-292.5416508365839 -292.541650836584
], ],
[ [
194.9234531376747, 194.923453137675,
-286.3366793395667 -286.336679339567
], ],
[ [
234.05675616721896, 234.056756167219,
-241.1315253602194 -241.131525360219
], ],
[ [
244.50993125963066, 244.509931259631,
-229.32934036140196 -229.329340361402
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
243.95347049022743, 243.953470490227,
-338.01196526635846 -338.011965266358
], ],
[ [
241.32949950132615, 241.329499501326,
-334.63644826175323 -334.636448261753
], ],
[ [
219.61114951437548, 219.611149514375,
-315.21901379742513 -315.219013797425
], ],
[ [
214.91318335480702, 214.913183354807,
-311.1488694949895 -311.14886949499
], ],
[ [
197.21785955435436, 197.217859554354,
-295.8238559560563 -295.823855956056
], ],
[ [
189.45480420951895, 189.454804209519,
-288.8065948320647 -288.806594832065
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
240.4674984004257, 240.467498400426,
-225.74901403845038 -225.74901403845
], ],
[ [
229.982416914263, 229.982416914263,
-237.5875502401286 -237.587550240129
], ],
[ [
190.83429465784906, 190.834294657849,
-282.80981346079136 -282.809813460791
], ],
[ [
185.5730615349928, 185.573061534993,
-289.07758916339617 -289.077589163396
], ],
[ [
180.09260788812207, 180.092607888122,
-295.6548470145767 -295.654847014577
], ],
[ [
177.29669340310514, 177.296693403105,
-298.8501898379666 -298.850189837967
], ],
[ [
175.7569318305437, 175.756931830544,
-300.6071997580377 -300.607199758038
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
} }
], ],
"targets": [ "targets": [
15000, 22500,
35000, 25000,
60000 30000
] ]
} }
] ]

View File

@ -2,149 +2,149 @@
{ {
"name": "Cliffs Corner", "name": "Cliffs Corner",
"spawn": { "spawn": {
"x": 19.82910866163153, "dx": 0.711628947630267,
"z": -91.88863639399733, "dz": -0.702555507340622,
"dx": 0.7116289476302671, "x": 21.7260085314512,
"dz": -0.7025555073406219 "z": -89.9672382353956
}, },
"streams": [ "streams": [
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
63.92619388342862, 63.9261938834286,
-109.98937518013152 -109.989375180132
], ],
[ [
78.3750416498091, 78.3750416498091,
-148.8340213803462 -148.834021380346
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
106.13660245700423, 106.136602457004,
-179.68219050814878 -179.682190508149
], ],
[ [
105.14898470103478, 105.148984701035,
-213.87167130817437 -213.871671308174
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
83.43625143590378, 83.4362514359038,
-146.95142862004474 -146.951428620045
], ],
[ [
68.98740366952329, 68.9874036695233,
-108.10678241983003 -108.10678241983
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
110.54673313420321, 110.546733134203,
-214.02759389225906 -214.027593892259
], ],
[ [
111.53435089017266, 111.534350890173,
-179.83811309223347 -179.838113092233
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
110.03793689684629, 110.037936896846,
-168.49583563849748 -168.495835638497
], ],
[ [
105.07701815835642, 105.077018158356,
-166.64105720795808 -166.641057207958
], ],
[ [
102.76621908994164, 102.766219089942,
-165.6886852292976 -165.688685229298
], ],
[ [
100.0562323833477, 100.056232383348,
-163.76233037299872 -163.762330372999
], ],
[ [
96.9873892973125, 96.9873892973125,
-160.78656603278262 -160.786566032783
], ],
[ [
94.50499850150788, 94.5049985015079,
-158.03413164414619 -158.034131644146
], ],
[ [
91.4342291831665, 91.4342291831665,
-153.71805517412884 -153.718055174129
], ],
[ [
82.70848350683406, 82.7084835068341,
-145.88280488205245 -145.882804882052
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
79.10280957887883, 79.1028095788788,
-149.90264511833848 -149.902645118338
], ],
[ [
87.56161285248508, 87.5616128524851,
-157.4814104264721 -157.481410426472
], ],
[ [
90.25853122720883, 90.2585312272088,
-161.369924756482 -161.369924756482
], ],
[ [
93.10927630970947, 93.1092763097095,
-164.5442567671812 -164.544256767181
], ],
[ [
96.57846276532892, 96.5784627653289,
-167.89332522702423 -167.893325227024
], ],
[ [
100.07071556655998, 100.07071556656,
-170.36781557108517 -170.367815571085
], ],
[ [
103.11280473039093, 103.112804730391,
-171.67115319207213 -171.671153192072
], ],
[ [
108.14657768085227, 108.146577680852,
-173.5537759619962 -173.553775961996
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
} }
], ],
"targets": [ "targets": [
15000, 4000,
35000, 6500,
60000 10500
] ]
} }
] ]

View File

@ -2,397 +2,397 @@
{ {
"name": "Albert x Adelaide", "name": "Albert x Adelaide",
"spawn": { "spawn": {
"x": 18.671705882497893, "dx": -0.663386853147646,
"z": -22.919507778110138, "dz": -0.748276608662107,
"dx": -0.6633868531476461, "x": 20.6920527258856,
"dz": -0.7482766086621067 "z": -24.7106522816088
}, },
"streams": [ "streams": [
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-58.84614846630014, -58.8461484663001,
-114.42417420924829 -114.424174209248
], ],
[ [
-53.880474905008, -53.880474905008,
-108.39185473942744 -108.391854739427
], ],
[ [
-51.24051503498836, -51.2405150349884,
-105.52578654474546 -105.525786544745
], ],
[ [
-20.352984240690695, -20.3529842406907,
-70.76962163514554 -70.7696216351455
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-86.70325250389301, -86.703252503893,
-94.08771386994844 -94.0877138699484
], ],
[ [
-77.60701968874399, -77.607019688744,
-101.92094169090129 -101.920941690901
], ],
[ [
-72.06522503228508, -72.0652250322851,
-106.94786296530025 -106.9478629653
], ],
[ [
-68.79209061830386, -68.7920906183039,
-109.50838129624599 -109.508381296246
], ],
[ [
-62.692661313561906, -62.6926613135619,
-114.75385541597699 -114.753855415977
], ],
[ [
-56.45081914916183, -56.4508191491618,
-120.13849830634709 -120.138498306347
], ],
[ [
-53.14418135326541, -53.1441813532654,
-122.9809049049611 -122.980904904961
], ],
[ [
-38.75486932340002, -38.7548693234,
-135.5677577748611 -135.567757774861
], ],
[ [
-8.138880164463979, -8.13888016446398,
-163.05430391717795 -163.054303917178
], ],
[ [
7.537426213222782, 7.53742621322278,
-176.88629254786764 -176.886292547868
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-24.38938905950134, -24.3893890595013,
-67.18250076477023 -67.1825007647702
], ],
[ [
-55.272013374374126, -55.2720133743741,
-101.93315225504524 -101.933152255045
], ],
[ [
-57.98533525129133, -57.9853352512913,
-104.88327646076375 -104.883276460764
], ],
[ [
-63.01508813331892, -63.0150881333189,
-110.99198219061685 -110.991982190617
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
11.110167779562063, 11.1101677795621,
-172.83715465195058 -172.837154651951
], ],
[ [
-4.543064055336218, -4.54306405533622,
-159.02564328250827 -159.025643282508
], ],
[ [
-35.16387720923361, -35.1638772092336,
-131.5347966250365 -131.534796625037
], ],
[ [
-49.59536988091847, -49.5953698809185,
-118.91077749494814 -118.910777494948
], ],
[ [
-52.92601130212681, -52.9260113021268,
-116.04756569366813 -116.047565693668
], ],
[ [
-59.168575286057155, -59.1685752860572,
-110.66230098388816 -110.662300983888
], ],
[ [
-65.33626025215173, -65.3362602521517,
-105.35901550369637 -105.359015503696
], ],
[ [
-68.5423745958537, -68.5423745958537,
-102.85524463438601 -102.855244634386
], ],
[ [
-74.0429581637501, -74.0429581637501,
-97.86416150877923 -97.8641615087792
], ],
[ [
-83.17948939242227, -83.1794893924223,
-89.9958813300908 -89.9958813300908
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-63.049013950748005, -63.049013950748,
-111.03404120330288 -111.034041203303
], ],
[ [
-67.67311197746825, -67.6731119774683,
-116.88556835863362 -116.885568358634
], ],
[ [
-69.33640432781439, -69.3364043278144,
-119.01651536179543 -119.016515361795
], ],
[ [
-72.74965354025018, -72.7496535402502,
-122.55658461736515 -122.556584617365
], ],
[ [
-98.24408864239251, -98.2440886423925,
-142.51997682349207 -142.519976823492
], ],
[ [
-106.03262882232805, -106.032628822328,
-149.46281622691504 -149.462816226915
], ],
[ [
-127.2548410984026, -127.254841098403,
-167.5083127878196 -167.50831278782
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-123.7567869560363, -123.756786956036,
-171.62214521234466 -171.622145212345
], ],
[ [
-102.50831375382124, -102.508313753821,
-153.55417337313145 -153.554173373131
], ],
[ [
-94.84937670776534, -94.8493767077653,
-146.71949237661244 -146.719492376612
], ],
[ [
-69.3394816295263, -69.3394816295263,
-126.74355578269574 -126.743555782696
], ],
[ [
-65.32529933336386, -65.3252993333639,
-122.63190423762802 -122.631904237628
], ],
[ [
-63.432906391639634, -63.4329063916396,
-120.22931724123647 -120.229317241236
], ],
[ [
-58.81222264887106, -58.8122226488711,
-114.38211519656227 -114.382115196562
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
} }
], ],
"targets": [ "targets": [
15000, 23000,
35000, 25500,
60000 29500
] ]
}, },
{ {
"name": "Edward x Elizabeth", "name": "Edward x Elizabeth",
"spawn": { "spawn": {
"x": 173.87950117253465,
"z": -177.50987452854054,
"dx": 0.688388502507091, "dx": 0.688388502507091,
"dz": 0.7253421741606128 "dz": 0.725342174160613,
"x": 171.921077302301,
"z": -175.651225571771
}, },
"streams": [ "streams": [
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
228.7426016851313, 228.742601685131,
-123.80938841141814 -123.809388411418
], ],
[ [
250.48785179439338, 250.487851794393,
-101.12418691157934 -101.124186911579
], ],
[ [
253.19184475779528, 253.191844757795,
-98.13216139604938 -98.1321613960494
], ],
[ [
258.48528328991137, 258.485283289911,
-92.28343983096748 -92.2834398309675
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
184.8196819904455, 184.819681990446,
-31.59973983603264 -31.5997398360326
], ],
[ [
200.9901724381037, 200.990172438104,
-45.56696118289086 -45.5669611828909
], ],
[ [
206.29822476676847, 206.298224766768,
-50.115127103271014 -50.115127103271
], ],
[ [
208.01277161716473, 208.012771617165,
-51.59585061763732 -51.5958506176373
], ],
[ [
243.56749157860247, 243.567491578602,
-82.55471207644285 -82.5547120764429
], ],
[ [
246.1313684904348, 246.131368490435,
-84.84463727526342 -84.8446372752634
], ],
[ [
254.68470539632878, 254.684705396329,
-92.48524564052305 -92.485245640523
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
254.4815819963581, 254.481581996358,
-88.65985376851496 -88.659853768515
], ],
[ [
249.1869798707451, 249.186979870745,
-94.50986140343801 -94.509861403438
], ],
[ [
246.5771986992584, 246.577198699258,
-97.40037268829819 -97.4003726882982
], ],
[ [
224.8443191668579, 224.844319166858,
-120.07262598818004 -120.07262598818
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
258.28215988994066, 258.282159889941,
-88.4580479589594 -88.4580479589594
], ],
[ [
249.72869976275985, 249.72869976276,
-80.81732952477397 -80.817329524774
], ],
[ [
247.11707918748664, 247.117079187487,
-78.48526152300741 -78.4852615230074
], ],
[ [
211.55809324014456, 211.558093240145,
-47.52268298180012 -47.5226829818001
], ],
[ [
209.81572383420533, 209.815723834205,
-46.017908496633005 -46.017908496633
], ],
[ [
204.51598169911696, 204.515981699117,
-41.47689161686228 -41.4768916168623
], ],
[ [
188.34948976520272, 188.349489765203,
-27.51312056415722 -27.5131205641572
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
258.4805413787254, 258.480541378725,
-92.28866542876725 -92.2886654287672
], ],
[ [
262.2737122591504, 262.27371225915,
-88.11954201221562 -88.1195420122156
], ],
[ [
266.8273793037693, 266.827379303769,
-83.1100839184909 -83.1100839184909
], ],
[ [
270.87333374760516, 270.873333747605,
-78.65784777138674 -78.6578477713867
], ],
[ [
298.08928934155523, 298.089289341555,
-47.30427629341134 -47.3042762934113
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
254.70925209424783, 254.709252094248,
-92.50690682734246 -92.5069068273425
], ],
[ [
259.70303711688206, 259.703037116882,
-96.8600914480509 -96.8600914480509
], ],
[ [
263.66545095997486, 263.665450959975,
-100.3447248693 -100.3447248693
], ],
[ [
288.61557906385735, 288.615579063857,
-122.1176793727558 -122.117679372756
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
} }
], ],
"targets": [ "targets": [
15000, 22000,
35000, 24500,
60000 28500
] ]
} }
] ]

View File

@ -2,345 +2,345 @@
{ {
"name": "Melbourne x Merivale", "name": "Melbourne x Merivale",
"spawn": { "spawn": {
"x": -598.2786454342968, "dx": 0.852877329272599,
"z": -212.65545062278278, "dz": -0.522111349438832,
"dx": 0.8528773292725991, "x": -596.868944790812,
"dz": -0.5221113494388324 "z": -210.352681833747
}, },
"streams": [ "streams": [
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-522.2431469994345, -522.243146999435,
-263.2916099068527 -263.291609906853
], ],
[ [
-513.2984743659174, -513.298474365917,
-268.5646201058227 -268.564620105823
], ],
[ [
-505.76645618454586, -505.766456184546,
-272.8477143314658 -272.847714331466
], ],
[ [
-497.90899041561073, -497.908990415611,
-277.2629244179048 -277.262924417905
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-518.3319604245614, -518.331960424561,
-316.20816625786284 -316.208166257863
], ],
[ [
-502.53998920863535, -502.539989208635,
-289.11772214349674 -289.117722143497
], ],
[ [
-501.0310720126822, -501.031072012682,
-286.5339989119062 -286.533998911906
], ],
[ [
-499.3074920997309, -499.307492099731,
-283.76972490400925 -283.769724904009
], ],
[ [
-498.93054530357944, -498.930545303579,
-283.2413778417831 -283.241377841783
], ],
[ [
-494.34501447411924, -494.345014474119,
-276.414559193545 -276.414559193545
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-495.26368453007734, -495.263684530077,
-272.55523318206934 -272.555233182069
], ],
[ [
-503.1094123444767, -503.109412344477,
-268.14663806831595 -268.146638068316
], ],
[ [
-510.58925218160783, -510.589252181608,
-263.8934194939837 -263.893419493984
], ],
[ [
-519.5007896114952, -519.500789611495,
-258.6397848932893 -258.639784893289
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-498.82766047156883, -498.827660471569,
-273.4035984064291 -273.403598406429
], ],
[ [
-503.4072640108861, -503.407264010886,
-280.2216113581537 -280.221611358154
], ],
[ [
-503.85991989590116, -503.859919895901,
-280.8653486954825 -280.865348695483
], ],
[ [
-505.6522751490968, -505.652275149097,
-283.7403486882755 -283.740348688276
], ],
[ [
-507.20498688872703, -507.204986888727,
-286.3978330566516 -286.397833056652
], ],
[ [
-522.997174842978, -522.997174842978,
-313.4886489421985 -313.488648942198
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-497.7097209821479, -497.709720982148,
-277.3642792991366 -277.364279299137
], ],
[ [
-489.2653413897242, -489.265341389724,
-281.21700470668776 -281.217004706688
], ],
[ [
-470.16395422466655, -470.163954224667,
-292.9741741951012 -292.974174195101
], ],
[ [
-453.3973200149641, -453.397320014964,
-303.3696498434199 -303.36964984342
], ],
[ [
-438.7171383481014, -438.717138348101,
-313.0237718470059 -313.023771847006
], ],
[ [
-428.17568968279613, -428.175689682796,
-319.6952218182481 -319.695221818248
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-490.9127030755138, -490.912703075514,
-271.2416907037699 -271.24169070377
], ],
[ [
-487.07948135301893, -487.079481353019,
-265.2321814476218 -265.232181447622
], ],
[ [
-460.79611403958603, -460.796114039586,
-221.7057389459239 -221.705738945924
], ],
[ [
-449.78766148749827, -449.787661487498,
-203.62165684766288 -203.621656847663
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
} }
], ],
"targets": [ "targets": [
15000, 35500,
35000, 38000,
60000 73000
] ]
}, },
{ {
"name": "Grey x Glenelg", "name": "Grey x Glenelg",
"spawn": { "spawn": {
"x": -135.06485953132193, "dx": 0.5279471843098,
"z": -97.50127625771249, "dz": 0.849277204792024,
"dx": 0.5279471843098005, "x": -137.35790798426,
"dz": 0.8492772047920241 "z": -96.075818860076
}, },
"streams": [ "streams": [
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-66.8941396578206, -66.8941396578206,
18.021454924938546 18.0214549249385
], ],
[ [
-68.93721227192415, -68.9372122719242,
14.729250272207434 14.7292502722074
], ],
[ [
-74.03417645108553, -74.0341764510855,
5.788135121643277 5.78813512164328
], ],
[ [
-78.66584427851572, -78.6658442785157,
-1.692678191469608 -1.69267819146961
], ],
[ [
-82.82069253186671, -82.8206925318667,
-8.344352365976752 -8.34435236597675
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-33.05020815528413, -33.0502081552841,
-14.758620186231095 -14.7586201862311
], ],
[ [
-35.06751528318885, -35.0675152831888,
-14.599409411489315 -14.5994094114893
], ],
[ [
-37.27001626186296, -37.270016261863,
-13.996146050544787 -13.9961460505448
], ],
[ [
-43.35852481930847, -43.3585248193085,
-10.760668273887504 -10.7606682738875
], ],
[ [
-53.694918113870564, -53.6949181138706,
-4.204520462618362 -4.20452046261836
], ],
[ [
-56.331462588402815, -56.3314625884028,
-2.4702458690280507 -2.47024586902805
], ],
[ [
-63.091151948462084, -63.0911519484621,
2.2185465904455017 2.2185465904455
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-78.24074203456223, -78.2407420345622,
-11.205130833848836 -11.2051308338488
], ],
[ [
-74.07981104388904, -74.079811043889,
-4.543695408341438 -4.54369540834144
], ],
[ [
-69.38832494823436, -69.3883249482344,
3.0356700785490762 3.03567007854908
], ],
[ [
-64.27327518677029, -64.2732751867703,
12.007542928328153 12.0075429283282
], ],
[ [
-62.30660151137585, -62.3066015113759,
15.172859875635417 15.1728598756354
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-66.1688465571084, -66.1688465571084,
-2.2185465904455017 -2.2185465904455
], ],
[ [
-59.37835881390333, -59.3783588139033,
-6.9285441308125515 -6.92854413081255
], ],
[ [
-56.602733425687326, -56.6027334256873,
-8.754752337189586 -8.75475233718959
], ],
[ [
-46.12004993919494, -46.1200499391949,
-15.401140126214159 -15.4011401262142
], ],
[ [
-39.50773651812935, -39.5077365181293,
-18.910676349026538 -18.9106763490265
], ],
[ [
-36.1005431869604, -36.1005431869604,
-19.899678588618844 -19.8996785886188
], ],
[ [
-33.51553068408273, -33.5155306840827,
-20.138534213814854 -20.1385342138149
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-62.42866919418658, -62.4286691941866,
-1.5633764655737972 -1.5633764655738
], ],
[ [
-56.22534149367183, -56.2253414936718,
7.176315693408943 7.17631569340894
], ],
[ [
-31.608294574960304, -31.6082945749603,
46.399012606383145 46.3990126063831
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
-105.44415325837058, -105.444153258371,
17.29338138921854 17.2933813892185
], ],
[ [
-124.85549758561747, -124.855497585617,
29.02803771609806 29.0280377160981
], ],
[ [
-145.9651989732041, -145.965198973204,
41.680234308480806 41.6802343084808
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
} }
], ],
"targets": [ "targets": [
15000, 22500,
35000, 25000,
60000 29000
] ]
} }
] ]

View File

@ -2,185 +2,185 @@
{ {
"name": "Bridge Approach", "name": "Bridge Approach",
"spawn": { "spawn": {
"x": 32.83372074498513, "dx": -0.114095858645717,
"z": -118.28842427027045, "dz": -0.993469745407426,
"dx": -0.11409585864571734, "x": 35.5160890575852,
"dz": -0.9934697454074263 "z": -118.596483088614
}, },
"streams": [ "streams": [
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
21.82446567810751, 21.8244656781075,
-237.81387509878263 -237.813875098783
], ],
[ [
23.145720027383163, 23.1457200273832,
-226.45520770652828 -226.455207706528
], ],
[ [
24.788209612143817, 24.7882096121438,
-213.84815371354867 -213.848153713549
], ],
[ [
26.145569174952232, 26.1455691749522,
-200.29741976993301 -200.297419769933
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
2.199941588527042, 2.19994158852704,
-240.32717119002737 -240.327171190027
], ],
[ [
-2.5248172223755736, -2.52481722237557,
-243.91950536774928 -243.919505367749
], ],
[ [
-6.325349530807717, -6.32534953080772,
-247.60965512377 -247.60965512377
], ],
[ [
-15.183983237537262, -15.1839832375373,
-255.2613583327868 -255.261358332787
], ],
[ [
-19.822722086570074, -19.8227220865701,
-258.6729952966697 -258.67299529667
], ],
[ [
-24.279515332983824, -24.2795153329838,
-261.70335578638884 -261.703355786389
], ],
[ [
-29.011437974400625, -29.0114379744006,
-263.89076106496833 -263.890761064968
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
20.772447151780117, 20.7724471517801,
-199.75931223039953 -199.7593122304
], ],
[ [
19.423377981138138, 19.4233779811381,
-213.23286388675078 -213.232863886751
], ],
[ [
17.78654515972297, 17.786545159723,
-225.7924522932427 -225.792452293243
], ],
[ [
16.46063564037367, 16.4606356403737,
-237.18991410136036 -237.18991410136
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.8,
"pts": [ "pts": [
[ [
-26.737042902514784, -26.7370429025148,
-268.7884265350654 -268.788426535065
], ],
[ [
-21.61124337794858, -21.6112433779486,
-266.3980682135746 -266.398068213575
], ],
[ [
-16.704188313209045, -16.704188313209,
-263.0814811029762 -263.081481102976
], ],
[ [
-11.761774350471743, -11.7617743504717,
-259.43849686691397 -259.438496866914
], ],
[ [
-2.7224195143774796, -2.72241951437748,
-251.63195487598963 -251.63195487599
], ],
[ [
0.9839307874462617, 0.983930787446262,
-248.02422063236523 -248.024220632365
], ],
[ [
5.4649806575202335, 5.46498065752023,
-244.6282780101317 -244.628278010132
] ]
], ],
"speed": 11.0, "speed": 11.0
"interval": 1.8
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
11.27070084290225, 11.2707008429023,
-197.84784324166512 -197.847843241665
], ],
[ [
10.896175804718348, 10.8961758047183,
-204.76641770228525 -204.766417702285
], ],
[ [
10.476477879675205, 10.4764778796752,
-211.20975788808624 -211.209757888086
], ],
[ [
9.92304078347784, 9.92304078347784,
-216.20700696593718 -216.207006965937
], ],
[ [
8.932958301853615, 8.93295830185362,
-221.62531766816238 -221.625317668162
], ],
[ [
7.508738699199866, 7.50873869919987,
-226.8653717079938 -226.865371707994
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
}, },
{ {
"interval": 1.5,
"pts": [ "pts": [
[ [
28.875188928696993, 28.875188928697,
-229.49242546244793 -229.492425462448
], ],
[ [
28.72548025209394, 28.7254802520939,
-214.05366159277472 -214.053661592775
], ],
[ [
28.150874632761848, 28.1508746327618,
-209.45956029627345 -209.459560296273
], ],
[ [
27.279147353059784, 27.2791473530598,
-204.7812989955361 -204.781298995536
], ],
[ [
26.094879529030933, 26.0948795290309,
-199.44340263065618 -199.443402630656
] ]
], ],
"speed": 12.0, "speed": 12.0
"interval": 1.5
} }
], ],
"targets": [ "targets": [
15000, 5000,
35000, 7500,
60000 11500
] ]
} }
] ]

View File

@ -1,13 +1,74 @@
[ [
{ {
"name": "Trolley Run", "name": "Trolley Run",
"spawn": {"x": 33.0, "z": 52.0, "dx": 0.0, "dz": -1.0}, "spawn": {
"dx": 0.0,
"dz": -1.0,
"x": 33.0,
"z": 52.0
},
"streams": [ "streams": [
{"pts": [[-70.0, 15.0], [70.0, 15.0]], "speed": 11.0, "interval": 2.0}, {
{"pts": [[70.0, 12.0], [-70.0, 12.0]], "speed": 12.0, "interval": 2.4}, "interval": 2.0,
{"pts": [[-70.0, -21.0], [70.0, -21.0]], "speed": 10.0, "interval": 2.2}, "pts": [
{"pts": [[70.0, -24.0], [-70.0, -24.0]], "speed": 12.0, "interval": 2.8} [
-70.0,
15.0
],
[
70.0,
15.0
]
],
"speed": 11.0
},
{
"interval": 2.4,
"pts": [
[
70.0,
12.0
],
[
-70.0,
12.0
]
],
"speed": 12.0
},
{
"interval": 2.2,
"pts": [
[
-70.0,
-21.0
],
[
70.0,
-21.0
]
],
"speed": 10.0
},
{
"interval": 2.8,
"pts": [
[
70.0,
-24.0
],
[
-70.0,
-24.0
]
],
"speed": 12.0
}
], ],
"targets": [8000, 20000, 40000] "targets": [
12500,
15000,
46000
]
} }
] ]

View File

@ -16,6 +16,10 @@ extends RefCounted
## ##
## ponytail: normals are left alone. Recomputing them per impact costs more than ## ponytail: normals are left alone. Recomputing them per impact costs more than
## it buys at this crumple scale; revisit if the shading reads flat. ## it buys at this crumple scale; revisit if the shading reads flat.
## ponytail: _write() rebuilds a whole ArrayMesh via add_surface_from_arrays(),
## which takes no LOD or shadow-mesh argument -- a deformable car therefore loses
## any LODs its import generated. Harmless for the procedural fleet (no LODs to
## lose) but worth knowing before wiring the deformer to a dense imported model.
const ALPHA := 2.0 # distance falloff exponent; PDF suggests 1.0-3.0 const ALPHA := 2.0 # distance falloff exponent; PDF suggests 1.0-3.0
const NEAR := 4 # control points blended per vertex const NEAR := 4 # control points blended per vertex
@ -34,6 +38,7 @@ var _meshes: Array = [] # one entry per MeshInstance3D, all its surfaces toget
var _cp := PackedVector3Array() var _cp := PackedVector3Array()
var _disp := PackedVector3Array() var _disp := PackedVector3Array()
var _ok := false var _ok := false
var _root: Node3D = null # the car model; panels reparented away stop deforming
var _skins: Array = [] # {mat, albedo, rough}: per-car material copies to dirty up var _skins: Array = [] # {mat, albedo, rough}: per-car material copies to dirty up
var damage := 0.0 # 0..1, drives the paint getting scratched and dulled var damage := 0.0 # 0..1, drives the paint getting scratched and dulled
@ -126,6 +131,7 @@ func setup(root: Node3D) -> bool:
(m["mi"] as MeshInstance3D).mesh = copy (m["mi"] as MeshInstance3D).mesh = copy
m["mesh"] = copy m["mesh"] = copy
_meshes.append(m) _meshes.append(m)
_root = root
_ok = true _ok = true
_write() _write()
return true return true
@ -198,6 +204,12 @@ func _wear() -> void:
m.detail_enabled = damage > 0.35 m.detail_enabled = damage > 0.35
func _write() -> void: func _write() -> void:
# car.gd reparents det_* panels onto their own RigidBody when shed and frees
# them seconds later; left in the list they'd be debris still being crumpled
# by a car they've come off, and eventually freed nodes being written to
if is_instance_valid(_root):
_meshes = _meshes.filter(func(m) -> bool:
return is_instance_valid(m["mi"]) and _root.is_ancestor_of(m["mi"]))
for m in _meshes: for m in _meshes:
var mesh: ArrayMesh = m["mesh"] var mesh: ArrayMesh = m["mesh"]
var inv: Transform3D = (m["xform"] as Transform3D).affine_inverse() var inv: Transform3D = (m["xform"] as Transform3D).affine_inverse()

View File

@ -269,11 +269,16 @@ func _ready() -> void:
add_child(path) add_child(path)
var L := curve.get_baked_length() var L := curve.get_baked_length()
var headway: float = stream["speed"] * stream["interval"] var headway: float = stream["speed"] * stream["interval"]
var n: int = clampi(int(L / headway), 1, 14) # At least 3 per stream, spaced to fit. int(L / headway) floors to 1
# on a short clipped stream, which is how Grey x Glenelg ended up
# with 9 convoy cars against the usual 20-25 and gaps wide enough to
# drive clean through -- it scored nothing in 12 of 12 tuning runs.
var n: int = clampi(int(L / headway), 3, 14)
var spacing := L / float(n)
for i in n: for i in n:
var t := TrafficCar.new() var t := TrafficCar.new()
t.path = path t.path = path
t.offset = fposmod(i * headway, L) t.offset = fposmod(i * spacing, L)
t.speed = stream["speed"] t.speed = stream["speed"]
t.model_idx = midx t.model_idx = midx
midx += 1 midx += 1

View File

@ -87,7 +87,14 @@ def launch_point(pts, jpt):
end = [end[0] + dx / L * grow, end[1] + dz / L * grow] end = [end[0] + dx / L * grow, end[1] + dz / L * grow]
dx, dz = jpt[0] - end[0], jpt[1] - end[1] dx, dz = jpt[0] - end[0], jpt[1] - end[1]
L = math.hypot(dx, dz) or 1.0 L = math.hypot(dx, dz) or 1.0
return {"x": end[0], "z": end[1], "dx": dx / L, "dz": dz / L} dx, dz = dx / L, dz / L
# Sit in a lane, not on the centreline. Convoys are offset +/-LANE either
# side, so a centreline launch threads straight between them -- Grey x
# Glenelg passed within 2.9 m of a convoy car and never touched one,
# scoring nothing in 12 of 12 tuning runs. Same transform as offset().
# sign matters: offsetting the other way moved the launch AWAY from the
# convoy lane and widened Grey x Glenelg's closest pass from 2.9 m to 5.5 m
return {"x": end[0] - dz * LANE, "z": end[1] + dx * LANE, "dx": dx, "dz": dz}
events = [] events = []
for spec in sys.argv[5:]: for spec in sys.argv[5:]: