zeroed-some/dougk / adc7b26

Browse files

more accessories

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
adc7b263470c8c731d90c6d4111557870d13df8b
Parents
5fa8df1
Tree
64a6979

2 changed files

StatusFile+-
M src/renderers/three/duck.js 9 0
M src/renderers/three/shop/items.js 434 0
src/renderers/three/duck.jsmodified
@@ -454,6 +454,15 @@ export function createDoug(scene, gradientMap) {
454454
     if (state.mode !== 'waiting') {
455455
       head.position.y = 0.7 + Math.sin(elapsed * 2) * 0.02
456456
     }
457
+
458
+    // Animate head accessories (propeller beanie, etc.)
459
+    if (accessories.head) {
460
+      accessories.head.traverse((child) => {
461
+        if (child.userData.isPropeller) {
462
+          child.rotation.y = elapsed * 8  // Fast spin!
463
+        }
464
+      })
465
+    }
457466
   }
458467
 
459468
   // Apply an outfit to Doug
src/renderers/three/shop/items.jsmodified
@@ -128,6 +128,148 @@ export const OUTFITS = {
128128
     }
129129
   },
130130
 
131
+  doug_aviator_goggles: {
132
+    id: 'doug_aviator_goggles',
133
+    name: 'Aviator Goggles',
134
+    character: CHARACTERS.DOUG,
135
+    type: OUTFIT_TYPES.ACCESSORY_FACE,
136
+    price: 35,
137
+    meshFactory: (gradientMap) => {
138
+      const group = new THREE.Group()
139
+      const brassMat = new THREE.MeshToonMaterial({ color: 0xb8860b, gradientMap })
140
+      const leatherMat = new THREE.MeshToonMaterial({ color: 0x5c4033, gradientMap })
141
+      const lensMat = new THREE.MeshBasicMaterial({ color: 0x4a90d9, transparent: true, opacity: 0.6 })
142
+
143
+      // Large goggle lenses (round, pilot-style)
144
+      const lensGeom = new THREE.CircleGeometry(0.1, 10)
145
+      const leftLens = new THREE.Mesh(lensGeom, lensMat)
146
+      leftLens.position.set(-0.12, 0, 0.02)
147
+      group.add(leftLens)
148
+
149
+      const rightLens = new THREE.Mesh(lensGeom, lensMat)
150
+      rightLens.position.set(0.12, 0, 0.02)
151
+      group.add(rightLens)
152
+
153
+      // Brass frames
154
+      const frameGeom = new THREE.TorusGeometry(0.1, 0.015, 6, 16)
155
+      const leftFrame = new THREE.Mesh(frameGeom, brassMat)
156
+      leftFrame.position.set(-0.12, 0, 0)
157
+      group.add(leftFrame)
158
+
159
+      const rightFrame = new THREE.Mesh(frameGeom, brassMat)
160
+      rightFrame.position.set(0.12, 0, 0)
161
+      group.add(rightFrame)
162
+
163
+      // Brass bridge with rivets
164
+      const bridgeGeom = new THREE.BoxGeometry(0.06, 0.025, 0.025)
165
+      const bridge = new THREE.Mesh(bridgeGeom, brassMat)
166
+      group.add(bridge)
167
+
168
+      // Rivets on bridge
169
+      const rivetGeom = new THREE.SphereGeometry(0.008, 4, 4)
170
+      const rivet1 = new THREE.Mesh(rivetGeom, brassMat)
171
+      rivet1.position.set(-0.02, 0, 0.015)
172
+      group.add(rivet1)
173
+
174
+      const rivet2 = new THREE.Mesh(rivetGeom, brassMat)
175
+      rivet2.position.set(0.02, 0, 0.015)
176
+      group.add(rivet2)
177
+
178
+      // Leather padding around lenses
179
+      const padGeom = new THREE.TorusGeometry(0.11, 0.02, 4, 16)
180
+      const leftPad = new THREE.Mesh(padGeom, leatherMat)
181
+      leftPad.position.set(-0.12, 0, -0.01)
182
+      group.add(leftPad)
183
+
184
+      const rightPad = new THREE.Mesh(padGeom, leatherMat)
185
+      rightPad.position.set(0.12, 0, -0.01)
186
+      group.add(rightPad)
187
+
188
+      // Leather strap connectors
189
+      const strapGeom = new THREE.BoxGeometry(0.04, 0.03, 0.015)
190
+      const leftStrap = new THREE.Mesh(strapGeom, leatherMat)
191
+      leftStrap.position.set(-0.22, 0, 0)
192
+      group.add(leftStrap)
193
+
194
+      const rightStrap = new THREE.Mesh(strapGeom, leatherMat)
195
+      rightStrap.position.set(0.22, 0, 0)
196
+      group.add(rightStrap)
197
+
198
+      return group
199
+    }
200
+  },
201
+
202
+  doug_propeller_beanie: {
203
+    id: 'doug_propeller_beanie',
204
+    name: 'Propeller Beanie',
205
+    character: CHARACTERS.DOUG,
206
+    type: OUTFIT_TYPES.ACCESSORY_HEAD,
207
+    price: 30,
208
+    meshFactory: (gradientMap) => {
209
+      const group = new THREE.Group()
210
+      const redMat = new THREE.MeshToonMaterial({ color: 0xdd3333, gradientMap })
211
+      const yellowMat = new THREE.MeshToonMaterial({ color: 0xffdd00, gradientMap })
212
+      const blueMat = new THREE.MeshToonMaterial({ color: 0x3366cc, gradientMap })
213
+
214
+      // Beanie cap base
215
+      const capGeom = new THREE.SphereGeometry(0.18, 10, 8, 0, Math.PI * 2, 0, Math.PI / 2)
216
+      const cap = new THREE.Mesh(capGeom, redMat)
217
+      group.add(cap)
218
+
219
+      // Striped panels (alternating colors)
220
+      for (let i = 0; i < 6; i++) {
221
+        const panelGeom = new THREE.SphereGeometry(0.182, 2, 8,
222
+          i * Math.PI / 3, Math.PI / 3, 0, Math.PI / 2)
223
+        const material = i % 2 === 0 ? yellowMat : blueMat
224
+        const panel = new THREE.Mesh(panelGeom, material)
225
+        group.add(panel)
226
+      }
227
+
228
+      // Brim
229
+      const brimGeom = new THREE.TorusGeometry(0.18, 0.02, 4, 16)
230
+      const brim = new THREE.Mesh(brimGeom, redMat)
231
+      brim.rotation.x = Math.PI / 2
232
+      brim.position.y = 0
233
+      group.add(brim)
234
+
235
+      // Button on top
236
+      const buttonGeom = new THREE.CylinderGeometry(0.03, 0.03, 0.02, 8)
237
+      const button = new THREE.Mesh(buttonGeom, yellowMat)
238
+      button.position.y = 0.17
239
+      group.add(button)
240
+
241
+      // Propeller mount
242
+      const mountGeom = new THREE.CylinderGeometry(0.015, 0.02, 0.04, 6)
243
+      const mount = new THREE.Mesh(mountGeom, blueMat)
244
+      mount.position.y = 0.19
245
+      group.add(mount)
246
+
247
+      // Propeller blades (will spin in animation)
248
+      const propGroup = new THREE.Group()
249
+      propGroup.userData.isPropeller = true
250
+      propGroup.position.y = 0.22
251
+
252
+      const bladeGeom = new THREE.BoxGeometry(0.15, 0.01, 0.03)
253
+      const blade1 = new THREE.Mesh(bladeGeom, redMat)
254
+      blade1.rotation.z = 0.1
255
+      propGroup.add(blade1)
256
+
257
+      const blade2 = new THREE.Mesh(bladeGeom, yellowMat)
258
+      blade2.rotation.y = Math.PI / 2
259
+      blade2.rotation.z = -0.1
260
+      propGroup.add(blade2)
261
+
262
+      // Center hub
263
+      const hubGeom = new THREE.SphereGeometry(0.02, 6, 4)
264
+      const hub = new THREE.Mesh(hubGeom, blueMat)
265
+      propGroup.add(hub)
266
+
267
+      group.add(propGroup)
268
+
269
+      return group
270
+    }
271
+  },
272
+
131273
   // === DOUG CLOTHING - Actual rendered garments ===
132274
 
133275
   // Simple tier - basic clothing
@@ -593,6 +735,148 @@ export const OUTFITS = {
593735
     }
594736
   },
595737
 
738
+  donny_bicorn: {
739
+    id: 'donny_bicorn',
740
+    name: "Captain's Bicorn",
741
+    character: CHARACTERS.DONNY,
742
+    type: OUTFIT_TYPES.ACCESSORY_HEAD,
743
+    price: 40,
744
+    meshFactory: (gradientMap) => {
745
+      const group = new THREE.Group()
746
+      const navyMat = new THREE.MeshToonMaterial({ color: 0x1a1a2e, gradientMap })
747
+      const goldMat = new THREE.MeshToonMaterial({ color: 0xffd700, gradientMap })
748
+      const whiteMat = new THREE.MeshToonMaterial({ color: 0xffffff, gradientMap })
749
+
750
+      // Main hat body (curved rectangular shape)
751
+      const bodyGeom = new THREE.BoxGeometry(0.35, 0.08, 0.2)
752
+      const body = new THREE.Mesh(bodyGeom, navyMat)
753
+      body.position.y = 0.04
754
+      group.add(body)
755
+
756
+      // Bicorn points (turned up sides)
757
+      const pointGeom = new THREE.BoxGeometry(0.08, 0.15, 0.18)
758
+      const leftPoint = new THREE.Mesh(pointGeom, navyMat)
759
+      leftPoint.position.set(-0.15, 0.1, 0)
760
+      leftPoint.rotation.z = 0.3
761
+      group.add(leftPoint)
762
+
763
+      const rightPoint = new THREE.Mesh(pointGeom, navyMat)
764
+      rightPoint.position.set(0.15, 0.1, 0)
765
+      rightPoint.rotation.z = -0.3
766
+      group.add(rightPoint)
767
+
768
+      // Gold trim along edges
769
+      const trimGeom = new THREE.BoxGeometry(0.36, 0.015, 0.01)
770
+      const frontTrim = new THREE.Mesh(trimGeom, goldMat)
771
+      frontTrim.position.set(0, 0.08, 0.1)
772
+      group.add(frontTrim)
773
+
774
+      const backTrim = new THREE.Mesh(trimGeom, goldMat)
775
+      backTrim.position.set(0, 0.08, -0.1)
776
+      group.add(backTrim)
777
+
778
+      // Cockade (rosette) decoration
779
+      const cockadeGeom = new THREE.CircleGeometry(0.04, 8)
780
+      const cockade = new THREE.Mesh(cockadeGeom, whiteMat)
781
+      cockade.position.set(0, 0.1, 0.11)
782
+      group.add(cockade)
783
+
784
+      // Gold button on cockade
785
+      const buttonGeom = new THREE.SphereGeometry(0.015, 6, 4)
786
+      const button = new THREE.Mesh(buttonGeom, goldMat)
787
+      button.position.set(0, 0.1, 0.12)
788
+      group.add(button)
789
+
790
+      // Feather plume
791
+      const featherGeom = new THREE.ConeGeometry(0.02, 0.15, 4)
792
+      const feather = new THREE.Mesh(featherGeom, whiteMat)
793
+      feather.position.set(0.02, 0.18, 0.08)
794
+      feather.rotation.z = -0.3
795
+      feather.rotation.x = 0.2
796
+      group.add(feather)
797
+
798
+      return group
799
+    }
800
+  },
801
+
802
+  donny_opera_glasses: {
803
+    id: 'donny_opera_glasses',
804
+    name: 'Opera Glasses',
805
+    character: CHARACTERS.DONNY,
806
+    type: OUTFIT_TYPES.ACCESSORY_FACE,
807
+    price: 45,
808
+    meshFactory: (gradientMap) => {
809
+      const group = new THREE.Group()
810
+      const goldMat = new THREE.MeshToonMaterial({ color: 0xd4af37, gradientMap })
811
+      const pearlMat = new THREE.MeshToonMaterial({ color: 0xfdf5e6, gradientMap })
812
+      const lensMat = new THREE.MeshBasicMaterial({ color: 0x87ceeb, transparent: true, opacity: 0.4 })
813
+
814
+      // Twin barrels (binocular style)
815
+      const barrelGeom = new THREE.CylinderGeometry(0.05, 0.06, 0.12, 8)
816
+
817
+      const leftBarrel = new THREE.Mesh(barrelGeom, pearlMat)
818
+      leftBarrel.position.set(-0.07, 0, 0)
819
+      leftBarrel.rotation.x = Math.PI / 2
820
+      group.add(leftBarrel)
821
+
822
+      const rightBarrel = new THREE.Mesh(barrelGeom, pearlMat)
823
+      rightBarrel.position.set(0.07, 0, 0)
824
+      rightBarrel.rotation.x = Math.PI / 2
825
+      group.add(rightBarrel)
826
+
827
+      // Lenses (front)
828
+      const lensGeom = new THREE.CircleGeometry(0.05, 10)
829
+      const leftLens = new THREE.Mesh(lensGeom, lensMat)
830
+      leftLens.position.set(-0.07, 0, 0.07)
831
+      group.add(leftLens)
832
+
833
+      const rightLens = new THREE.Mesh(lensGeom, lensMat)
834
+      rightLens.position.set(0.07, 0, 0.07)
835
+      group.add(rightLens)
836
+
837
+      // Gold rims
838
+      const rimGeom = new THREE.TorusGeometry(0.05, 0.008, 4, 12)
839
+      const leftRim = new THREE.Mesh(rimGeom, goldMat)
840
+      leftRim.position.set(-0.07, 0, 0.06)
841
+      group.add(leftRim)
842
+
843
+      const rightRim = new THREE.Mesh(rimGeom, goldMat)
844
+      rightRim.position.set(0.07, 0, 0.06)
845
+      group.add(rightRim)
846
+
847
+      // Bridge connecting barrels
848
+      const bridgeGeom = new THREE.BoxGeometry(0.04, 0.02, 0.03)
849
+      const bridge = new THREE.Mesh(bridgeGeom, goldMat)
850
+      bridge.position.set(0, 0, 0.02)
851
+      group.add(bridge)
852
+
853
+      // Ornate handle
854
+      const handleGeom = new THREE.CylinderGeometry(0.012, 0.015, 0.15, 6)
855
+      const handle = new THREE.Mesh(handleGeom, goldMat)
856
+      handle.position.set(0.12, -0.06, 0)
857
+      handle.rotation.z = Math.PI / 4
858
+      group.add(handle)
859
+
860
+      // Handle end knob
861
+      const knobGeom = new THREE.SphereGeometry(0.02, 6, 4)
862
+      const knob = new THREE.Mesh(knobGeom, goldMat)
863
+      knob.position.set(0.18, -0.12, 0)
864
+      group.add(knob)
865
+
866
+      // Decorative filigree on barrels
867
+      const filigreeGeom = new THREE.TorusGeometry(0.055, 0.005, 3, 12)
868
+      const leftFiligree = new THREE.Mesh(filigreeGeom, goldMat)
869
+      leftFiligree.position.set(-0.07, 0, 0)
870
+      group.add(leftFiligree)
871
+
872
+      const rightFiligree = new THREE.Mesh(filigreeGeom, goldMat)
873
+      rightFiligree.position.set(0.07, 0, 0)
874
+      group.add(rightFiligree)
875
+
876
+      return group
877
+    }
878
+  },
879
+
596880
   // === DONNY CLOTHING - Narwhal garments ===
597881
 
598882
   donny_sailor_vest: {
@@ -836,6 +1120,156 @@ export const OUTFITS = {
8361120
     }
8371121
   },
8381122
 
1123
+  ollie_jeweler_loupe: {
1124
+    id: 'ollie_jeweler_loupe',
1125
+    name: "Jeweler's Loupe",
1126
+    character: CHARACTERS.OLLIE,
1127
+    type: OUTFIT_TYPES.ACCESSORY_FACE,
1128
+    price: 35,
1129
+    meshFactory: (gradientMap) => {
1130
+      const group = new THREE.Group()
1131
+      const brassMat = new THREE.MeshToonMaterial({ color: 0xb8860b, gradientMap })
1132
+      const blackMat = new THREE.MeshToonMaterial({ color: 0x1a1a1a, gradientMap })
1133
+      const lensMat = new THREE.MeshBasicMaterial({ color: 0xaaffaa, transparent: true, opacity: 0.5 })
1134
+
1135
+      // Main loupe barrel
1136
+      const barrelGeom = new THREE.CylinderGeometry(0.06, 0.08, 0.1, 10)
1137
+      const barrel = new THREE.Mesh(barrelGeom, blackMat)
1138
+      barrel.rotation.x = Math.PI / 2
1139
+      barrel.position.z = 0.03
1140
+      group.add(barrel)
1141
+
1142
+      // Lens (front)
1143
+      const lensGeom = new THREE.CircleGeometry(0.06, 12)
1144
+      const lens = new THREE.Mesh(lensGeom, lensMat)
1145
+      lens.position.z = 0.09
1146
+      group.add(lens)
1147
+
1148
+      // Brass rim
1149
+      const rimGeom = new THREE.TorusGeometry(0.06, 0.01, 4, 16)
1150
+      const rim = new THREE.Mesh(rimGeom, brassMat)
1151
+      rim.position.z = 0.08
1152
+      group.add(rim)
1153
+
1154
+      // Eyepiece (back)
1155
+      const eyepieceGeom = new THREE.CylinderGeometry(0.05, 0.06, 0.03, 10)
1156
+      const eyepiece = new THREE.Mesh(eyepieceGeom, brassMat)
1157
+      eyepiece.rotation.x = Math.PI / 2
1158
+      eyepiece.position.z = -0.03
1159
+      group.add(eyepiece)
1160
+
1161
+      // Headband attachment (wraps around head)
1162
+      const bandGeom = new THREE.TorusGeometry(0.15, 0.015, 4, 16, Math.PI)
1163
+      const band = new THREE.Mesh(bandGeom, blackMat)
1164
+      band.position.set(0, 0.05, -0.05)
1165
+      band.rotation.x = Math.PI / 2
1166
+      band.rotation.z = Math.PI / 2
1167
+      group.add(band)
1168
+
1169
+      // Adjustment knob
1170
+      const knobGeom = new THREE.CylinderGeometry(0.015, 0.02, 0.03, 6)
1171
+      const knob = new THREE.Mesh(knobGeom, brassMat)
1172
+      knob.position.set(0.07, 0, 0.02)
1173
+      knob.rotation.z = Math.PI / 2
1174
+      group.add(knob)
1175
+
1176
+      // Knob ridges
1177
+      for (let i = 0; i < 6; i++) {
1178
+        const ridgeGeom = new THREE.BoxGeometry(0.002, 0.025, 0.005)
1179
+        const ridge = new THREE.Mesh(ridgeGeom, brassMat)
1180
+        const angle = (i / 6) * Math.PI * 2
1181
+        ridge.position.set(0.085, Math.sin(angle) * 0.015, 0.02 + Math.cos(angle) * 0.015)
1182
+        group.add(ridge)
1183
+      }
1184
+
1185
+      return group
1186
+    }
1187
+  },
1188
+
1189
+  ollie_wizard_hat: {
1190
+    id: 'ollie_wizard_hat',
1191
+    name: 'Wizard Hat',
1192
+    character: CHARACTERS.OLLIE,
1193
+    type: OUTFIT_TYPES.ACCESSORY_HEAD,
1194
+    price: 45,
1195
+    meshFactory: (gradientMap) => {
1196
+      const group = new THREE.Group()
1197
+      const purpleMat = new THREE.MeshToonMaterial({ color: 0x4b0082, gradientMap })
1198
+      const goldMat = new THREE.MeshToonMaterial({ color: 0xffd700, gradientMap })
1199
+      const silverMat = new THREE.MeshToonMaterial({ color: 0xc0c0c0, gradientMap })
1200
+
1201
+      // Main cone
1202
+      const coneGeom = new THREE.ConeGeometry(0.2, 0.45, 8)
1203
+      const cone = new THREE.Mesh(coneGeom, purpleMat)
1204
+      cone.position.y = 0.22
1205
+      group.add(cone)
1206
+
1207
+      // Bent tip (wizards hats droop!)
1208
+      const tipGeom = new THREE.ConeGeometry(0.05, 0.12, 6)
1209
+      const tip = new THREE.Mesh(tipGeom, purpleMat)
1210
+      tip.position.set(0.08, 0.42, 0.05)
1211
+      tip.rotation.z = -0.8
1212
+      tip.rotation.x = 0.3
1213
+      group.add(tip)
1214
+
1215
+      // Wide brim
1216
+      const brimGeom = new THREE.CylinderGeometry(0.28, 0.3, 0.03, 12)
1217
+      const brim = new THREE.Mesh(brimGeom, purpleMat)
1218
+      brim.position.y = 0
1219
+      group.add(brim)
1220
+
1221
+      // Gold band at base
1222
+      const bandGeom = new THREE.TorusGeometry(0.2, 0.02, 4, 16)
1223
+      const band = new THREE.Mesh(bandGeom, goldMat)
1224
+      band.position.y = 0.02
1225
+      band.rotation.x = Math.PI / 2
1226
+      group.add(band)
1227
+
1228
+      // Stars on hat (scattered)
1229
+      const starPositions = [
1230
+        { x: 0.12, y: 0.25, z: 0.1, scale: 0.8 },
1231
+        { x: -0.08, y: 0.35, z: 0.12, scale: 0.6 },
1232
+        { x: 0.05, y: 0.15, z: 0.15, scale: 0.5 },
1233
+        { x: -0.1, y: 0.2, z: -0.1, scale: 0.7 },
1234
+        { x: 0.08, y: 0.38, z: -0.05, scale: 0.5 }
1235
+      ]
1236
+
1237
+      for (const star of starPositions) {
1238
+        // Simple 4-point star shape
1239
+        const starGroup = new THREE.Group()
1240
+
1241
+        const point1Geom = new THREE.ConeGeometry(0.015, 0.04, 4)
1242
+        const point1 = new THREE.Mesh(point1Geom, silverMat)
1243
+        starGroup.add(point1)
1244
+
1245
+        const point2 = new THREE.Mesh(point1Geom, silverMat)
1246
+        point2.rotation.z = Math.PI
1247
+        starGroup.add(point2)
1248
+
1249
+        const point3 = new THREE.Mesh(point1Geom, silverMat)
1250
+        point3.rotation.z = Math.PI / 2
1251
+        starGroup.add(point3)
1252
+
1253
+        const point4 = new THREE.Mesh(point1Geom, silverMat)
1254
+        point4.rotation.z = -Math.PI / 2
1255
+        starGroup.add(point4)
1256
+
1257
+        starGroup.position.set(star.x, star.y, star.z)
1258
+        starGroup.scale.setScalar(star.scale)
1259
+        group.add(starGroup)
1260
+      }
1261
+
1262
+      // Moon crescent
1263
+      const moonGeom = new THREE.TorusGeometry(0.03, 0.01, 4, 12, Math.PI * 1.5)
1264
+      const moon = new THREE.Mesh(moonGeom, goldMat)
1265
+      moon.position.set(-0.12, 0.3, 0.08)
1266
+      moon.rotation.z = 0.5
1267
+      group.add(moon)
1268
+
1269
+      return group
1270
+    }
1271
+  },
1272
+
8391273
   // === OLLIE CLOTHING - Octopus garments ===
8401274
 
8411275
   ollie_bowtie: {