let-them-talk 4.2.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +640 -540
- package/README.md +592 -415
- package/cli.js +1089 -589
- package/conversation-templates/autonomous-feature.json +22 -0
- package/conversation-templates/code-review.json +21 -11
- package/conversation-templates/debug-squad.json +21 -11
- package/conversation-templates/feature-build.json +21 -11
- package/conversation-templates/research-write.json +21 -11
- package/dashboard.html +9250 -7771
- package/dashboard.js +1232 -29
- package/office/agents.js +148 -4
- package/office/animation.js +68 -0
- package/office/assets.js +431 -0
- package/office/builder.js +355 -0
- package/office/building-interior.js +261 -0
- package/office/campus-env.js +119 -23
- package/office/car-hud.js +368 -0
- package/office/daynight.js +221 -0
- package/office/economy-hud.js +432 -0
- package/office/economy-ui.js +238 -0
- package/office/environment.js +818 -808
- package/office/face.js +65 -0
- package/office/fast-travel.js +215 -0
- package/office/hq-building.js +295 -0
- package/office/index.js +1095 -423
- package/office/instancing.js +160 -0
- package/office/lod-manager.js +165 -0
- package/office/multiplayer-hud.js +428 -0
- package/office/net-client.js +299 -0
- package/office/particles.js +172 -0
- package/office/player.js +658 -436
- package/office/post-processing.js +82 -0
- package/office/sky.js +319 -0
- package/office/street-furniture.js +308 -0
- package/office/vehicle.js +455 -0
- package/office/world-save.js +91 -0
- package/package.json +59 -59
- package/server.js +7190 -4685
- package/conversation-templates/managed-team.json +0 -12
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Particle effects for AI City.
|
|
5
|
+
* Industrial smoke, chimney steam, ambient dust.
|
|
6
|
+
* Uses THREE.Points for minimal draw calls (1 per effect).
|
|
7
|
+
* Target: 120fps — max 200 particles per emitter.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const emitters = [];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Create a smoke emitter at a position (e.g., factory chimney).
|
|
14
|
+
* @param {THREE.Scene} scene
|
|
15
|
+
* @param {THREE.Vector3} position - World position of the emitter
|
|
16
|
+
* @param {Object} options
|
|
17
|
+
* @param {number} options.count - Particle count (default 80)
|
|
18
|
+
* @param {number} options.spread - Horizontal spread (default 1)
|
|
19
|
+
* @param {number} options.height - Max rise height (default 8)
|
|
20
|
+
* @param {number} options.speed - Rise speed (default 0.5)
|
|
21
|
+
* @param {number} options.size - Particle size (default 0.4)
|
|
22
|
+
* @param {number} options.color - Hex color (default 0x888888)
|
|
23
|
+
* @param {number} options.opacity - Max opacity (default 0.3)
|
|
24
|
+
* @returns {Object} Emitter handle for update/dispose
|
|
25
|
+
*/
|
|
26
|
+
export function createSmokeEmitter(scene, position, options) {
|
|
27
|
+
const opts = Object.assign({
|
|
28
|
+
count: 80,
|
|
29
|
+
spread: 1,
|
|
30
|
+
height: 8,
|
|
31
|
+
speed: 0.5,
|
|
32
|
+
size: 0.4,
|
|
33
|
+
color: 0x888888,
|
|
34
|
+
opacity: 0.3,
|
|
35
|
+
}, options);
|
|
36
|
+
|
|
37
|
+
const count = opts.count;
|
|
38
|
+
const positions = new Float32Array(count * 3);
|
|
39
|
+
const velocities = new Float32Array(count * 3);
|
|
40
|
+
const lifetimes = new Float32Array(count);
|
|
41
|
+
const maxLifetimes = new Float32Array(count);
|
|
42
|
+
|
|
43
|
+
// Initialize particles
|
|
44
|
+
for (let i = 0; i < count; i++) {
|
|
45
|
+
resetParticle(i, positions, velocities, lifetimes, maxLifetimes, position, opts);
|
|
46
|
+
// Stagger initial lifetimes so particles don't all spawn at once
|
|
47
|
+
lifetimes[i] = Math.random() * maxLifetimes[i];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const geometry = new THREE.BufferGeometry();
|
|
51
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
|
52
|
+
|
|
53
|
+
const material = new THREE.PointsMaterial({
|
|
54
|
+
color: opts.color,
|
|
55
|
+
size: opts.size,
|
|
56
|
+
transparent: true,
|
|
57
|
+
opacity: opts.opacity,
|
|
58
|
+
depthWrite: false,
|
|
59
|
+
sizeAttenuation: true,
|
|
60
|
+
fog: true,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const points = new THREE.Points(geometry, material);
|
|
64
|
+
points.name = 'smoke-emitter';
|
|
65
|
+
points.frustumCulled = true;
|
|
66
|
+
scene.add(points);
|
|
67
|
+
|
|
68
|
+
const emitter = {
|
|
69
|
+
points,
|
|
70
|
+
positions,
|
|
71
|
+
velocities,
|
|
72
|
+
lifetimes,
|
|
73
|
+
maxLifetimes,
|
|
74
|
+
origin: position.clone(),
|
|
75
|
+
opts,
|
|
76
|
+
active: true,
|
|
77
|
+
};
|
|
78
|
+
emitters.push(emitter);
|
|
79
|
+
return emitter;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function resetParticle(i, positions, velocities, lifetimes, maxLifetimes, origin, opts) {
|
|
83
|
+
const i3 = i * 3;
|
|
84
|
+
positions[i3] = origin.x + (Math.random() - 0.5) * opts.spread * 0.3;
|
|
85
|
+
positions[i3 + 1] = origin.y;
|
|
86
|
+
positions[i3 + 2] = origin.z + (Math.random() - 0.5) * opts.spread * 0.3;
|
|
87
|
+
|
|
88
|
+
velocities[i3] = (Math.random() - 0.5) * opts.spread * 0.1;
|
|
89
|
+
velocities[i3 + 1] = opts.speed * (0.7 + Math.random() * 0.6);
|
|
90
|
+
velocities[i3 + 2] = (Math.random() - 0.5) * opts.spread * 0.1;
|
|
91
|
+
|
|
92
|
+
maxLifetimes[i] = opts.height / opts.speed * (0.8 + Math.random() * 0.4);
|
|
93
|
+
lifetimes[i] = 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Update all active smoke emitters. Call once per frame.
|
|
98
|
+
* @param {number} dt - Delta time in seconds
|
|
99
|
+
*/
|
|
100
|
+
export function updateParticles(dt) {
|
|
101
|
+
for (const emitter of emitters) {
|
|
102
|
+
if (!emitter.active) continue;
|
|
103
|
+
const { positions, velocities, lifetimes, maxLifetimes, origin, opts, points } = emitter;
|
|
104
|
+
const count = lifetimes.length;
|
|
105
|
+
const posAttr = points.geometry.getAttribute('position');
|
|
106
|
+
|
|
107
|
+
for (let i = 0; i < count; i++) {
|
|
108
|
+
lifetimes[i] += dt;
|
|
109
|
+
if (lifetimes[i] >= maxLifetimes[i]) {
|
|
110
|
+
resetParticle(i, positions, velocities, lifetimes, maxLifetimes, origin, opts);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const i3 = i * 3;
|
|
115
|
+
// Wind drift + rise
|
|
116
|
+
positions[i3] += velocities[i3] * dt;
|
|
117
|
+
positions[i3 + 1] += velocities[i3 + 1] * dt;
|
|
118
|
+
positions[i3 + 2] += velocities[i3 + 2] * dt;
|
|
119
|
+
|
|
120
|
+
// Slow horizontal drift increases with height
|
|
121
|
+
velocities[i3] += (Math.random() - 0.5) * 0.02;
|
|
122
|
+
velocities[i3 + 2] += (Math.random() - 0.5) * 0.02;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
posAttr.needsUpdate = true;
|
|
126
|
+
|
|
127
|
+
// Fade opacity based on average lifetime progress
|
|
128
|
+
const avgProgress = lifetimes.reduce((s, l, i) => s + l / maxLifetimes[i], 0) / count;
|
|
129
|
+
points.material.opacity = opts.opacity * (1 - avgProgress * 0.5);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Set emitter active/inactive.
|
|
135
|
+
* @param {Object} emitter
|
|
136
|
+
* @param {boolean} active
|
|
137
|
+
*/
|
|
138
|
+
export function setEmitterActive(emitter, active) {
|
|
139
|
+
emitter.active = active;
|
|
140
|
+
emitter.points.visible = active;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Dispose a single emitter.
|
|
145
|
+
* @param {Object} emitter
|
|
146
|
+
* @param {THREE.Scene} scene
|
|
147
|
+
*/
|
|
148
|
+
export function disposeEmitter(emitter, scene) {
|
|
149
|
+
scene.remove(emitter.points);
|
|
150
|
+
emitter.points.geometry.dispose();
|
|
151
|
+
emitter.points.material.dispose();
|
|
152
|
+
const idx = emitters.indexOf(emitter);
|
|
153
|
+
if (idx >= 0) emitters.splice(idx, 1);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Dispose all emitters.
|
|
158
|
+
* @param {THREE.Scene} scene
|
|
159
|
+
*/
|
|
160
|
+
export function disposeAllEmitters(scene) {
|
|
161
|
+
while (emitters.length > 0) {
|
|
162
|
+
disposeEmitter(emitters[0], scene);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get active emitter count (for performance monitoring).
|
|
168
|
+
* @returns {number}
|
|
169
|
+
*/
|
|
170
|
+
export function getEmitterCount() {
|
|
171
|
+
return emitters.filter(e => e.active).length;
|
|
172
|
+
}
|