Level 01: Paddington Skatepark from the council plan + park guides — heightAt(x,z) single-source terrain, grindable rails/ledges, named gaps, B-O-O-K-Q-U-O-Y letters with the BOOKQUOYORK callback. SKATE / BMX / BLADES (blades cop thrown rubbish, as is tradition). character_kit two-rig banks: physics owns the root, clips are cosmetic. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
81 lines
3.8 KiB
JavaScript
81 lines
3.8 KiB
JavaScript
// BOOKQUOY trick tables — tricks are DATA, not code.
|
|
// (The core lesson from the THUG QB decompile: Neversoft shipped yearly because designers
|
|
// edited tables.) Clip names bind to the character_kit banks.
|
|
//
|
|
// Each discipline is a KIT: which bank the trick clips live in, what plays while rolling,
|
|
// and its own trick table. `mate` overrides the paired secondary clip when it differs
|
|
// from the pairs.json default (e.g. double barspin = same rider clip, faster bike clip).
|
|
|
|
export const KITS = {
|
|
skate: {
|
|
label: 'SKATE', anchor: 'Board', primary: 'prop', grinds: true,
|
|
idle: 'Board_Idle', roll: 'Board_Roll', push: 'Board_Push',
|
|
bail: 'Board_Bail', airFall: 'Ollie',
|
|
ollie: { clip: 'Ollie', name: 'Ollie', score: 10 },
|
|
grindKinds: {
|
|
rail: { clip: 'Grind_5050', name: '50-50', base: 100, perSec: 60 },
|
|
ledge: { clip: 'Grind_5050', name: 'Ledge Grind', base: 100, perSec: 60 },
|
|
},
|
|
tricks: {
|
|
KeyJ: { base: { clip: 'Kickflip', name: 'Kickflip', score: 100 },
|
|
up: { clip: 'VarialKickflip', name: 'Varial Kickflip', score: 200 },
|
|
down: { clip: 'DoubleKickflip', name: 'Double Kickflip', score: 250 } },
|
|
KeyK: { base: { clip: 'Heelflip', name: 'Heelflip', score: 100 },
|
|
up: { clip: 'VarialHeelflip', name: 'Varial Heelflip', score: 200 },
|
|
down: { clip: 'InwardHeelflip', name: 'Inward Heelflip', score: 275 } },
|
|
KeyL: { base: { clip: 'PopShoveIt', name: 'Pop Shove-It', score: 75 },
|
|
up: { clip: 'BigSpin', name: 'BigSpin', score: 150 },
|
|
down: { clip: 'Shove360', name: '360 Shove-It', score: 200 } },
|
|
KeyT: { base: { clip: 'TreFlip', name: 'Tre Flip', score: 300 } },
|
|
KeyY: { base: { clip: 'LaserFlip', name: 'Laser Flip', score: 350 } },
|
|
KeyH: { base: { clip: 'Hardflip', name: 'Hardflip', score: 300 } },
|
|
KeyN: { base: { clip: 'Impossible', name: 'Impossible', score: 250 } },
|
|
KeyF: { base: { clip: 'FSShoveIt', name: 'FS Shove-It', score: 100 } },
|
|
},
|
|
},
|
|
|
|
bmx: {
|
|
label: 'BMX', anchor: 'Bike', primary: 'rider', grinds: false,
|
|
idle: 'BikeRide_Idle', roll: 'BikeRide_Idle', push: 'BikePedal',
|
|
bail: 'BikeBail_Rider', airFall: 'BikeAir_Idle',
|
|
ollie: { clip: 'Bunnyhop_Rider', name: 'Bunnyhop', score: 50 },
|
|
tricks: {
|
|
KeyJ: { base: { clip: 'Barspin_Rider', name: 'Barspin', score: 150 },
|
|
down: { clip: 'Barspin_Rider', mate: 'Barspin_Double',
|
|
name: 'Double Barspin', score: 300 } },
|
|
KeyK: { base: { clip: 'Tailwhip_Rider', name: 'Tailwhip', score: 250 } },
|
|
KeyL: { base: { clip: 'XUp_Rider', name: 'X-Up', score: 150 } },
|
|
},
|
|
},
|
|
|
|
blades: {
|
|
label: 'BLADES', anchor: null, primary: 'rider', grinds: true, rubbish: true,
|
|
idle: 'Skate_Idle', roll: 'Skate_Roll', push: 'Skate_Push',
|
|
bail: 'Bail_Rider', airFall: 'Pop_Ollie',
|
|
ollie: { clip: 'Pop_Ollie', name: 'Air', score: 10 },
|
|
grindKinds: {
|
|
rail: { clip: 'Grind_Idle', name: 'Soul Grind', base: 100, perSec: 60 },
|
|
ledge: { clip: 'Grind_Idle', name: 'Royale', base: 100, perSec: 60 },
|
|
},
|
|
tricks: {
|
|
KeyJ: { base: { clip: 'Pop_Kick', name: '360 Spin', score: 100 } },
|
|
KeyK: { base: { clip: 'Pop_Heel', name: 'Zero Spin', score: 100 } },
|
|
KeyL: { base: { clip: 'Pop_Shove', name: 'Truespin', score: 120 } },
|
|
KeyT: { base: { clip: 'Pop_Long', name: 'Misty Flip', score: 300 } },
|
|
},
|
|
},
|
|
};
|
|
|
|
export const RUBBISH_INSULTS = [
|
|
'OI!', 'GET A BOARD!', 'FRUIT BOOTS!!', 'NICE ROLLERBLADES MATE',
|
|
'WRONG PARK, BLADER', 'COP THAT', '*thrown VB can*',
|
|
];
|
|
|
|
export const GAP_SCORE = 300;
|
|
export const LETTER_SCORE = 500;
|
|
export const ALL_LETTERS_SCORE = 5000;
|
|
|
|
export function comboLabel(items) {
|
|
return items.map(i => i.name).join(' + ') + (items.length > 1 ? ` x${items.length}` : '');
|
|
}
|