BANNON
OFF THE TOP ROPE
starting the engine
0%
tap to continue anyway
BANNONFIRE · SCORPIO
SOUTHPAW · ICEVIPER
ROUND 1 ○○ : ○○
86
0
HIT COMBO
FROG SPLASH
BANNON
MOVE: WASD · RUN: SHIFT+dir · ZONE(LB): context exit/climb/pin/whip · J=LIGHT · K=HEAVY · L=GRAB · G=GRAPPLE · SPACE=FINISHER · U=UPPERCUT · ESC=PAUSE
FORWARD
T
ZONE: RING
SPINEBUSTER
CRANE STICK = REPOSITION · MOD = CHANGE HOLD · ZONE = DELIVER
⚡ FINISHER READY ⚡
SUBMISSION
TAP ZONE BUTTON TO ESCAPE
BANNON // SELF-BUILDER
SWARM NODES
CLAUDE
Claude Sonnet 4
200k context · guaranteed output · primary
● ACTIVE · CLOUD
QWEN LOCAL
qwen2.5-coder:32b
No token limit · unlimited output · runs while active
● ACTIVE · LOCAL
DEEPSEEK LOCAL
deepseek-coder-v2
No token limit · code specialist · fallback
● ACTIVE · LOCAL
LLAMA LOCAL
llama3.1:70b
No token limit · reasoning + code · tertiary
● ACTIVE · LOCAL
LM STUDIO
LM Studio (local)
No key · OpenAI-compatible · localhost:1234 · uncapped
● ACTIVE · LOCAL
OPENROUTER
OpenRouter
Cloud fallback · any model · requires key
○ OFF · CLOUD
GEMINI PRO
Gemini 2.5 Pro
FREE · 1M context · whole 800KB file in one call · no chunking
● ACTIVE · CLOUD
GEMINI FLASH
Gemini 2.5 Flash
FREE · 1M context · fast · chat + quick fixes
○ OFF · CLOUD
API KEYS
Anthropic (Claude — primary)
Ollama URL (local qwen2.5-coder)
Google Gemini (free · 1M context — aistudio.google.com/apikey)
SWARM MODE
Surgery Directive
[BANNON SWARM BUILDER] ONLINE
[SYS] Configure nodes → set directive → execute swarm
[SYS] AUTO mode tries Claude first, falls back to qwen, then OpenRouter
AI reads the live BANNON code. Ask anything. Get patches back with Apply button.
Ask anything about BANNON. The AI has the live game code.
Tap scan to analyze the live game code
Session Memory (survives tab changes)
No memory yet. Build and chat sessions are remembered here.
Version History
BANNON PREVIEW
// ============================================================================ // BRICK 117: ADVANCED KINEMATICS, JOINT LOCKS & DEEP COMBAT // ============================================================================ (function() { if (typeof Fighter === 'undefined') return; // --- Capoeira & Archetypal Stance Offsets --- const _origGuard = Fighter.prototype.poseGuard; if (_origGuard) { Fighter.prototype.poseGuard = function(dt, walking) { _origGuard.apply(this, arguments); if (!this.J) return; const style = this.style ? this.style.toUpperCase() : 'ORTHODOX'; const isCapoeira = style === 'CAPOEIRA'; // Stance offsets let sx = 0, sy = 0, sz = 0; if (style === 'SOUTHPAW') { sx = -0.15; sz = -0.1; } else if (style === 'BRAWLER') { sy = -0.15; sx = 0.1; } else if (style === 'MUAY_THAI') { sy = 0.15; sz = 0.05; } else if (style === 'LUCHA') { sy = -0.1; sx = 0.1; } else if (style === 'TECHNICIAN') { sy = -0.1; sx = -0.1; } if (!isCapoeira && (sx||sy||sz)) { if (this.J.haL) { this.J.haL.tgt.x += sx; this.J.haL.tgt.y += sy; this.J.haL.tgt.z += sz; } if (this.J.haR) { this.J.haR.tgt.x -= sx; this.J.haR.tgt.y -= sy; this.J.haR.tgt.z -= sz; } } // Capoeira Constant Locomotion (Ginga) if (isCapoeira) { const p = this.walkPhase || 0; if (Math.abs(this.wantMove||0) < 0.1) this.walkPhase = (this.walkPhase || 0) + dt * 2.0; const hipS = Math.sin(p) * 0.28; const hipD = 0.15 + Math.abs(Math.cos(p * 2)) * 0.15; if (this.J.pelvis) { this.J.pelvis.tgt.x += hipS * 0.3; this.J.pelvis.tgt.y -= hipD; this.J.pelvis.tgt.z += hipS * 1.2; } if (this.J.haL) { this.J.haL.tgt.set(0.4, 0.7, 0.3); } if (this.J.haR) { this.J.haR.tgt.set(0.4, 0.7, -0.3); } if (this.J.head) { this.J.head.tgt.x += 0.1; this.J.head.tgt.z -= hipS * 0.4; } } }; } // --- Capoeira Inverted Kinematics (Attacks) --- const _origAttack = Fighter.prototype.poseAttack; if (_origAttack) { Fighter.prototype.poseAttack = function(dt) { _origAttack.apply(this, arguments); if (!this.J || !this.attackData) return; const m = this.attackData; if (this.style === 'CAPOEIRA' && m.limb && m.limb.includes('KICK')) { const p = Math.max(0.001, Math.min(this.attackPhase || 0, 1.0)); const sweepAngle = p * Math.PI * 2; const isLeft = m.limb.includes('LEFT'); const kf = isLeft ? 'ftL' : 'ftR'; const plantHand = isLeft ? 'haR' : 'haL'; const r = this.reachScale || 1.0; if (p < 0.8 && this.J[kf]) { this.J[kf].tgt.x += Math.cos(sweepAngle) * 0.8 * r; this.J[kf].tgt.z += Math.sin(sweepAngle) * 0.8 * r; this.J[kf].tgt.y += 0.8; } if (this.J.pelvis) this.J.pelvis.tgt.y -= 0.3; if (this.J.chest) this.J.chest.tgt.y -= 0.4; if (this.J[plantHand]) this.J[plantHand].tgt.set(0.1, 0.05, 0.3); } }; } // --- Mass Delta Resistance in Lifts --- const _origDeliver = Fighter.prototype.poseDeliver; if (_origDeliver) { Fighter.prototype.poseDeliver = function(dt) { _origDeliver.apply(this, arguments); const opp = (typeof fighters !== 'undefined') ? fighters[1 - this.idx] : null; if (!opp) return; // Submission Hyperextension Logics if (this.grapplePos && this.grapplePos.includes('SUBMISSION')) { const isArm = this.grapplePos.includes('ARMBAR'); const tgt = isArm ? 'elR' : 'knR'; if (opp.J && opp.J[tgt]) { opp.J[tgt].tgt.y = 1.3 + ((this.stateTime || 0) * 0.2); if (opp.stamina > 0) opp.stamina -= dt * 15; } } // Lift Resistance based on mass ratio if (this._gPhase !== undefined && this._gPhase > 0.1 && this._gPhase < 0.9) { const n1 = this.opts && this.opts.name ? this.opts.name.toUpperCase() : 'BANNON'; const n2 = opp.opts && opp.opts.name ? opp.opts.name.toUpperCase() : 'BANNON'; const wMe = ROSTER_SPEC[n1] ? ROSTER_SPEC[n1].weight : 90; const wOpp = ROSTER_SPEC[n2] ? ROSTER_SPEC[n2].weight : 90; if (wMe < wOpp - 10 && opp.root) { const penalty = (wOpp - wMe) / 100.0; opp.root.position.y -= penalty * Math.abs(Math.sin((this.stateTime||0)*15)); // struggle } } }; } // --- Deepen Combat (Hitstop & CA) --- window._hitstopTicks = 0; const _origAD = window.applyDamage; if (_origAD) { window.applyDamage = function(defender, dmg, attacker, move, isGround) { const res = _origAD(defender, dmg, attacker, move, isGround); if (dmg >= 8) { window._hitstopTicks = Math.min(12, Math.floor(dmg / 3)); const canvas = document.querySelector('canvas'); if (canvas) { canvas.style.transition = 'none'; const dx = (Math.random() - 0.5) * dmg * 0.4; const dy = (Math.random() - 0.5) * dmg * 0.4; canvas.style.transform = `translate(${dx}px, ${dy}px)`; canvas.style.filter = `drop-shadow(${dmg*0.5}px 0 0 rgba(255,20,0,0.6)) drop-shadow(-${dmg*0.5}px 0 0 rgba(0,255,255,0.6)) saturate(1.5)`; setTimeout(() => { canvas.style.transition = 'transform 0.1s ease-out, filter 0.1s ease-out'; canvas.style.transform = 'translate(0px, 0px)'; canvas.style.filter = 'none'; }, window._hitstopTicks * 16 + 30); } // Spine/Hip Recoil boost if (defender.J) { if (defender.J.chest) defender.J.chest.tgt.x -= dmg * 0.02; if (defender.J.spineMid) defender.J.spineMid.tgt.x -= dmg * 0.01; if (defender.J.head) defender.J.head.tgt.x -= dmg * 0.025; if (defender.J.pelvis) defender.J.pelvis.tgt.x += dmg * 0.01; // opposing torque } } return res; }; } // Intercept the main update loop to apply hitstop frame freezing const _origUpdate = Fighter.prototype.update; if (_origUpdate) { Fighter.prototype.update = function(dt) { if (window._hitstopTicks > 0) { if (this.idx === 0) window._hitstopTicks--; // Apply visual jitter during freeze if (this.root && this.state !== 'down' && !this.ragdoll) { this.root.position.x += (Math.random() - 0.5) * 0.02; } return; } _origUpdate.apply(this, arguments); }; } // --- Lock Joints (Ragdoll Angle Enforcement) --- const _origUpdateRagdoll = Fighter.prototype.updateRagdoll; if (_origUpdateRagdoll) { Fighter.prototype.updateRagdoll = function(dt) { _origUpdateRagdoll.apply(this, arguments); if (!this.V) return; // Project vectors to enforce hinge limits const enforceHinge = (P1, P2, P3, isKnee, isRight) => { if (!P1 || !P2 || !P3) return; const v1x = P1.pos.x - P2.pos.x, v1y = P1.pos.y - P2.pos.y, v1z = P1.pos.z - P2.pos.z; const v2x = P3.pos.x - P2.pos.x, v2y = P3.pos.y - P2.pos.y, v2z = P3.pos.z - P2.pos.z; // Dot product to test angle const len1 = Math.sqrt(v1x*v1x + v1y*v1y + v1z*v1z); const len2 = Math.sqrt(v2x*v2x + v2y*v2y + v2z*v2z); if (len1===0 || len2===0) return; const dot = (v1x*v2x + v1y*v2y + v1z*v2z) / (len1 * len2); // The cross product determines the bend direction (forward vs backward) const crx = v1y*v2z - v1z*v2y; const crz = v1x*v2y - v1y*v2x; // Very basic correction: If knee bends forward over a threshold, push the knee back along its local Z if (isKnee) { // In default pose, +Z is forward. If joint buckles forward, push it back. if (crx > 0 && dot > 0.1) { P2.pos.z -= 0.05 * (dot); if (P2.old) P2.old.z = P2.pos.z; } } else { // Elbows bending backwards if (crx < 0 && dot > 0.1) { P2.pos.z += 0.05 * (dot); if (P2.old) P2.old.z = P2.pos.z; } } }; enforceHinge(this.V['hipL'], this.V['knL'], this.V['ftL'], true, false); enforceHinge(this.V['hipR'], this.V['knR'], this.V['ftR'], true, true); enforceHinge(this.V['shL'], this.V['elL'], this.V['haL'], false, false); enforceHinge(this.V['shR'], this.V['elR'], this.V['haR'], false, true); }; } try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'combat.joints_archetypes', kind: 'physics+gameplay', summary: 'Brick 117: Deepen combat (CA burst + spine torque + hitstop), Roster Archetypes (Capoeira Ginga & attacks, Southpaw/Brawler guard offsets), Submissions hyperextension lock, Mass Delta Hoist, and Verlet Joint Angle Locks.', call: 'ROSTER_SPEC augmentation + capoeira poseAttack + applyDamage hitstop/CA + enforceHinge' }); } catch(e) {} console.log('%c[BANNON v117] JOINT LOCKS · DEEP COMBAT RECOIL · ROSTER ARCHETYPES · CAPOEIRA GINGA · HOIST MASS DELTA — injected', 'color:#00ffff;font-weight:bold'); })(); /* BANNON SYSTEM BRICK — PER-FRAME BONE LENGTH ENFORCEMENT */ (function() { if (typeof Fighter === 'undefined' || typeof BONES === 'undefined' || typeof REST === 'undefined') return; const getRestDist = (b1, b2) => { const r1 = REST[b1], r2 = REST[b2]; if (!r1 || !r2) return null; const x1 = r1.x !== undefined ? r1.x : r1[0]; const y1 = r1.y !== undefined ? r1.y : r1[1]; const z1 = r1.z !== undefined ? r1.z : r1[2]; const x2 = r2.x !== undefined ? r2.x : r2[0]; const y2 = r2.y !== undefined ? r2.y : r2[1]; const z2 = r2.z !== undefined ? r2.z : r2[2]; return Math.sqrt((x1-x2)**2 + (y1-y2)**2 + (z1-z2)**2); }; const enforceLengths = (jointsArray) => { if (!jointsArray) return; for (let iter = 0; iter < 3; iter++) { // 3 iterations for rigid solve for (let i = 0; i < BONES.length; i++) { const bn1 = BONES[i][0]; const bn2 = BONES[i][1]; const j1 = jointsArray[bn1]; const j2 = jointsArray[bn2]; if (!j1 || !j2 || !j1.pos || !j2.pos) continue; const restDist = getRestDist(bn1, bn2); if (!restDist || restDist < 0.0001) continue; const dx = j1.pos.x - j2.pos.x; const dy = j1.pos.y - j2.pos.y; const dz = j1.pos.z - j2.pos.z; const curDist = Math.sqrt(dx*dx + dy*dy + dz*dz) || 0.0001; // strict length enforcement const diff = (curDist - restDist) / curDist; const moveDist = diff * 0.5; const px = dx * moveDist; const py = dy * moveDist; const pz = dz * moveDist; j1.pos.x -= px; j1.pos.y -= py; j1.pos.z -= pz; j2.pos.x += px; j2.pos.y += py; j2.pos.z += pz; } } }; const _origUpdate = Fighter.prototype.update; if (_origUpdate) { Fighter.prototype.update = function(dt) { _origUpdate.apply(this, arguments); if (this.J) enforceLengths(this.J); if (this.V) enforceLengths(this.V); }; } try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'physics.bone_length_enforcement', kind: 'physics', summary: 'Brick: Per-frame bone length enforcement to correct the mesh stretching glitch during ragdoll/grappling.', call: 'Fighter.prototype.update post-layer length correction' }); } catch(e) {} console.log('%c[BANNON] PER-FRAME BONE LENGTH ENFORCEMENT — injected', 'color:#ff00ff;font-weight:bold'); })(); /* BANNON SYSTEM BRICK — BULK FBX ASSET LOADER & MOVEDEX REGISTRAR (WWE 2K26 STRUCTURE) */ (function() { window.BANNON_LOAD_FBX_LIBRARY = async function() { if (typeof THREE.FBXLoader === 'undefined') { console.error('[BANNON FBX BATCH] FBXLoader must be loaded to batch-import assets.'); return; } const ASSETS = [ 'Action Idle To Standing Idle.fbx', 'Baseball Hit.fbx', 'Body Block.fbx', 'Box Idle.fbx', 'Boxing (1).fbx', 'Boxing (2).fbx', 'Boxing (3).fbx', 'Boxing.fbx', 'Brooklyn Uprock.fbx', 'Brutal Assassination.fbx', 'Capoeira (1).fbx', 'Capoeira.fbx', 'Center Block.fbx', 'Cross Jumps.fbx', 'Dancing.fbx', 'Death From Back Headshot.fbx', 'Defender.fbx', 'Double Leg Takedown - Victim.fbx', 'Drop Kick.fbx', 'Drunk Idle Variation.fbx', 'Drunk Walk.fbx', 'Fist Fight A.fbx', 'Flair.fbx', 'Goalkeeper Catch.fbx', 'Hurricane Kick.fbx', 'Idle.fbx', 'Illegal Elbow Punch (1).fbx', 'Illegal Elbow Punch.fbx', 'Inverted Double Kick To Kip Up.fbx', 'Jogging.fbx', 'Jump Attack.fbx', 'Jump.fbx', 'Jumping Down.fbx', 'Jumping.fbx', 'Kick To The Groin (1).fbx', 'Kick To The Groin.fbx', 'Mma Kick.fbx', 'Mutant Roaring.fbx', 'Pivot.fbx', 'Playing Drums.fbx', 'Punching Bag.fbx', 'Punching.fbx', 'Ready Idle.fbx', 'Running (1).fbx', 'Running Jump.fbx', 'Running.fbx', 'Sad Walk.fbx', 'Singing.fbx', 'Skateboarding.fbx', 'Snake Hip Hop Dance.fbx', 'Soccer Spin.fbx', 'Stable Sword Inward Slash.fbx', 'Standard Run.fbx', 'Standing Block Start.fbx', 'Standing Cover To Cover.fbx', 'Standing Melee Attack Horizontal.fbx', 'Standing React Large From Left.fbx', 'Standing Taunt Battlecry.fbx', 'Standing Turn Right 90.fbx', 'Standing Walk Left.fbx', 'Strut Walking.fbx', 'Swinging.fbx', 'Sword And Shield Attack.fbx', 'Sword And Shield Power Up.fbx', 'Taunt.fbx', 'Terrified.fbx', 'Treadmill Running.fbx', 'Two Handed Sword Death.fbx', 'Unarmed Idle Looking Ver. 2.fbx', 'Walk Backward.fbx', 'Walk Crouching Backward Right.fbx', 'Walking (1).fbx', 'Walking Backward.fbx', 'Walking Backwards (1).fbx', 'Walking Backwards.fbx', 'Walking.fbx', 'Zombie Dying.fbx', 'Zombie Punching.fbx' ]; // WRESTLING-MOVE CLIPS banked in the repo (assets/mocap/drive/, pulled from the owner's Drive // folders) — real move mocap that feeds STUDIO.clips and then every fighter's moveset. const COMBAT_CLIPS = [ 'Chokeslam.fbx','DoubleSuplex.fbx','HammerlockDDT.fbx','Tombstone.fbx','JayKick.fbx', 'ApronJayKick.fbx','StereoSuperkick.fbx','TagSuperkick.fbx','StrongZero.fbx', 'ViolenceParty.fbx','FenceM-Kick.fbx','Drop Kick (1).fbx','Kip Up.fbx','Queshada 2.fbx', 'Esquiva 3.fbx','Esquiva 4 (1).fbx','Ginga Forward.fbx','Fall B Loop.fbx','Taunt2.fbx', 'Baseball Hit.fbx','Big Body Blow.fbx','Big Rib Hit.fbx','Body Jab Cross.fbx','Body Block.fbx', 'Brutal Assassination.fbx','Breakdance Uprock To Ground.fbx','Breakdance Footwork To Freeze.fbx' ]; let FILES = [...new Set([...ASSETS, ...COMBAT_CLIPS])]; // MOBILE-SAFE HARVEST (owner plays the APK on a phone): each FBX is ~2-12MB — loading all 179 // at once is ~1GB and WILL crash a phone. So the default load is the CURATED CORE SET only // (~100 clips: locomotion + the mapped combat/taunt clips). The full drive_manifest set is // loaded ONLY when explicitly requested (window.FBX_LOAD_ALL=true) or by the daemon on desktop. // Individual moves lazy-load their own clip on-demand via loadClipFor() (below) when equipped. const LOAD_ALL = (window.FBX_LOAD_ALL===true); if (LOAD_ALL) { try { const _cdnM = window.MODEL_CDN_BASE || 'https://raw.githubusercontent.com/mhvnsnt/Bannon/main/'; let mr = await fetch('assets/mocap/drive_manifest.json').catch(()=>null); if (!mr || !mr.ok) mr = await fetch(_cdnM+'assets/mocap/drive_manifest.json').catch(()=>null); if (mr && mr.ok) { const mj = await mr.json(); const names=(mj.files||[]).filter(n=>/\.fbx$/i.test(n)); FILES = [...new Set([...FILES, ...names])]; } } catch (_e) {} try { const lr = await fetch('/api/list-mocap-files'); if (lr.ok) { const lj = await lr.json(); const names = (lj.files || lj || []).map(f => (typeof f === 'string' ? f : f.name)).filter(n => /\.fbx$/i.test(n)); if (names.length > FILES.length) FILES = names; } } catch (_e) {} } console.log(`[FBX BATCH] Importing ${FILES.length} FBX (${LOAD_ALL?'FULL set':'mobile-safe core; set FBX_LOAD_ALL=true for all 179'})...`); const loader = new THREE.FBXLoader(); let loadedCount = 0; // Ensure MOVEDEX and STUDIO clips are instantiated if (typeof STUDIO === 'undefined') window.STUDIO = { clips: {} }; STUDIO.clips = STUDIO.clips || {}; for (const file of FILES) { try { // LAG FIX (the "can't even make them fight" freeze): this loop used to fetch + SYNC-parse // ~78 FBX files back-to-back on the main thread, starting 1s after page load — right on // top of char select / the opening bell. Now it (a) fully PAUSES while a fight is live, // (b) yields a frame + breather between files so parses never stack into one long stall. while ((function(){ try { return (typeof gameState !== 'undefined' ? gameState : window.gameState) === 'fight'; } catch(_) { return window.gameState === 'fight'; } })()) { await new Promise(r => setTimeout(r, 2000)); } await new Promise(r => (window.requestAnimationFrame || setTimeout)(() => setTimeout(r, 120))); // repo layout first (works on GitHub Pages / a downloaded folder), then legacy root let response = await fetch('assets/mocap/drive/' + encodeURIComponent(file)).catch(() => null); if (!response || !response.ok) response = await fetch('assets/mocap/' + encodeURIComponent(file)).catch(() => null); if (!response || !response.ok) response = await fetch('/' + encodeURIComponent(file)).catch(() => null); // CDN FALLBACK — the APK (file://) has no bundled mocap; stream it from the repo like the // models/audio so the auto-loader actually works in-app (this is why moves weren't animating). if (!response || !response.ok){ const _cdn = window.MODEL_CDN_BASE || 'https://raw.githubusercontent.com/mhvnsnt/Bannon/main/'; response = await fetch(_cdn+'assets/mocap/drive/'+encodeURIComponent(file)).catch(()=>null); if (!response || !response.ok) response = await fetch(_cdn+'assets/mocap/'+encodeURIComponent(file)).catch(()=>null); } if (!response || !response.ok) continue; const buffer = await response.arrayBuffer(); const baseName = file.replace(/\.fbx$/i, ''); // e.g. "GermanSuplex", "Big Body Blow" const clipName = baseName.toUpperCase().replace(/[^A-Z0-9]/g, '_'); // e.g. "GERMANSUPLEX" // Parse synchronously here (could be chunked if UI freezes) const fbxObj = loader.parse(buffer, ''); if (fbxObj.animations && fbxObj.animations.length) { const clip = extractClipFromGLTF(fbxObj.animations[0], fbxObj); STUDIO.clips[clipName] = clip; // ALSO key under the RAW basename — move_clip_map.json references clips by basename // ("GermanSuplex", "Big Body Blow"), not the uppercased key, so without this alias // every mapped move's STUDIO.clips[m.clip] lookup missed and no mocap ever played. if (baseName !== clipName) STUDIO.clips[baseName] = clip; loadedCount++; // Register in MOVEDEX dynamically based on heuristics if (window.MOVEDEX) { let cat = 'STRIKE'; let subcat = 'STRIKE'; if (file.toLowerCase().includes('kick')) subcat = 'KICK'; else if (file.toLowerCase().includes('punch') || file.toLowerCase().includes('boxing')) subcat = 'PUNCH'; else if (file.toLowerCase().includes('idle')) { cat = 'TAUNT'; subcat = 'IDLE'; } else if (file.toLowerCase().includes('taunt')) { cat = 'TAUNT'; subcat = 'TAUNT'; } else if (file.toLowerCase().includes('walk') || file.toLowerCase().includes('run')) { cat = 'TAUNT'; subcat = 'LOCOMOTION'; } else if (file.toLowerCase().includes('victim') || file.toLowerCase().includes('react')) { cat = 'REACTION'; subcat = 'HIT_REACT'; } const customMove = { name: clipName, cat: cat, limb: 'BODY', traj: 'STRAIGHT', height: 'MID', power: 75, speed: 60, style: 'MOCAP', follow: 'RESET STANCE', clip: clipName }; if (typeof customMoves !== 'undefined' && !customMoves.some(m => m.name === clipName)) { customMoves.push(customMove); } } } } catch(e) { console.warn(`[FBX BATCH] Failed to parse: ${file}`, e); } } console.log(`[FBX BATCH] Loaded ${loadedCount}/${ASSETS.length} FBX files into STUDIO clips and MOVEDEX.`); }; // LAZY SINGLE-CLIP LOADER (mobile-safe): load ONE mocap clip on demand by basename, e.g. when a // move is equipped/played whose clip isn't in the core set — instead of the 1GB full harvest. // Returns the clip (cached in STUDIO.clips under both the raw basename and the UPPER_KEY). window.__fbxClipInFlight = window.__fbxClipInFlight || {}; // ══ THE FREEZE LIVED HERE ══════════════════════════════════════════════════════════════════ // This used to do fetch -> arrayBuffer -> `new THREE.FBXLoader().parse(buf,'')`, SYNCHRONOUSLY, // on the render thread — and poseAttack() calls it when a strike needs a clip that is not // resident. So throwing a punch mid-match kicked off a multi-megabyte FBX parse in the middle of // a frame. A V8 CPU profile of a live match was almost entirely FBXLoader and fflate (genFace, // genBuffers, getFloat64Array, parseNode, generateRotationTrack, inflate). Measured frames: // median 543 ms, worst 3766 ms. That is the freezing, exactly. // // There was a second half to it that is worse: 76 of the mocap files in the repo are Git LFS // POINTERS with no data in them — 130 bytes of text — and they include the locomotion set and // core combat moves the tables map to (Suplex, NeckBreaker, GermanSuplex, HurricaneRana, walking, // idle, running). Those fetched fine, parsed as garbage, threw, and the move played un-animated. // // Clips are now BAKED AHEAD OF TIME to the engine's own compact format // (tools/mocap/bake_clips.cjs, and tools/mocap/video_to_clip.py for anything captured from video) // and loaded as small JSON. JSON.parse of a 45 KB clip is sub-millisecond. No FBX at match time, // ever — window.ALLOW_RUNTIME_FBX=true re-enables it for authoring work only. window.loadClipFor = async function(name){ if(!name) return null; const base = String(name).replace(/\.fbx$/i,''); const key = base.toUpperCase().replace(/[^A-Z0-9]/g,'_'); try{ if(typeof STUDIO!=='undefined' && STUDIO.clips && (STUDIO.clips[base]||STUDIO.clips[key])) return STUDIO.clips[base]||STUDIO.clips[key]; }catch(e){} if(window.__fbxClipInFlight[key]) return window.__fbxClipInFlight[key]; window.__fbxClipInFlight[key] = (async()=>{ const cdn = window.MODEL_CDN_BASE || 'https://raw.githubusercontent.com/mhvnsnt/Bannon/main/'; // 0. a VARIANT is derived from its base, not fetched — no request, no stored file if(window.__deriveVariant){ const dv=await window.__deriveVariant(key); if(dv) return dv; } // 1. the baked clip — this is the path that should always win // gzipped-first (BANNON_CLIP_GZ). BOTH clip fetch sites go through the one helper — // this is the second, and the one loadCore() drives at boot. Fixing only the other one // would have left every boot-warmed capture on the network path. try{ const clip = await window.__clipJsonFetch(key, cdn); if(clip){ if(typeof STUDIO!=='undefined'){ STUDIO.clips=STUDIO.clips||{}; STUDIO.clips[key]=clip; STUDIO.clips[base]=clip; } return clip; } }catch(e){} // 2. raw FBX, for authoring only. Off by default because this is what froze the game. if(window.ALLOW_RUNTIME_FBX===true && typeof THREE!=='undefined' && THREE.FBXLoader){ const urls = ['assets/mocap/drive/'+encodeURIComponent(base)+'.fbx','assets/mocap/'+encodeURIComponent(base)+'.fbx', cdn+'assets/mocap/drive/'+encodeURIComponent(base)+'.fbx']; for(const u of urls){ try{ const r=await fetch(u).catch(()=>null); if(!r||!r.ok) continue; const buf=await r.arrayBuffer(); // an LFS pointer is ~130 bytes of ASCII starting "version https://git-lfs" — parsing it // throws deep inside FBXLoader, so recognise it and say so instead if(buf.byteLength<4096){ const head=new TextDecoder().decode(new Uint8Array(buf).slice(0,32)); if(head.indexOf('version https://git-lfs')===0){ console.warn('[clip] '+base+'.fbx is an LFS pointer, not data'); continue; } } const obj=(new THREE.FBXLoader()).parse(buf,''); if(obj.animations && obj.animations.length){ const clip=(typeof extractClipFromGLTF==='function')?extractClipFromGLTF(obj.animations[0],obj):obj.animations[0]; if(typeof STUDIO!=='undefined'){ STUDIO.clips=STUDIO.clips||{}; STUDIO.clips[key]=clip; STUDIO.clips[base]=clip; } return clip; } }catch(e){} } } return null; })(); const c = await window.__fbxClipInFlight[key]; delete window.__fbxClipInFlight[key]; return c; }; // ══ ONE FETCH AT BOOT for the whole core set ═══════════════════════════════════════════════ // core.json holds every locomotion + core combat clip inlined. One request, parsed once, off the // critical path — so the first strike of the first match is already animated instead of kicking // off a load. Failure here is silent and harmless: loadClipFor still fetches individual clips. window.__coreClipsReady = (async function(){ try{ const cdn = window.MODEL_CDN_BASE || 'https://raw.githubusercontent.com/mhvnsnt/Bannon/main/'; for(const u of ['assets/moves/clips/core.json', cdn+'assets/moves/clips/core.json']){ const r = await fetch(u).catch(()=>null); if(!r||!r.ok) continue; const all = await r.json(); if(typeof STUDIO==='undefined') return 0; STUDIO.clips = STUDIO.clips || {}; let n=0; for(const k in all){ if(!STUDIO.clips[k]){ STUDIO.clips[k]=all[k]; n++; } } console.log('%c[clips] '+n+' baked clips resident — no FBX parse at match time','color:#7CFC00'); return n; } }catch(e){} return 0; })(); try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'mocap.bulk_load', kind: 'forge', summary: 'Batch loads root environment .fbx files directly into STUDIO.clips & MOVEDEX using WWE 2K category heuristics.', call: 'window.BANNON_LOAD_FBX_LIBRARY()' }); } catch(e) {} })(); /* BANNON SYSTEM BRICK 89 — NODE 4: SPATIAL ENVIRONMENT / OPAQUE ARENA SUITE */ (function() { window.BANNON_LOAD_ARENA_ASSETS = async function() { if (typeof THREE === 'undefined' || typeof THREE.FBXLoader === 'undefined') { console.error('[NODE 4] FBXLoader must be loaded to import arena assets.'); return; } const ARENA_ASSETS = [ 'uploads_files_2434745_ringsalefbx.fbx', 'uploads_files_4374447_Chair_steel.fbx' ]; console.log(`[NODE 4 - SPATIAL ENVIRONMENT] Starting bulk import of ${ARENA_ASSETS.length} Arena FBX files...`); const loader = new THREE.FBXLoader(); for (const file of ARENA_ASSETS) { try { const response = await fetch('/' + encodeURIComponent(file)); if (!response.ok) continue; const buffer = await response.arrayBuffer(); const fbx = loader.parse(buffer, ''); // Arena Placement Node Logic if (file.toLowerCase().includes('ring')) { fbx.scale.set(0.01, 0.01, 0.01); fbx.position.set(0, 0, 0); if (typeof arenaGroup !== 'undefined') arenaGroup.add(fbx); else if (typeof scene !== 'undefined') scene.add(fbx); console.log(`[NODE 4] Injected Arena Asset: ${file}`); // Implement strict frustum culling and lock static matrices for background props fbx.traverse((child) => { if (child.isMesh) { child.frustumCulled = true; // Disable auto-update for static background rendering boosts child.matrixAutoUpdate = false; child.updateMatrix(); } }); if (window.BPHYS && window.BPHYS.rebuildRing) { try { window.BPHYS.rebuildRing(); } catch (e) {} } } else if (file.toLowerCase().includes('chair')) { fbx.scale.set(0.015, 0.015, 0.015); fbx.position.set(4.5, 0, 4.5); // Place just outside the ropes if (typeof scene !== 'undefined') scene.add(fbx); console.log(`[NODE 4] Injected Prop Asset: ${file}`); } } catch (e) { console.warn(`[NODE 4] Failed to load arena asset ${file}:`, e); } } }; try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick89.node4_arena_suite', kind: 'spatial-environment', summary: 'Node 4 Spatial Environment (Arena & Props). Dedicated loader for rings and steel chairs separation.', call: 'window.BANNON_LOAD_ARENA_ASSETS()' }); } catch(e) {} console.log('%c[BANNON · BRICK 89] NODE 4 SPATIAL ENVIRONMENT ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 90 — NODE 11: CREATION SUITE / CHARACTER ASSETS */ (function() { window.BANNON_LOAD_CHARACTER_ASSETS = async function() { if (typeof THREE === 'undefined' || typeof THREE.FBXLoader === 'undefined') { console.error('[NODE 11] FBXLoader must be loaded to import character assets.'); return; } const CHAR_ASSETS = [ // Extracted distinct character models (e.g. custom Titan/Cruiserweight rigs) will be arrayed here ]; console.log(`[NODE 11 - CREATION SUITE] Character Asset loader ready. Intercepting ${CHAR_ASSETS.length} files...`); // We will process these distinct models via the Creation Suite isolated scene, not the arena. }; try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick90.node11_character_suite', kind: 'creation-suite', summary: 'Node 11 Creation Suite. Dedicated parsing pathway for distinct fighter character models.', call: 'window.BANNON_LOAD_CHARACTER_ASSETS()' }); } catch(e) {} console.log('%c[BANNON · BRICK 90] NODE 11 CREATION SUITE ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 91 — NODE 5 KINEMATIC CORE: WEAPON-GRIP IK CONSTRAINT */ (function() { if (typeof Fighter === 'undefined') return; const _origSolve = Fighter.prototype.solveLimbIK; if (_origSolve) { Fighter.prototype.solveLimbIK = function() { _origSolve.call(this); // Weapon Grip IK Constraint // If the fighter has a bound weapon (e.g. Steel Chair), forcibly pull the hands // to the local grip coordinates of the weapon mesh. if (this.weaponProp && this.J && this.J['haL'] && this.J['haR']) { // Ensure the weapon respects gravity/momentum natively or follows root if (this.weaponProp.matrixWorld) { const lHandTarget = new THREE.Vector3(-0.35, 0.1, 0.4).applyMatrix4(this.weaponProp.matrixWorld); const rHandTarget = new THREE.Vector3(0.35, 0.1, 0.4).applyMatrix4(this.weaponProp.matrixWorld); // Clamp hand positional data directly to the prop's spatial coordinates this.J['haL'].pos.lerp(lHandTarget, 0.85); this.J['haR'].pos.lerp(rHandTarget, 0.85); } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick91.weapon_grip_ik', kind: 'physics-stability', summary: 'Node 5: Kinematic weapon-grip constraint. Hands visually and physically lock onto the coordinates of equipped props (like Steel Chairs) carrying real mass.', call: 'Fighter.prototype.solveLimbIK weapon-grip' }); } catch(e) {} console.log('%c[BANNON · BRICK 91] NODE 5 WEAPON-GRIP IK CONSTRAINT ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 92 — NODE 7 COMBAT AI: GOAL-ORIENTED ACTION PLANNING */ (function() { if (typeof Fighter === 'undefined') return; const _origUpdateAI = Fighter.prototype.updateAI; if (_origUpdateAI) { Fighter.prototype.updateAI = function(dt) { // GOAP Predicate Evaluation (Before Behavior Tree execution) if (!this.isPlayer && this.parts && this.state !== 'attack' && this.state !== 'block') { const opp = this.opponent(); if (opp) { // GOAL: Protect damaged left/right leg autonomously if (this.parts.legL > 65 && this.stance !== 'southpaw') { this.stance = 'southpaw'; } else if (this.parts.legR > 65 && this.stance !== 'orthodox') { this.stance = 'orthodox'; } // GOAL: Assess arena coordinates to avoid getting cornered const arenaHalf = typeof ARENA_HALF !== 'undefined' ? ARENA_HALF : 3.5; const arenaHalfZ = typeof ARENA_HALF_Z !== 'undefined' ? ARENA_HALF_Z : 3.5; const distToRopeX = arenaHalf - Math.abs(this.x); const distToRopeZ = arenaHalfZ - Math.abs(this.z); if (distToRopeX < 1.0 || distToRopeZ < 1.0) { // AI realizes it is cornered; increase lateral movement priority this._cornerPanic = (this._cornerPanic || 0) + dt; if (this._cornerPanic > 1.5) { this.wantMove = 1; this._lastMoveIx = opp.x > 0 ? -1 : 1; this._lastMoveIz = opp.z > 0 ? -1 : 1; } } else { this._cornerPanic = 0; } // GOAL: Regulate cardiovascular output (Stamina Drops) if (this.stamina < 20) { this.aggressionFactor = 0.2; // Severely pull back attacks } else if (this.stamina > 80) { this.aggressionFactor = 1.2; // Unload } } } // Execute absolute fallback to unified BT or prior zone logic _origUpdateAI.call(this, dt); }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick92.node7_goap_ai', kind: 'combat-ai', summary: 'Node 7 Goal-Oriented Action Planning. AI dynamically reads stamina drops, local limb damage (auto-stance switching), and spatial coordinate trapping.', call: 'Fighter.prototype.updateAI goap-eval' }); } catch(e) {} console.log('%c[BANNON · BRICK 92] NODE 7 COMBAT AI (GOAP) ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK — VRM ANATOMICAL POLE VECTOR PROJECTION */ (function() { if (typeof Fighter === 'undefined') return; const _origTwoBoneIK = Fighter.prototype._twoBoneIK; if (!_origTwoBoneIK) return; Fighter.prototype._twoBoneIK = function(sh, el, ha, a, b, pole) { if (!this.J || !this.J[sh] || !this.J[ha] || !this.J['spineLow'] || !this.J['chest'] || !this.J['shL'] || !this.J['shR']) { _origTwoBoneIK.call(this, sh, el, ha, a, b, pole); return; } // 1. Determine local body axis const up = new THREE.Vector3().subVectors(this.J['chest'].pos, this.J['spineLow'].pos).normalize(); let right = new THREE.Vector3().subVectors(this.J['shR'].pos, this.J['shL'].pos).normalize(); // Fallback if (right.lengthSq() < 0.1 || isNaN(right.x)) { const fxy = typeof this.forward === 'function' ? this.forward() : {x:0, z:-1}; right.set(fxy.z, 0, -fxy.x).normalize(); } if (up.lengthSq() < 0.1 || isNaN(up.x)) { up.set(0,1,0); } // 2. Anatomical forward (right hand rule correction) // up x right = forward const fwd = new THREE.Vector3().crossVectors(up, right); if (fwd.lengthSq() < 0.001) { fwd.set(0, 0, -1); // Failsafe } else { fwd.normalize(); } // 3. Project definitive pole tracking coordinate let dyPole = new THREE.Vector3(); if (sh === 'shL' || sh === 'shR') { // ELBOWS: Bend backward + outward + slightly down const isLeft = (sh === 'shL'); const out = right.clone().multiplyScalar(isLeft ? -1 : 1); dyPole.copy(fwd).multiplyScalar(-1.5); dyPole.add(out.multiplyScalar(0.7)); dyPole.add(up.multiplyScalar(-0.4)); pole = { x: dyPole.x, y: dyPole.y, z: dyPole.z }; } else if (sh === 'hipL' || sh === 'hipR') { // KNEES: Bend purely forward dyPole.copy(fwd).multiplyScalar(2.0); pole = { x: dyPole.x, y: dyPole.y, z: dyPole.z }; } _origTwoBoneIK.call(this, sh, el, ha, a, b, pole); }; try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'physics.vrm_pole_vector', kind: 'physics', summary: 'Brick: True VRM IK pole vectors dynamically locked using chest/spine cross products. Permanently fixes geometric backward arm/leg mesh inversions.', call: 'Fighter.prototype._twoBoneIK pole override' }); } catch(e) {} console.log('%c[BANNON] VRM ANATOMICAL POLE VECTORS — injected', 'color:#ff00ff;font-weight:bold'); })(); (function installBrick57(){ 'use strict'; if(window.__brick57) return; window.__brick57 = true; if(typeof Fighter === 'undefined') return; // ── 1. DISABLE UNINTENTIONAL AUTO-ZONING ───────────────────────────────── // We surgically mask the velocity and inputs for the duration of the // updateZone call so the logic always sees a stationary fighter. This kills // the automatic walk-off while preserving the v93 wrappers and ZONE button. const _v93UpdateZone = Fighter.prototype.updateZone; if (typeof _v93UpdateZone === 'function') { Fighter.prototype.updateZone = function(dt) { // Save real movement data const _vx = this.vx, _vz = this.vz; const _ix = this._lastMoveIx, _iz = this._lastMoveIz; // Mask movement to neutralize auto-zone threshold timers this.vx = 0; this.vz = 0; this._lastMoveIx = 0; this._lastMoveIz = 0; _v93UpdateZone.call(this, dt); // Restore real movement data this.vx = _vx; this.vz = _vz; this._lastMoveIx = _ix; this._lastMoveIz = _iz; }; } // ── 2. PREVENT FLOOR CLIPPING UNDER THE RING MAT ───────────────────────── // Replaces _zoneClamp to enforce a hard exclusion zone. If a fighter is // legitimately in the 'FLOOR' zone, they are physically blocked from // walking back underneath the ring apron and clipping through the geometry. Fighter.prototype._zoneClamp = function() { const AH = ARENA_HALF, AHZ = (typeof ARENA_HALF_Z !== 'undefined' ? ARENA_HALF_Z : 2.2); // Allow transition animations (climbing in/out) to move freely across bounds if (this.state === 'apron' || this.state === 'ringIn' || this.state === 'ringOut') { const SAFE = AH * 1.6, SAFE_Z = AHZ * 1.6; this.x = clamp(this.x, -SAFE, SAFE); this.z = clamp(this.z, -SAFE_Z, SAFE_Z); return; } if (this.zone === 'APRON') { const side = this.apronSide || 'X+'; if (side === 'X+') { this.x = clamp(this.x, AH + 0.16, AH + 0.42); this.z = clamp(this.z, -AHZ, AHZ); } else if (side === 'X-') { this.x = clamp(this.x, -(AH + 0.42), -(AH + 0.16)); this.z = clamp(this.z, -AHZ, AHZ); } else if (side === 'Z+') { this.z = clamp(this.z, AHZ + 0.16, AHZ + 0.42); this.x = clamp(this.x, -AH, AH); } else { this.z = clamp(this.z, -(AHZ + 0.42), -(AHZ + 0.16)); this.x = clamp(this.x, -AH, AH); } } else if (this.zone === 'FLOOR') { const AW = 0.45; // Apron width outer limit const absX = Math.abs(this.x); const absZ = Math.abs(this.z); // Hard collision: block entry to the space under the ring + apron if (absX < AH + AW && absZ < AHZ + AW) { // Determine nearest valid escape edge and eject if ((AH + AW) - absX < (AHZ + AW) - absZ) { this.x = Math.sign(this.x || 1) * (AH + AW); } else { this.z = Math.sign(this.z || 1) * (AHZ + AW); } } // Outer floor bounds this.x = clamp(this.x, -(AH + 1.4), AH + 1.4); this.z = clamp(this.z, -(AHZ + 1.2), AHZ + 1.2); } else { // RING zone bounds this.x = clamp(this.x, -AH, AH); this.z = clamp(this.z, -AHZ, AHZ); } }; try{ window.MANIFESTO && window.MANIFESTO.register({ key: 'brick57.zone_fix', kind: 'physics-bounds', summary: 'Kills accidental auto-walk-off zoning by masking inputs during updateZone. Reinforces _zoneClamp so FLOOR fighters cannot clip under the ring mat.', call: 'Fighter.prototype.updateZone wrap, Fighter.prototype._zoneClamp replace' }); } catch(e) {} console.log('%c[BANNON · BRICK 57] MAT CLIPPING & AUTO-ZONE FIX ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK — RAGDOLL ANGULAR MOMENTUM TRANSFER */ (function() { if (typeof Fighter === 'undefined') return; // 1. Store actual world joint positions every frame const _origUpdate = Fighter.prototype.update; if (_origUpdate) { Fighter.prototype.update = function(dt) { if (!this.ragdoll && this.J) { if (!this._prevWorldJ) this._prevWorldJ = {}; for (const j in this.J) { const wp = this.worldJoint(j); this._prevWorldJ[j] = wp; } } _origUpdate.call(this, dt); }; } // 2. Override seedRagdoll to inject that true velocity into Verlet nodes const _origSeed = Fighter.prototype.seedRagdoll; if (_origSeed) { Fighter.prototype.seedRagdoll = function() { _origSeed.call(this); // Let original set up V nodes, set ragdoll=true, etc. // Overgrowth Energy injection if (this.V && this._prevWorldJ) { for (const j in this.V) { if (this._prevWorldJ[j]) { const wp = this.worldJoint(j); const pwp = this._prevWorldJ[j]; // Calculate actual distance traveled in the last frame const dx = wp.x - pwp.x; const dy = wp.y - pwp.y; const dz = wp.z - pwp.z; // Limit the physical injection to prevent explosive velocity glitches const MAX_VEL = 0.5; // per frame max const vx = clamp(dx, -MAX_VEL, MAX_VEL); const vy = clamp(dy, -MAX_VEL, MAX_VEL); const vz = clamp(dz, -MAX_VEL, MAX_VEL); // Set the old coordinate backward so the verlet integrator // naturally throws the limb forward on the next physics step. this.V[j].old.x = wp.x - vx; this.V[j].old.y = wp.y - vy; this.V[j].old.z = wp.z - vz; } } } }; } try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'physics.angular_momentum_transfer', kind: 'physics', summary: 'Brick: Transfers true animated bone velocity directly into the Verlet ragdoll upon KO to preserve angular momentum.', call: 'Fighter.prototype.seedRagdoll velocity injection' }); } catch(e) {} console.log('%c[BANNON] RAGDOLL ANGULAR MOMENTUM TRANSFER — injected', 'color:#ff00ff;font-weight:bold'); })(); /* BANNON SYSTEM BRICK — RAYCAST-DRIVEN FOOT IK */ (function() { if (typeof Fighter === 'undefined' || typeof THREE === 'undefined') return; const _raycaster = new THREE.Raycaster(); const _down = new THREE.Vector3(0, -1, 0); // We patch solveFootIK to determine dynamic groundY via raycast const _origSolveFootIK = Fighter.prototype.solveFootIK; if (_origSolveFootIK) { Fighter.prototype.solveFootIK = function(dt, walking) { if (!this.J || !this.J['hipL'] || typeof rawScene === 'undefined') { _origSolveFootIK.call(this, dt, walking); return; } // Default let FP = (window.LOCO && window.LOCO.footPlant) || {}; let baselineGroundY = (FP.groundY != null ? FP.groundY : 0.05); // Perform a raycast straight down from the fighter's root/hips const origin = new THREE.Vector3(this.x, 2.0, this.z); _raycaster.set(origin, _down); // Assume rawScene holds the arena environment const intersects = _raycaster.intersectObject(rawScene, true); let dynamicGroundY = baselineGroundY; for (const hit of intersects) { // Exclude UI, helpers, and characters (keep it strictly environment) if (!hit.object.isFighter && !hit.object.userData.isHUD && hit.distance > 0) { dynamicGroundY = Math.max(baselineGroundY, hit.point.y + 0.05); break; } } // Temporarily override the LOCO groundY const oldGroundY = FP.groundY; if (!window.LOCO) window.LOCO = { footPlant: {} }; window.LOCO.footPlant.groundY = dynamicGroundY; _origSolveFootIK.call(this, dt, walking); // Restore if (oldGroundY !== undefined) { window.LOCO.footPlant.groundY = oldGroundY; } else { delete window.LOCO.footPlant.groundY; } }; } try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'physics.raycast_foot_ik', kind: 'physics', summary: 'Brick: Dynamic Raycast-Driven Foot IK. Replaces hardcoded floor planes with true vertical ray projections against rawScene geometry.', call: 'Fighter.prototype.solveFootIK dynamic groundY injection' }); } catch(e) {} console.log('%c[BANNON] RAYCAST-DRIVEN FOOT IK — injected', 'color:#ff00ff;font-weight:bold'); })(); /* BANNON SYSTEM BRICK — NARROWPHASE MULTI-BODY COLLISION */ (function() { if (typeof Fighter === 'undefined') return; const _origUpdateRagdoll = Fighter.prototype.updateRagdoll; if (_origUpdateRagdoll) { Fighter.prototype.updateRagdoll = function(dt) { _origUpdateRagdoll.call(this, dt); // Multi-body resolution: Check this ragdoll against ALL other fighters if (this.ragdoll && this.V && typeof fighters !== 'undefined') { const COLLISION_RADIUS = 0.25; const STIFFNESS = 0.4; for (const other of fighters) { if (other === this || !other.V) continue; // Simple particle-to-particle sweeping for narrowphase for (const keyA in this.V) { const vA = this.V[keyA]; for (const keyB in other.V) { const vB = other.V[keyB]; const dx = vB.pos.x - vA.pos.x; const dy = vB.pos.y - vA.pos.y; const dz = vB.pos.z - vA.pos.z; let dist = Math.hypot(dx, dy, dz); if (dist < COLLISION_RADIUS) { // Safeguard against NaN/Infinity repulsion explosions if (dist < 0.001) { dist = 0.001; } const overlap = COLLISION_RADIUS - dist; const resolve = (overlap / dist) * 0.5 * STIFFNESS; // Hard cap resolution velocity to prevent spaghetti limbs const maxResolve = 0.15; const ox = THREE.MathUtils.clamp(dx * resolve, -maxResolve, maxResolve); const oy = THREE.MathUtils.clamp(dy * resolve, -maxResolve, maxResolve); const oz = THREE.MathUtils.clamp(dz * resolve, -maxResolve, maxResolve); if (!vA.pinned) { vA.pos.x -= ox; vA.pos.y -= oy; vA.pos.z -= oz; } if (!vB.pinned) { vB.pos.x += ox; vB.pos.y += oy; vB.pos.z += oz; } } } } } } }; } try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'physics.narrowphase_multibody', kind: 'physics', summary: 'Brick: Narrowphase multi-body mass resolution. Dynamically resolves inter-character collisions via particle repulsion during ragdoll integration.', call: 'Fighter.prototype.updateRagdoll narrowphase append' }); } catch(e) {} console.log('%c[BANNON] NARROWPHASE MULTI-BODY COLLISION — injected', 'color:#ff00ff;font-weight:bold'); })(); /* BANNON SYSTEM BRICK 58 — OVERGROWTH VERLET VELOCITY CLAMP & SELF-COLLISION */ (function() { if (typeof Fighter === 'undefined') return; const _origUpdateRagdoll = Fighter.prototype.updateRagdoll; if (_origUpdateRagdoll) { Fighter.prototype.updateRagdoll = function(dt) { _origUpdateRagdoll.call(this, dt); if (this.ragdoll && this.V && typeof RING !== 'undefined') { const MAX_BONE_VEL = 0.35; // Maximum biological travel distance per frame (~21 m/s) const floorHeight = (this.zone === 'FLOOR') ? RING.floorY - 0.85 : RING.floorY; for (const j in this.V) { const v = this.V[j]; if (v && v.pos && v.old && !v.pinned) { // 1. Kinetic Energy Limit (Velocity Clamp) // Kills the infinite phantom momentum loops that cause jitter / seizing const dx = v.pos.x - v.old.x; const dy = v.pos.y - v.old.y; const dz = v.pos.z - v.old.z; const spd = Math.hypot(dx, dy, dz); if (spd > MAX_BONE_VEL) { const scale = MAX_BONE_VEL / spd; v.old.x = v.pos.x - (dx * scale); v.old.y = v.pos.y - (dy * scale); v.old.z = v.pos.z - (dz * scale); } // 2. Anatomical Self-Collision (Chest vs Wrists/Elbows) // Stops limbs from tunneling through the torso and inverting the mesh if (this.V['chest'] && (j === 'wrL' || j === 'wrR' || j === 'elL' || j === 'elR' || j === 'haL' || j === 'haR')) { const chest = this.V['chest']; const cx = v.pos.x - chest.pos.x; const cy = v.pos.y - chest.pos.y; const cz = v.pos.z - chest.pos.z; const cDist = Math.hypot(cx, cy, cz); const MIN_DIST = 0.18; // Biological volume radius of the torso if (cDist < MIN_DIST && cDist > 0.001) { const overlap = (MIN_DIST - cDist) / cDist * 0.5; v.pos.x += cx * overlap; v.pos.y += cy * overlap; v.pos.z += cz * overlap; } } // 3. Absolute Floor Penetration Bailout if (v.pos.y < floorHeight + 0.04) { v.pos.y = floorHeight + 0.04; // Bleed 90% vertical velocity on hard impact v.old.y = v.pos.y - (v.pos.y - v.old.y) * 0.1; } } } } }; } try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'brick58.overgrowth_stability', kind: 'physics-stability', summary: 'Caps maximum Verlet kinetic energy per frame and applies anatomical self-collision to stop limb inversion and jitter loops.', call: 'Fighter.prototype.updateRagdoll velocity limit append' }); } catch(e) {} console.log('%c[BANNON · BRICK 58] OVERGROWTH KINETIC CAP & SELF-COLLISION ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 59 — EUPHORIA SELF-PRESERVATION (ACTIVE FALL BRACING) */ (function() { if (typeof Fighter === 'undefined') return; const _origUR = Fighter.prototype.updateRagdoll; if (_origUR) { Fighter.prototype.updateRagdoll = function(dt) { _origUR.call(this, dt); // Active Ragdoll Muscular Bracing (Euphoria Paradigm) // Characters don't just go limp. They brace for impact, reaching hands // toward the ground and tucking the head upward to prevent trauma. if (this.ragdoll && this.V && this.downStage < 1.0) { const chest = this.V['chest']; const pelvis = this.V['pelvis']; const head = this.V['head']; // Stamina determines how hard the fighter works to brace const stamina = (this.stamina != null) ? this.stamina : 100; const awareness = Math.max(0, Math.min(1.0, stamina / 50.0)); if (awareness > 0.05 && chest && pelvis) { // Determine physical falling velocity if (chest.pos && chest.old) { const vy = chest.pos.y - chest.old.y; // Trigger panic bracing if actively falling fast or thrown if (vy < -0.015 || this.state === 'falling') { // Calculate skeletal facing direction (using Verlet world nodes) const sz = Math.sign(chest.pos.z - pelvis.pos.z) || 1; const sx = Math.sign(chest.pos.x - pelvis.pos.x) || 1; // 1. Hands reach down and array to break the fall for (const h of ['haL', 'haR']) { const hand = this.V[h]; if (hand && !hand.pinned && hand.pos) { hand.pos.y -= 0.06 * awareness; // Reach toward floor hand.pos.x += sx * 0.03 * awareness; // Spread out to catch weight hand.pos.z += sz * 0.03 * awareness; } } // 2. Neck Bracing Reflex (pull head up and back to avoid mat collision) if (head && !head.pinned && head.pos && head.old) { head.pos.y += 0.04 * awareness; // Pull up against gravity head.pos.x -= sx * 0.02 * awareness; // Pull back head.pos.z -= sz * 0.02 * awareness; // Dampen head velocity natively (stiffen neck muscles) head.old.x = head.old.x + (head.pos.x - head.old.x) * (0.1 * awareness); head.old.y = head.old.y + (head.pos.y - head.old.y) * (0.1 * awareness); head.old.z = head.old.z + (head.pos.z - head.old.z) * (0.1 * awareness); } // 3. Fetal Knee Tuck (pull knees up toward chest) for (const k of ['knL', 'knR']) { const knee = this.V[k]; if (knee && !knee.pinned && knee.pos) { knee.pos.y += 0.03 * awareness; knee.pos.x += sx * 0.02 * awareness; knee.pos.z += sz * 0.02 * awareness; } } } } } } }; } try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'brick59.euphoria_bracing', kind: 'physics-stability', summary: 'Euphoria-style active fall bracing. Verlet nodes (hands, head, knees) autonomously contract toward defensive postures when falling in ragdoll state.', call: 'Fighter.prototype.updateRagdoll append' }); } catch(e) {} console.log('%c[BANNON · BRICK 59] EUPHORIA FALL BRACING ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 60 — KINEMATIC STRIKE RETARGETING & GOAL-ORIENTED STANCES */ (function() { if (typeof Fighter === 'undefined') return; const _v3 = typeof THREE !== 'undefined' ? new THREE.Vector3() : null; // 1. Kinematic Target Tracking (Magnetic Homing for Strikes) const _origSolveIK = Fighter.prototype.solveLimbIK; if (_origSolveIK && _v3) { Fighter.prototype.solveLimbIK = function() { // Execute original kinematics first _origSolveIK.call(this); // Height and Angle Retargeting during strike execution if (this.state === 'attack' && this.attackData && this.attackPhase > 0.20 && this.attackPhase < 0.95) { const isLeft = this.attackData.limb && this.attackData.limb.includes('LEFT'); const hand = isLeft ? this.J.haL : this.J.haR; const opp = typeof this.opponent === 'function' ? this.opponent() : null; if (opp && opp.worldJoint && !this._whiffed && hand && hand.tgt && this.root) { // Lock onto height-appropriate limb based on move category const isHigh = this.attackData.height === 'HIGH' || this.attackData.height === 'OVERHEAD'; const tBoneName = isHigh ? 'head' : 'chest'; const worldHitbox = opp.worldJoint(tBoneName); if (worldHitbox) { _v3.copy(worldHitbox); this.root.updateMatrixWorld(true); this.root.worldToLocal(_v3); // Convert opponent bone into attacker's local coordinate space // Calculate magnetic pull based on strike temporal phase (peaks right before impact) const magPeak = Math.max(0, 1.0 - Math.abs(this.attackPhase - 0.75) * 3.5); const dx = _v3.x - hand.tgt.x; const dy = _v3.y - hand.tgt.y; const dz = _v3.z - hand.tgt.z; // Only auto-correct if within plausible biological range (don't stretch arms 3 meters) const distToTarget = Math.hypot(dx, dy, dz); if (distToTarget < 1.2) { // Interpolate the hand's kinematic target toward the opponent's actual bone mesh hand.tgt.y += dy * magPeak * 0.70; // Highly prioritize Y axis to fix short/tall gaps hand.tgt.x += dx * magPeak * 0.40; hand.tgt.z += dz * magPeak * 0.40; } } } } }; } // 2. Goal-Oriented Action Planning (Injury Stance Swap) const _origUpdate = Fighter.prototype.update; if (_origUpdate) { Fighter.prototype.update = function(dt) { _origUpdate.call(this, dt); // Autonomous Posture Protection if (this.parts && this.state !== 'down' && !this.ragdoll && this.root) { // Sum critical damage per side const leftDanger = (this.parts.legL || 100) + (this.parts.armL || 100); const rightDanger = (this.parts.legR || 100) + (this.parts.armR || 100); // Determine protective torque let offsetGoal = 0; if (leftDanger < rightDanger - 40 && leftDanger < 120) { offsetGoal = 0.45; // Angle left side away from opponent } else if (rightDanger < leftDanger - 40 && rightDanger < 120) { offsetGoal = -0.45; // Angle right side away from opponent } if (offsetGoal !== 0) { if (!this._injuryOffset) this._injuryOffset = 0; // Smooth blend this._injuryOffset += (offsetGoal - this._injuryOffset) * Math.min(1.0, dt * 2.0); // Apply directly to rendering root (overrides standard base orientation slightly) this.root.rotation.y += this._injuryOffset; } } }; } try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'brick60.kinematic_retargeting', kind: 'physics-stability', summary: 'Goal-oriented Stance Selection (Southpaw shifting for limb protection) and Kinematic Height Retargeting for strikes (arms magnetically correct trajectory to strike actual bone coordinates of different-sized opponents).', call: 'Fighter.prototype.update / solveLimbIK append' }); } catch(e) {} console.log('%c[BANNON · BRICK 60] KINEMATIC STRIKE RETARGETING & GOAL-ORIENTED STANCES ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 61 — EXANIMA CENTER OF MASS WEAPONIZATION */ (function() { if (typeof Fighter === 'undefined') return; const _origSolveIK = Fighter.prototype.solveLimbIK; if (_origSolveIK) { Fighter.prototype.solveLimbIK = function() { _origSolveIK.call(this); // Exanima-style Kinetic Pelvis Counter-Torque // A real punch doesn't just move the arm; the pelvis shifts oppositely to anchor the center of mass. if (this.state === 'attack' && this.attackPhase > 0.1 && this.attackPhase < 0.8 && this.attackData && this.J) { const isLeft = this.attackData.limb && this.attackData.limb.includes('LEFT'); const hand = isLeft ? this.J.haL : this.J.haR; const shoulder = isLeft ? this.J.shL : this.J.shR; const dx = hand.pos.x - shoulder.pos.x; const dz = hand.pos.z - shoulder.pos.z; // Power delivery phase (hips fire into the strike) if (this.attackPhase > 0.3 && hand.tgt) { const kineticSnap = Math.sin((this.attackPhase - 0.3) / 0.5 * Math.PI); // Arc from 0 to 1 to 0 // Push pelvis opposite to the arm extension to simulate weight transfer if (this.J.pelvis && this.J.chest && this.J.pelvis.tgt && this.J.chest.tgt) { this.J.pelvis.tgt.x -= dx * 0.15 * kineticSnap; this.J.pelvis.tgt.z -= dz * 0.15 * kineticSnap; // Chest leans into the strike this.J.chest.tgt.x += dx * 0.12 * kineticSnap; this.J.chest.tgt.z += dz * 0.12 * kineticSnap; } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick61.exanima_kinetics', kind: 'physics-stability', summary: 'Center of mass weaponization. Calculates pelvis counter-torque during strikes to generate raw physical momentum instead of floating arms.', call: 'Fighter.prototype.solveLimbIK pelvis inverse snap' }); } catch(e) {} console.log('%c[BANNON · BRICK 61] EXANIMA CENTER OF MASS WEAPONIZATION ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 62 — EUPHORIA INVERTED PENDULUM BALANCING */ (function() { if (typeof Fighter === 'undefined') return; const _origStumble = Fighter.prototype._tickStumble; if (_origStumble) { Fighter.prototype._tickStumble = function(dt) { _origStumble.call(this, dt); if (this._stumbleMag > 0.01 && this.J && this.state !== 'down' && !this.ragdoll) { // Euphoria Inverted Pendulum Math // Calculate the center of mass (chest/lumbar) relative to the feet const leftFoot = this.J.ftL.pos; const rightFoot = this.J.ftR.pos; const chest = this.J.chest.pos; const midFootX = (leftFoot.x + rightFoot.x) * 0.5; const midFootZ = (leftFoot.z + rightFoot.z) * 0.5; const comOffsetX = chest.x - midFootX; const comOffsetZ = chest.z - midFootZ; // PD Controller pulling chest back over the feet const pGain = 1.8; const correctiveX = -comOffsetX * pGain * dt; const correctiveZ = -comOffsetZ * pGain * dt; // Apply torque forces to spine nodes to fight falling over if (this.J.chest) { this.J.chest.x += correctiveX; this.J.chest.z += correctiveZ; } if (this.J.head) { this.J.head.x += correctiveX * 1.5; // Head overcorrects (whiplash stabilization) this.J.head.z += correctiveZ * 1.5; } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick62.euphoria_pendulum', kind: 'physics-stability', summary: 'Euphoria-style inverted pendulum PD balancing. Dynamically pulls the center of mass (chest/head) back over the feet during stagger states.', call: 'Fighter.prototype._tickStumble append' }); } catch(e) {} console.log('%c[BANNON · BRICK 62] EUPHORIA INVERTED PENDULUM BALANCE ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 63 — BULLET PHYSICS CONE-TWIST JOINT LOCKS */ (function() { if (typeof Fighter === 'undefined') return; const _origUR = Fighter.prototype.updateRagdoll; if (_origUR) { Fighter.prototype.updateRagdoll = function(dt) { _origUR.call(this, dt); // Strict Cone-Twist Joint Clamping (Bullet Physics Math) if (this.ragdoll && this.V) { // Function to enforce that Node C stays within a safe angle relative to A-B bone const enforceConeTwist = (nodeA, nodeB, nodeC, safeAngleDeg, dirMask) => { if (!this.V[nodeA] || !this.V[nodeB] || !this.V[nodeC]) return; const A = this.V[nodeA]; const B = this.V[nodeB]; const C = this.V[nodeC]; // Vector from B to C (e.g. elbow to hand) const vx = C.pos.x - B.pos.x; const vy = C.pos.y - B.pos.y; const vz = C.pos.z - B.pos.z; const fwd = typeof this.forward === 'function' ? this.forward() : {x: 0, z: -1}; const vzLocal = vx * fwd.x + vz * fwd.z; // Project to forward axis const vxLocal = vx * -fwd.z + vz * fwd.x; // Project to right axis // Knees bend forward (positive vzLocal is bad if lower leg goes backward from upper leg? No, knees bend forward, so lower leg bends backward relative to the thigh. So V shape forms backward) // Actually, the lower leg should not bend FORWARD of the knee. `vzLocal > 0.05` is bad. if (dirMask === 'KNEE') { if (vzLocal > 0.05) { const penalty = (vzLocal - 0.05) * 0.4; C.pos.x -= fwd.x * penalty; C.pos.z -= fwd.z * penalty; if (C.old) { C.old.x = C.pos.x; C.old.z = C.pos.z; } } } // Elbows bend backward. Lower arm should not bend FORWARD of elbow. But wait, elbows bend backward/inward. So `vzLocal > 0.05` might also be bad. if (dirMask === 'ELBOW') { if (vzLocal > 0.05) { const penalty = (vzLocal - 0.05) * 0.4; C.pos.x -= fwd.x * penalty; C.pos.z -= fwd.z * penalty; if (C.old) { C.old.x = C.pos.x; C.old.z = C.pos.z; } } } }; enforceConeTwist('hipL', 'knL', 'ftL', 20, 'KNEE'); enforceConeTwist('hipR', 'knR', 'ftR', 20, 'KNEE'); enforceConeTwist('shL', 'elL', 'haL', 20, 'ELBOW'); enforceConeTwist('shR', 'elR', 'haR', 20, 'ELBOW'); } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick63.bullet_cone_twist', kind: 'physics-stability', summary: 'Bullet Physics style Cone-Twist Joint Limits limits. Prevents unnatural reverse-bending of elbows and knees dynamically in the Verlet solver.', call: 'Fighter.prototype.updateRagdoll append' }); } catch(e) {} console.log('%c[BANNON · BRICK 63] BULLET CONE-TWIST JOINT LOCKS ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 64 — JOLT PHYSICS MATERIAL SLIPPAGE (SWEAT) */ (function() { if (typeof Fighter === 'undefined') return; const _origPoseGrab = Fighter.prototype.poseGrab; if (_origPoseGrab) { Fighter.prototype.poseGrab = function(dt) { _origPoseGrab.call(this, dt); // Sweat Friction Slipping // When grappling for an extended period, heavy sweat (low stamina) causes the grip to slide. if (this.grappling && this.grabTarget && this.grappleStage >= 1 && this.grappleStage < 4) { const opp = this.grabTarget; const myStam = (this.stamina != null) ? this.stamina : 100; const oppStam = (opp.stamina != null) ? opp.stamina : 100; const fatigueFactor = 1.0 - (myStam / 100.0); const sweatFactor = 1.0 - (oppStam / 100.0); // If both are exhausted and sweating heavily, there is a chance the grip slips if (fatigueFactor > 0.5 && sweatFactor > 0.5) { // Apply micro-slips to the opponent's Y lock to simulate fighting for a sweaty grip const sweatVariance = Math.random() * (fatigueFactor * sweatFactor * 0.05); if (this._lockY != null) { this._lockY -= sweatVariance; // Target slowly sinks out of grip // If the target drops dangerously low, break the grip entirely if (this.grappleStage !== 1 && this._lockY < 0.2) { // Jolt physics material slip failure if (this._gripStrain != null) this._gripStrain += 50; // Force an immediate break } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick64.jolt_friction', kind: 'physics-stability', summary: 'Jolt Physics local friction overrides. Grapple holds dynamically slip and lose lock altitude based on inverse stamina values (simulating heavy sweat and muscle fatigue).', call: 'Fighter.prototype.poseGrab append' }); } catch(e) {} console.log('%c[BANNON · BRICK 64] JOLT PHYSICS GRAPPLE FRICTION (SWEAT) ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 65 — GISH VOLUME PRESERVATION (SQUASH & STRETCH) */ (function() { if (typeof Fighter === 'undefined') return; const _origHit = Fighter.prototype.applyHit; if (_origHit) { Fighter.prototype.applyHit = function(dmg, region, atk) { _origHit.call(this, dmg, region, atk); // Gish Volume Preservation Math // When flesh takes impact, it doesn't just disappear; the volume displaces laterally. if (dmg > 5 && this.root && this.root.scale) { let maxSquash = Math.min(0.2, dmg / 50.0); // Temporarily warp the mesh scale (volume preserved: scaleY * scaleX * scaleZ = 1.0) this._volumeSquashTarget = maxSquash; } }; } const _origUpdate = Fighter.prototype.update; if (_origUpdate) { Fighter.prototype.update = function(dt) { _origUpdate.call(this, dt); if (this.root && this.root.scale) { if (!this._volumeSquashAmount) this._volumeSquashAmount = 0; if (!this._volumeSquashTarget) this._volumeSquashTarget = 0; // Spring toward target squash (instant compress, slow release) if (this._volumeSquashAmount < this._volumeSquashTarget) { this._volumeSquashAmount += (this._volumeSquashTarget - this._volumeSquashAmount) * 0.8; } else { // Decay target back to zero this._volumeSquashTarget = 0; this._volumeSquashAmount += (0 - this._volumeSquashAmount) * 0.15; // Slow return to normal } // Apply Volume Preservation // If Y is compressed by X%, X and Z must expand to maintain the volume const squash = this._volumeSquashAmount; const scaleY = 1.0 - squash; // Clamp scaleY to prevent dividing by 0 const safeScaleY = Math.max(0.1, scaleY); const scaleXZ = Math.sqrt(1.0 / safeScaleY); this.root.scale.set(scaleXZ, safeScaleY, scaleXZ); } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick65.gish_volume', kind: 'physics-stability', summary: 'Gish volume preservation algorithm. Hard impacts compress the physical mesh on the Y axis while mathematically bulging the X and Z axes to preserve biological mass.', call: 'Fighter.prototype.applyHit / update append' }); } catch(e) {} console.log('%c[BANNON · BRICK 65] GISH VOLUME PRESERVATION ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 66 — RIGS OF RODS SOFT BODY CANVAS DEFORMATION */ (function() { if (typeof Fighter === 'undefined') return; const _origUR = Fighter.prototype.updateRagdoll; if (_origUR) { Fighter.prototype.updateRagdoll = function(dt) { // Local canvas deformation state if (!this._canvasDepression) this._canvasDepression = 0; let maxImpact = 0; if (this.V && this.zone === 'RING') { // Check for heavy spinal impacts on the floor const chest = this.V['chest']; if (chest && chest.pos && chest.old) { const vy = chest.pos.y - chest.old.y; // Floor height const floorY = typeof RING !== 'undefined' ? RING.floorY : 0; if (chest.pos.y < floorY + 0.3 && vy < -0.05) { maxImpact = Math.abs(vy); } } } // Deform the canvas locally if (maxImpact > 0.05) { this._canvasDepression += maxImpact * 0.4; } // Rigs of Rods Damped Harmonic Oscillator (Spring) const k = 15.0; // Stiffness const d = 3.0; // Damping const accel = -k * this._canvasDepression - d * (this._canvasVelocity || 0); this._canvasVelocity = (this._canvasVelocity || 0) + accel * dt; this._canvasDepression += this._canvasVelocity * dt; // Prevent canvas from bouncing above resting height if (this._canvasDepression < 0) { this._canvasDepression = 0; this._canvasVelocity = 0; } // Tell floor solver to let the fighter sink into this temporary depression const _origRagFloorOffset = window._v98_ragFloorOffset || 0; window._v98_ragFloorOffset = _origRagFloorOffset - this._canvasDepression; _origUR.call(this, dt); // Restore window._v98_ragFloorOffset = _origRagFloorOffset; }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick66.rigs_of_rods_canvas', kind: 'physics-stability', summary: 'Rigs of Rods soft body deformation. The ring canvas acts as a damped harmonic oscillator, physically absorbing heavy slams by temporarily depressing beneath the fighter rather than acting like concrete.', call: 'Fighter.prototype.updateRagdoll append' }); } catch(e) {} console.log('%c[BANNON · BRICK 66] RIGS OF RODS SOFT BODY CANVAS ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 67 — XASH3D SPATIAL PREDICTION (FOOT PLANTING) */ (function() { if (typeof Fighter === 'undefined') return; const _origUR = Fighter.prototype.updateRagdoll; if (_origUR) { Fighter.prototype.updateRagdoll = function(dt) { _origUR.call(this, dt); // Xash3D Movement Prediction if (this.V && this.ragdoll) { const floorY = (this.zone === 'FLOOR' && typeof RING !== 'undefined') ? RING.floorY - 0.85 : (typeof RING !== 'undefined' ? RING.floorY : 0); for (const ft of ['ftL', 'ftR', 'knL', 'knR', 'head']) { const v = this.V[ft]; if (v && v.pos && v.old && !v.pinned) { const vy = v.pos.y - v.old.y; // If moving downward rapidly if (vy < -0.02) { // Predict position 3 frames in the future const projectedY = v.pos.y + (vy * 3.0); // If the projection clips through the floor if (projectedY < floorY) { // Apply immediate deceleration force natively to the Verlet integrator // to ensure a soft plant rather than a violent tunnel-clip const penetrationRisk = floorY - projectedY; v.old.y -= penetrationRisk * 0.15; // Bleed velocity early } } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick67.xash3d_prediction', kind: 'physics-stability', summary: 'Xash3D movement prediction matrices. Computes projected vertex coordinates 3 frames into the future and decelerates limbs before they can tunnel through the floor plane.', call: 'Fighter.prototype.updateRagdoll append' }); } catch(e) {} console.log('%c[BANNON · BRICK 67] XASH3D SPATIAL MOVEMENT PREDICTION ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 68 — PROJECT CHRONO BIOMECHANICAL FATIGUE */ (function() { if (typeof Fighter === 'undefined') return; const _origSolveIK = Fighter.prototype.solveLimbIK; if (_origSolveIK) { Fighter.prototype.solveLimbIK = function() { // Execute standard kinematic targets _origSolveIK.call(this); // Project Chrono Biological Torque Decay // Arms lift slower and drop heavier as the stamina pool drains if (this.J && this.stamina != null) { const exhaustLvl = Math.max(0, 1.0 - (this.stamina / 100)); // 0 to 1 if (exhaustLvl > 0.1) { // Actuate the hand joints for (const h of ['haL', 'haR']) { const hand = this.J[h]; if (hand && hand.tgt && hand.pos) { const dy = hand.tgt.y - hand.pos.y; // Lifting against gravity (dy > 0) if (dy > 0) { // Muscle torque decay: apply lag when lifting arms hand.tgt.y -= dy * exhaustLvl * 0.45; // Slows ascent } else { // Gravity assist: arms fall slightly heavier/further hand.tgt.y += Math.abs(dy) * exhaustLvl * 0.20; // Accelerates descent } } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick68.chrono_biomechanics', kind: 'physics-stability', summary: 'Project Chrono muscular actuation simulation. Injects fatigue decay curves into the spatial solver, causing limbs to physically lift slower against gravity and drop heavier when exhausted.', call: 'Fighter.prototype.solveLimbIK append' }); } catch(e) {} console.log('%c[BANNON · BRICK 68] PROJECT CHRONO BIOMECHANICAL FATIGUE ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 69 — OPEN DYNAMICS ENGINE (ODE) ABSOLUTE STABILITY DAEMON */ (function() { if (typeof Fighter === 'undefined') return; const _origUR = Fighter.prototype.updateRagdoll; if (_origUR) { Fighter.prototype.updateRagdoll = function(dt) { // NaN EXORCIST FIREWALL if (this.V) { for (const j in this.V) { const v = this.V[j]; if (v && v.pos) { if (!isFinite(v.pos.x) || !isFinite(v.pos.y) || !isFinite(v.pos.z)) { const safeWp = this.worldJoint ? this.worldJoint(j) : {x: this.x, y: 1.0, z: this.z}; if (safeWp && isFinite(safeWp.x) && isFinite(safeWp.y) && isFinite(safeWp.z)) { v.pos.x = safeWp.x; v.pos.y = safeWp.y; v.pos.z = safeWp.z; v.old.x = safeWp.x; v.old.y = safeWp.y; v.old.z = safeWp.z; } else { v.pos.x = this.x || 0; v.pos.y = 1.0; v.pos.z = this.z || 0; v.old.x = this.x || 0; v.old.y = 1.0; v.old.z = this.z || 0; } } } } } _origUR.call(this, dt); if (this.V) { for (const j in this.V) { const v = this.V[j]; if (v && v.pos) { if (!isFinite(v.pos.x) || !isFinite(v.pos.y) || !isFinite(v.pos.z)) { v.pos.x = this.x || 0; v.pos.y = 1.0; v.pos.z = this.z || 0; v.old.x = v.pos.x; v.old.y = v.pos.y; v.old.z = v.pos.z; } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick69.ode_stability_daemon', kind: 'physics-stability', summary: 'Open Dynamics Engine absolute NaN / Infinity firewall. Completely eradicates game-breaking structural explosions / spaghetti limbs.', call: 'Fighter.prototype.updateRagdoll matrix sanitize' }); } catch(e) {} console.log('%c[BANNON · BRICK 69] OPEN DYNAMICS ENGINE: NaN / INFINITY FIREWALL ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 70 — OVERGROWTH JOINT STRESS DEFORMATION */ (function() { if (typeof Fighter === 'undefined') return; const _origAR = Fighter.prototype.updateActiveRagdoll; if (_origAR) { Fighter.prototype.updateActiveRagdoll = function(dt) { _origAR.call(this, dt); if (this.J && this._arV) { if (this.state === 'hurt' || this.state === 'flinch' || this.state === 'stumble') { const stressMultiplier = Math.min(1.0, (this._stumbleMag || 0.5) * 1.5); for (const h of ['haL', 'haR', 'ftL', 'ftR']) { const kinematic = this.J[h]; const physical = this._arV[h]; if (kinematic && physical && physical.pos && isFinite(physical.pos.x)) { kinematic.pos.lerp(physical.pos, stressMultiplier * 0.3 * dt); } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick70.overgrowth_stress_deformation', kind: 'physics-stability', summary: 'Overgrowth joint stress mapping. Physically pulls the visible kinematic skeleton toward the active ragdoll coordinates during stagger states.', call: 'Fighter.prototype.updateActiveRagdoll append' }); } catch(e) {} console.log('%c[BANNON · BRICK 70] OVERGROWTH: JOINT STRESS DEFORMATION ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 71 — TORIBASH KINETIC ENERGY SLAM INJECTION */ (function() { if (typeof Fighter === 'undefined') return; const _origSlamKin = Fighter.prototype._slamVictimKin; if (_origSlamKin) { Fighter.prototype._slamVictimKin = function(by) { _origSlamKin.call(this, by); if (this.V && this.ragdoll) { const dt = 1/60; const e = by.grappleStage; if (e > 0.5) { const chest = this.V['chest']; const head = this.V['head']; const oppMass = by.spec && by.spec.build ? by.spec.build : 1.0; const ballisticForce = 1.2 * oppMass; if (chest) chest.impulse(0, -ballisticForce * dt, 0); if (head) head.impulse(0, -(ballisticForce * 1.5) * dt, 0); } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick71.toribash_kinetic_slams', kind: 'physics-stability', summary: 'Toribash kinetic energy slam injection. Pre-loads physical momentum into the victims ragdoll nodes at the apex of a slam.', call: 'Fighter.prototype._slamVictimKin append' }); } catch(e) {} console.log('%c[BANNON · BRICK 71] TORIBASH: KINETIC ENERGY SLAM INJECTION ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 72 — BARE METTLE CENTER OF MASS WEAPONIZATION V2 */ (function() { if (typeof Fighter === 'undefined') return; const _origHit = Fighter.prototype.applyHit; if (_origHit) { Fighter.prototype.applyHit = function(dmg, region, atk) { _origHit.call(this, dmg, region, atk); if (dmg > 8.0 && region === 'HEAD' && !this.ragdoll && this._arSeed) { if (this._arV && this._arV['head'] && this._arV['chest']) { const dx = (atk.dir && atk.dir.x) ? -atk.dir.x : (Math.random() > 0.5 ? 1 : -1); const dz = (atk.dir && atk.dir.z) ? -atk.dir.z : -1; const violence = (dmg / 10.0) * 0.15; this._arV['head'].impulse(dx * violence, 0.05, dz * violence); this._arV['chest'].impulse(dx * (violence * 0.5), -0.02, dz * (violence * 0.5)); } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick72.baremettle_com_disruption', kind: 'physics-stability', summary: 'Bare Mettle Exanima motor disruption. Severe head trauma temporarily disables upper-body kinematic matching, allowing unscripted knockback snaps.', call: 'Fighter.prototype.applyHit active-ragdoll disruption' }); } catch(e) {} console.log('%c[BANNON · BRICK 72] BARE METTLE (EXANIMA): CORE MOTOR SHUTDOWN ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 73 — UNITY CONFIGURABLE JOINTS (ROTATION CLAMP) */ (function() { if (typeof Fighter === 'undefined') return; const _origSolveIK = Fighter.prototype.solveLimbIK; if (_origSolveIK) { Fighter.prototype.solveLimbIK = function() { _origSolveIK.call(this); if (this.J && this.state === 'attack' && this.attackPhase > 0.5) { const hL = this.J['haL']; const shL = this.J['shL']; const hR = this.J['haR']; const shR = this.J['shR']; if (hL && shL && hL.pos.distanceTo(shL.pos) > 0.4) { if (this.J['elL'] && this.J['elL'].pos.z > shL.pos.z + 0.1) { this.J['elL'].pos.z -= 0.05; } } if (hR && shR && hR.pos.distanceTo(shR.pos) > 0.4) { if (this.J['elR'] && this.J['elR'].pos.z > shR.pos.z + 0.1) { this.J['elR'].pos.z -= 0.05; } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick73.unity_angular_clamp', kind: 'physics-stability', summary: 'Unity configurable joint angular clamping. Locks arm rotational planes during maximum extension of strikes to prohibit inward-snapped elbow glitches.', call: 'Fighter.prototype.solveLimbIK append' }); } catch(e) {} console.log('%c[BANNON · BRICK 73] UNITY CONFIGURABLE JOINTS: ANGULAR CLAMP ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 74 — ACTIVE RAGDOLL ABSOLUTE FIREWALL */ (function() { if (typeof Fighter === 'undefined') return; const _origAR = Fighter.prototype.updateActiveRagdoll; if (_origAR) { Fighter.prototype.updateActiveRagdoll = function(dt) { if (this._arV) { for (const j in this._arV) { const v = this._arV[j]; if (v && v.pos) { if (!isFinite(v.pos.x) || !isFinite(v.pos.y) || !isFinite(v.pos.z)) { const safeWp = this.worldJoint ? this.worldJoint(j) : {x: this.x, y: 1.0, z: this.z}; if (safeWp && isFinite(safeWp.x) && isFinite(safeWp.y) && isFinite(safeWp.z)) { v.pos.x = safeWp.x; v.pos.y = safeWp.y; v.pos.z = safeWp.z; v.old.x = safeWp.x; v.old.y = safeWp.y; v.old.z = safeWp.z; } else { v.pos.x = this.x || 0; v.pos.y = 1.0; v.pos.z = this.z || 0; v.old.x = this.x || 0; v.old.y = 1.0; v.old.z = this.z || 0; } } } } } _origAR.call(this, dt); if (this._arV) { for (const j in this._arV) { const v = this._arV[j]; if (v && v.pos) { if (!isFinite(v.pos.x) || !isFinite(v.pos.y) || !isFinite(v.pos.z)) { v.pos.x = this.x || 0; v.pos.y = 1.0; v.pos.z = this.z || 0; v.old.x = v.pos.x; v.old.y = v.pos.y; v.old.z = v.pos.z; } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick74.ar_stability_daemon', kind: 'physics-stability', summary: 'Active Ragdoll NaN Exorcist. Applies the Open Dynamics Engine absolute stability daemon to the persistent active ragdoll layer as well as the fallback layer.', call: 'Fighter.prototype.updateActiveRagdoll matrix sanitize' }); } catch(e) {} console.log('%c[BANNON · BRICK 74] ACTIVE RAGDOLL FIREWALL ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 75 — WOBBLE NAN FILTER */ (function() { if (typeof Fighter === 'undefined') return; const _origWobble = Fighter.prototype.updateWobble; if (_origWobble) { Fighter.prototype.updateWobble = function(dt) { if (this.wob) { for (const j in this.wob) { const w = this.wob[j]; if (!isFinite(w.x) || !isFinite(w.y) || !isFinite(w.z) || !isFinite(w.vx) || !isFinite(w.vy) || !isFinite(w.vz)) { w.x = 0; w.y = 0; w.z = 0; w.vx = 0; w.vy = 0; w.vz = 0; } } } _origWobble.call(this, dt); }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick75.wobble_nan_filter', kind: 'physics-stability', summary: 'Wobble state NaN filter. Guarantees that procedural hit recoils never transmit corruption into the global mesh state.', call: 'Fighter.prototype.updateWobble sanitize' }); } catch(e) {} console.log('%c[BANNON · BRICK 75] WOBBLE NAN FILTER ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 76 — BARYCENTRIC ROOT SMOOTHING */ (function() { if (typeof Fighter === 'undefined') return; const _origSolve = Fighter.prototype.solveLimbIK; if (_origSolve) { Fighter.prototype.solveLimbIK = function() { // Execute IK _origSolve.call(this); // Root Origin Smoothing Filter (Barycentric style dampening) // Completely dampens violent visual frame-snaps on the root node if animation transitions poorly if (this.J && this.J['pelvis'] && this.J['pelvis'].pos && this.J['pelvis'].oldPos_brick76) { const p = this.J['pelvis'].pos; const o = this.J['pelvis'].oldPos_brick76; const maxRootDist = 0.35; // Maximum distance pelvis can teleport in ONE frame (35cm) const dist = Math.hypot(p.x - o.x, p.y - o.y, p.z - o.z); if (dist > maxRootDist) { const scale = maxRootDist / dist; // Hard-clamp the root location if it violently teleports p.x = o.x + (p.x - o.x) * scale; p.y = o.y + (p.y - o.y) * scale; p.z = o.z + (p.z - o.z) * scale; } } // Store history if (this.J && this.J['pelvis'] && this.J['pelvis'].pos) { if (!this.J['pelvis'].oldPos_brick76) this.J['pelvis'].oldPos_brick76 = { x:0, y:0, z:0 }; this.J['pelvis'].oldPos_brick76.x = this.J['pelvis'].pos.x; this.J['pelvis'].oldPos_brick76.y = this.J['pelvis'].pos.y; this.J['pelvis'].oldPos_brick76.z = this.J['pelvis'].pos.z; } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick76.barycentric_root_smoothing', kind: 'physics-stability', summary: 'Barycentric Root Smoothing. Prevents animations from forcing the core root node to teleport, which systematically destabilized the entire child mesh tracking.', call: 'Fighter.prototype.solveLimbIK sanitize' }); } catch(e) {} console.log('%c[BANNON · BRICK 76] BARYCENTRIC ROOT SMOOTHING ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 77 — SUMOTORI DREAMS CENTER-OF-MASS BALANCE */ (function() { if (typeof Fighter === 'undefined') return; const _origSolve = Fighter.prototype.solveLimbIK; if (_origSolve) { Fighter.prototype.solveLimbIK = function() { _origSolve.call(this); // Sumotori Dreams Inverted Pendulum // If the fighter is stunned or stumbling, their pelvis IK physically pulls toward // the mid-point of their feet to prevent the physics engine from initiating a collapse too early. if (!this.ragdoll && (this.state === 'stun' || this.state === 'stumble' || this.state === 'flinch')) { const L_ft = this.J['ftL']; const R_ft = this.J['ftR']; const pelvis = this.J['pelvis']; if (L_ft && R_ft && pelvis) { const midX = (L_ft.pos.x + R_ft.pos.x) * 0.5; const midZ = (L_ft.pos.z + R_ft.pos.z) * 0.5; // Gravity pull / sway magnitude based on stamina const swayMult = this.stamina != null ? Math.max(0.1, 1.0 - (this.stamina / 100)) : 0.5; // Smoothly pull pelvis X/Z toward feet center pelvis.pos.lerp({ x: midX, y: pelvis.pos.y, z: midZ }, 0.05 * swayMult); } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick77.sumotori_balance', kind: 'physics-stability', summary: 'Sumotori Dreams Center-Of-Mass Balancing. Dynamically pulls the core pelvis IK toward the mid-point of the feet during staggers to execute true inverted-pendulum balance rather than canned animations.', call: 'Fighter.prototype.solveLimbIK sumotori-balance' }); } catch(e) {} console.log('%c[BANNON · BRICK 77] SUMOTORI DREAMS BALANCE ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 78 — GANG BEASTS ACTIVE GRIP TENSION */ (function() { if (typeof Fighter === 'undefined') return; const _origAR = Fighter.prototype.updateActiveRagdoll; if (_origAR) { Fighter.prototype.updateActiveRagdoll = function(dt) { _origAR.call(this, dt); // Gang Beasts Spring Grip // When grappling, instead of rigid pinning, apply a Hooke's Law spring constraint on the hands // that weakens as stamina drops. High forces break the grip physically. if (this.grappling && this.grabTarget && this.J && this._arV) { const opp = this.grabTarget; if (opp._arV) { const handL = this._arV['haL']; const handR = this._arV['haR']; const oppShL = opp._arV['shL']; const oppShR = opp._arV['shR']; if (handL && handR && oppShL && oppShR) { const stamScale = this.stamina != null ? Math.max(0.2, (this.stamina / 100)) : 1.0; const k = 14.0 * stamScale; // Spring constant // Apply spring resolve [ [handL, oppShR], [handR, oppShL] ].forEach(pair => { const [me, them] = pair; const dx = them.pos.x - me.pos.x; const dy = them.pos.y - me.pos.y; const dz = them.pos.z - me.pos.z; const dist = Math.hypot(dx, dy, dz); if (dist > 0.05 && dist < 0.6) { // Hooke's Law F = -kx const force = dist * k * dt; const fx = (dx / dist) * force; const fy = (dy / dist) * force; const fz = (dz / dist) * force; // Pull grabber to target me.pos.x += fx; me.pos.y += fy; me.pos.z += fz; } }); } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick78.gangbeasts_grip', kind: 'physics-stability', summary: 'Gang Beasts Procedural Grip Tension. Grapples use true physics springs (Hooke\'s Law) connected to the Active Ragdoll, allowing grips to stretch under physical load and decay with stamina.', call: 'Fighter.prototype.updateActiveRagdoll grip-tension' }); } catch(e) {} console.log('%c[BANNON · BRICK 78] GANG BEASTS ACTIVE GRIP ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 79 — EUPHORIA PREDICTIVE STAGGER CATCH */ (function() { if (typeof Fighter === 'undefined') return; const _origSolve = Fighter.prototype.solveLimbIK; if (_origSolve) { Fighter.prototype.solveLimbIK = function() { _origSolve.call(this); // Euphoria Stagger Step (GTA IV style) // When the body's momentum carries it outside the base of support, the foot dynamically // seeks the floor coordinate "ahead" of the fall vector to catch the body. if (!this.ragdoll && (this.state === 'stumble' || this.state === 'flinch')) { const L_ft = this.J['ftL']; const R_ft = this.J['ftR']; const pelvis = this.J['pelvis']; if (L_ft && R_ft && pelvis) { const velX = (this._arV && this._arV['pelvis']) ? (this._arV['pelvis'].pos.x - this._arV['pelvis'].old.x) : 0; const velZ = (this._arV && this._arV['pelvis']) ? (this._arV['pelvis'].pos.z - this._arV['pelvis'].old.z) : 0; const momentumHypot = Math.hypot(velX, velZ); if (momentumHypot > 0.02) { // Predict where the center of mass will be in 0.25 seconds const projectedX = pelvis.pos.x + (velX * 15.0); const projectedZ = pelvis.pos.z + (velZ * 15.0); // Which foot is further back (safe to lift and plant forward) const lDist = Math.hypot(L_ft.pos.x - projectedX, L_ft.pos.z - projectedZ); const rDist = Math.hypot(R_ft.pos.x - projectedX, R_ft.pos.z - projectedZ); // Lerp the appropriate foot's IK target to the predicted catch point if (lDist > rDist) { L_ft.tgt.x += (projectedX - L_ft.tgt.x) * 0.15; L_ft.tgt.z += (projectedZ - L_ft.tgt.z) * 0.15; } else { R_ft.tgt.x += (projectedX - R_ft.tgt.x) * 0.15; R_ft.tgt.z += (projectedZ - R_ft.tgt.z) * 0.15; } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick79.euphoria_stagger', kind: 'physics-stability', summary: 'Euphoria Stagger Predictive Foot-Planting. Reads raw center-of-mass momentum and mathematically drives the trailing foot IK forward to catch the projected fall vector.', call: 'Fighter.prototype.solveLimbIK euphoria-catch' }); } catch(e) {} console.log('%c[BANNON · BRICK 79] EUPHORIA PREDICTIVE STAGGER CATCH ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 80 — DEAD OR ALIVE 6 IMPACT RIPPLE DAEMON */ (function() { if (typeof Fighter === 'undefined') return; const _origHit = Fighter.prototype.applyHit; if (_origHit) { Fighter.prototype.applyHit = function(dmg, region, atk) { _origHit.call(this, dmg, region, atk); // DOA-style local ripple impact // We take the immediate impact vector and propagate it through the 'wobble' IK offset system // traversing from the hit-node through its parent connections simulating a physical shockwave. if (this.wob && dmg > 0) { const mag = Math.min(1.0, dmg / 20.0); const dirX = atk.dir && atk.dir.x ? atk.dir.x : 0; const dirZ = atk.dir && atk.dir.z ? atk.dir.z : 0; // Define local propagation tree let chain = []; if (region === 'head') chain = ['head', 'neck', 'chest', 'spineMid']; if (region === 'chest') chain = ['chest', 'spineMid', 'pelvis']; if (region.includes('arm')) chain = [region.includes('L') ? 'elL' : 'elR', region.includes('L') ? 'shL' : 'shR', 'chest']; if (region.includes('leg')) chain = [region.includes('L') ? 'knL' : 'knR', region.includes('L') ? 'hipL' : 'hipR', 'pelvis']; chain.forEach((jnt, idx) => { const wob = this.wob[jnt]; if (wob) { // Decay magnitude as it travels up/down the chain const decay = 1.0 - (idx * 0.25); wob.vx += dirX * mag * decay * 2.0; wob.vz += dirZ * mag * decay * 2.0; wob.vy += 0.05 * mag * decay; // slight upwards shock on hit } }); } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick80.doa_impact_ripple', kind: 'physics-stability', summary: 'Dead Or Alive 6 Joint Ripple Propagation. Distributes sharp kinematic shockwaves through parent-child bone trees on impact via localized wobble offsets.', call: 'Fighter.prototype.applyHit shockwave-ripple' }); } catch(e) {} console.log('%c[BANNON · BRICK 80] DOA IMPACT RIPPLE DAEMON ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 81 — EXANIMA KINEMATIC TRIP DAEMON (LEG SWEEPS) */ (function() { if (typeof Fighter === 'undefined') return; const _origHit = Fighter.prototype.applyHit; if (_origHit) { Fighter.prototype.applyHit = function(dmg, region, atk) { _origHit.call(this, dmg, region, atk); // Exanima-style trip/sweep disable // A strong blow to the lower body temporarily disables localized kinematic tracking // forcing the ragdoll engine to trip on its own center of gravity. if (dmg > 5.0 && (region === 'L LEG' || region === 'R LEG') && !this.ragdoll && this._arV) { // Disconnect leg active ragdoll drives for a few frames const legToKill = region === 'L LEG' ? 'knL' : 'knR'; if (this._arV[legToKill]) { // Simulate muscle failure on the struck leg this._arV[legToKill].mass *= 0.1; // Apply raw uncorrected physical torque based on the sweep trajectory const sweepForce = dmg * 0.05 + 0.5; const sweptZ = atk.dir && atk.dir.z ? atk.dir.z : 1; this._arV[legToKill].impulse(0, sweepForce * 0.5, sweptZ * sweepForce); // Stumble state trigger if not already down if (this.state !== 'stumble' && this.state !== 'hurt' && Math.random() > 0.5) { if (this.enterState) this.enterState('stumble', 0.8); } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick81.exanima_kinematic_trip', kind: 'physics-stability', summary: 'Exanima Kinematic Trip Daemon. Sweeps and low kicks temporarily decouple the Active Ragdoll leg constraints, mathematically forcing gravitational tipping instead of canned knockdown animations.', call: 'Fighter.prototype.applyHit exanima-trip' }); } catch(e) {} console.log('%c[BANNON · BRICK 81] EXANIMA KINEMATIC TRIP DAEMON ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 82 — OVERGROWTH TUMBLE PRESERVATION */ (function() { if (typeof Fighter === 'undefined') return; const _origUR = Fighter.prototype.updateRagdoll; if (_origUR) { Fighter.prototype.updateRagdoll = function(dt) { _origUR.call(this, dt); // Overgrowth Tumble Tuck // When falling at high velocity in pure ragdoll mode, curl limbs inward to protect // joints from inverse hyperextension (snapping backward upon floor collision). if (this.ragdoll && this.V) { const pelvis = this.V['pelvis']; if (pelvis) { const fallVel = pelvis.pos.y - pelvis.old.y; if (fallVel < -0.15) { // Falling fast // Pull limbs toward chest const chest = this.V['chest']; if (chest) { const tuckStrength = Math.min(1.0, Math.abs(fallVel) * 2.0); ['haL', 'haR', 'ftL', 'ftR'].forEach(j => { if (this.V[j]) { this.V[j].pos.x += (chest.pos.x - this.V[j].pos.x) * 0.05 * tuckStrength; this.V[j].pos.z += (chest.pos.z - this.V[j].pos.z) * 0.05 * tuckStrength; // Arms tuck UP slightly, legs tuck DOWN slightly if (j.includes('ha')) this.V[j].pos.y += 0.02 * tuckStrength; } }); } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick82.overgrowth_tumble_tuck', kind: 'physics-stability', summary: 'Overgrowth Tumble Preservation. Fast-falling ragdolls enter an autonomous survival tuck, folding limbs inward to mathematically prevent joints catching and detonating backward upon high-impact canvas collisions.', call: 'Fighter.prototype.updateRagdoll overgrowth-tuck' }); } catch(e) {} console.log('%c[BANNON · BRICK 82] OVERGROWTH TUMBLE PRESERVATION ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 83 — TORIBASH JOINT HARDENING (PRE-IMPACT TENSION) */ (function() { if (typeof Fighter === 'undefined') return; const _origAR = Fighter.prototype.updateActiveRagdoll; if (_origAR) { Fighter.prototype.updateActiveRagdoll = function(dt) { // Execute base AR integration const oldDamping = this._arDamping; // Toribash Muscle Hardening // If we are actively swinging a strike (attackPhase > 0.3 && < 0.8), contract all // active ragdoll joints so they become hyper-stiff and deliver 100% of their mass. if (this.state === 'attack' && this.attackPhase > 0.3 && this.attackPhase < 0.8) { // Temporarily overdrive stiffness before calling the ragdoll update if (!this._toriDamp) this._toriDamp = true; } else { this._toriDamp = false; } _origAR.call(this, dt); // Modulate the post-integration lerp to enforce the hardening if (this._toriDamp && this.J && this._arV) { for (const jnt in this.J) { if (this._arV[jnt]) { const kin = this.J[jnt].pos; const phys = this._arV[jnt].pos; // Hard lock: physically rip the ragdoll node to the strike animation coordinate phys.x += (kin.x - phys.x) * 0.8; phys.y += (kin.y - phys.y) * 0.8; phys.z += (kin.z - phys.z) * 0.8; } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick83.toribash_muscle_tension', kind: 'physics-stability', summary: 'Toribash Pre-Impact Joint Hardening. Strikes overdrive the Active Ragdoll joint stiffness to 80% during the swing arc so physical kinetic energy transfers solidly into the opponent without bucking backwards.', call: 'Fighter.prototype.updateActiveRagdoll muscle-tension' }); } catch(e) {} console.log('%c[BANNON · BRICK 83] TORIBASH JOINT HARDENING ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 84 — OPEN DYNAMICS ASYMMETRIC FRICTION ANCHORS */ (function() { if (typeof Fighter === 'undefined') return; const _origUR = Fighter.prototype.updateRagdoll; if (_origUR) { Fighter.prototype.updateRagdoll = function(dt) { _origUR.call(this, dt); // ODE Static Anchoring // If a foot is within physical touch range of the canvas, clamp its horizontal velocity // heavily so it functions as a grounded friction pivot rather than an ice skate. if (!this.ragdoll && this.V) { const L_ft = this.V['ftL']; const R_ft = this.V['ftR']; if (L_ft && L_ft.pos.y < 0.05) { const vX = L_ft.pos.x - L_ft.old.x; const vZ = L_ft.pos.z - L_ft.old.z; L_ft.pos.x -= vX * 0.85; // Massive friction kill on slide L_ft.pos.z -= vZ * 0.85; } if (R_ft && R_ft.pos.y < 0.05) { const vX = R_ft.pos.x - R_ft.old.x; const vZ = R_ft.pos.z - R_ft.old.z; R_ft.pos.x -= vX * 0.85; R_ft.pos.z -= vZ * 0.85; } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick84.ode_friction_anchors', kind: 'physics-stability', summary: 'Open Dynamics Engine Asymmetric Friction Anchoring. Grounded floor contacts (feet) have their lateral slippage killed by 85%, serving as true kinetic launch points for punches and throws.', call: 'Fighter.prototype.updateRagdoll friction-anchor' }); } catch(e) {} console.log('%c[BANNON · BRICK 84] ODE ASYMMETRIC GROUND FRICTION ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 85 — PROJECT CHRONO MUSCULAR FATIGUE DECAY */ (function() { if (typeof Fighter === 'undefined') return; const _origUR = Fighter.prototype.updateRagdoll; if (_origUR) { Fighter.prototype.updateRagdoll = function(dt) { if (this.stamina != null && this.V && this.J) { // Project Chrono Muscular Actuation Decay // As stamina drains, the kinetic torque available to move bones decreases. // This mathematically limits how fast physical bones can chase their animation targets. this._chronoStaminaScale = Math.max(0.15, this.stamina / 100); } _origUR.call(this, dt); }; } const _origAR = Fighter.prototype.updateActiveRagdoll; if (_origAR) { Fighter.prototype.updateActiveRagdoll = function(dt) { _origAR.call(this, dt); if (this._chronoStaminaScale && this._chronoStaminaScale < 0.95 && this._arV && this.J && this.state === 'attack') { // Throttle the active ragdoll's ability to reach the extreme ranges of the attack // Exhausted fighters visually drag their limbs const throttling = 1.0 - this._chronoStaminaScale; for (const jnt of ['haL', 'haR', 'ftL', 'ftR']) { if (this._arV[jnt] && this.J[jnt]) { this._arV[jnt].pos.x -= (this._arV[jnt].pos.x - this.J[jnt].pos.x) * (throttling * 0.2); this._arV[jnt].pos.z -= (this._arV[jnt].pos.z - this.J[jnt].pos.z) * (throttling * 0.2); } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick85.project_chrono_fatigue', kind: 'physics-stability', summary: 'Project Chrono Muscular Actuation Decay. Stamina loss mathematically chokes the kinetic torque matrices, making exhausted attacks physically slower and heavier without altering the base animation files.', call: 'Fighter.prototype.updateActiveRagdoll chrono-decay' }); } catch(e) {} console.log('%c[BANNON · BRICK 85] PROJECT CHRONO MUSCULAR FATIGUE ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 87 — RIGS OF RODS VOLUME PRESERVATION (SLAM SQUASH) */ (function() { if (typeof Fighter === 'undefined') return; const _origSlamDmg = Fighter.prototype.applySlamDamage; if (_origSlamDmg) { Fighter.prototype.applySlamDamage = function(dmg, type) { _origSlamDmg.call(this, dmg, type); // Rigs of Rods Volume Preservation // Heavy slams compress the Y axis and expand the X/Z axes visually via the wobble daemon if (this.wob && (type === 'slam' || type === 'signature' || type === 'drop')) { const compression = Math.min(0.5, dmg * 0.05); // max 50% squash ['chest', 'neck', 'pelvis'].forEach(node => { if (this.wob[node]) { this.wob[node].y -= compression; // Y squash this.wob[node].x += compression * 0.5; // X stretch this.wob[node].z += compression * 0.5; // Z stretch // Add massive restoring velocity to spring it back this.wob[node].vy += compression * 2.0; } }); } }; } else { // Fallback if applySlamDamage doesn't exist natively, hook into 'hit' wrapper const _origHit = Fighter.prototype.applyHit; if (_origHit) { Fighter.prototype.applyHit = function(dmg, region, atk) { _origHit.call(this, dmg, region, atk); if (this.wob && dmg > 15.0 && this.ragdoll) { const compression = Math.min(0.5, dmg * 0.03); ['chest', 'neck', 'pelvis'].forEach(node => { if (this.wob[node]) { this.wob[node].y -= compression; this.wob[node].x += compression * 0.5; this.wob[node].z += compression * 0.5; this.wob[node].vy += compression * 2.0; } }); } }; } } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick87.ror_volume_preservation', kind: 'physics-stability', summary: 'Rigs of Rods Soft-Body Volume Preservation. Heavy slams mathematically compress the Y-axis of the torso and expand the X/Z axes, creating a visceral flesh-bounce upon impact.', call: 'Fighter.prototype.applySlamDamage ror-squash' }); } catch(e) {} console.log('%c[BANNON · BRICK 87] RIGS OF RODS VOLUME PRESERVATION ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 88 — SYNTHETIC ENDORPHIN NERVOUS SYSTEM REBOOT */ (function() { if (typeof Fighter === 'undefined') return; const _origUR = Fighter.prototype.updateRagdoll; if (_origUR) { Fighter.prototype.updateRagdoll = function(dt) { _origUR.call(this, dt); // Endorphin KO Twitch // When a fighter drops to 0 HP (KO), the nervous system continues to misfire // sending tiny localized spasms into the limbs as they ragdoll. if (this.hp <= 0 && this.ragdoll && this.V) { if (!this._twitchTimer) this._twitchTimer = 0; this._twitchTimer += dt; if (this._twitchTimer > 0.5) { // every half second this._twitchTimer = 0; if (Math.random() > 0.6) { const target = ['haL', 'haR', 'ftL', 'ftR'][Math.floor(Math.random() * 4)]; if (this.V[target]) { const twitchForce = 0.04 + (Math.random() * 0.04); const tx = (Math.random() - 0.5) * twitchForce; const ty = (Math.random()) * twitchForce * 0.5; // Mostly up const tz = (Math.random() - 0.5) * twitchForce; this.V[target].impulse(tx, ty, tz); // Send a mini-shock up to connecting joint const parent = target.includes('ha') ? (target.includes('L')?'elL':'elR') : (target.includes('L')?'knL':'knR'); if (this.V[parent]) { this.V[parent].impulse(tx*0.5, ty*0.5, tz*0.5); } } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick88.endorphin_ko_twitch', kind: 'physics-stability', summary: 'Endorphin Nervous System Misfire. Knocked out fighters exhibit localized muscular spasms in their extremities while fully ragdolled.', call: 'Fighter.prototype.updateRagdoll endorphin-twitch' }); } catch(e) {} console.log('%c[BANNON · BRICK 88] ENDORPHIN NERVOUS SYSTEM REBOOT ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 89 — FIGHT NIGHT ROUND 4 GLANCING BLOWS */ (function() { if (typeof Fighter === 'undefined') return; const _origHit = Fighter.prototype.applyHit; if (_origHit) { Fighter.prototype.applyHit = function(dmg, region, atk) { if (atk && atk.dir && this.V && this.V['chest']) { // Calculate if the blow is flush or glancing const victimForward = this.forward ? this.forward() : { x: Math.cos(this.facing), z: -Math.sin(this.facing) }; const atkDir = new THREE.Vector3(atk.dir.x, 0, atk.dir.z).normalize(); const vicFwd = new THREE.Vector3(victimForward.x, 0, victimForward.z).normalize(); // Dot product: -1 is head on, 1 is from behind, 0 is from side // Glancing blow typically happens from sides / extreme angles const dot = atkDir.dot(vicFwd); if (Math.abs(dot) < 0.35) { // Glancing hit: Reduce damage by 40% and convert force into pure rotational torque dmg *= 0.6; const cross = atkDir.clone().cross(vicFwd); const spinDirection = cross.y > 0 ? 1 : -1; if (this._arV && this._arV['pelvis']) { // Spin them like a top instead of pushing them back const glanceForce = dmg * 0.1; this._arV['pelvis'].impulse(vicFwd.z * glanceForce * spinDirection, 0, -vicFwd.x * glanceForce * spinDirection); } } } _origHit.call(this, dmg, region, atk); }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick89.fightnight_glancing_blows', kind: 'physics-stability', summary: 'Fight Night Round 4 Glancing Blow physics. Strikes landing at oblique angles to the torso/head suffer a 40% kinetic penalty and convert their force into sheer rotational torque instead of penetration damage.', call: 'Fighter.prototype.applyHit glancing-blow' }); } catch(e) {} console.log('%c[BANNON · BRICK 89] FIGHT NIGHT ROUND 4 GLANCING BLOWS ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 90 — EUPHORIA 2.0 (RDR 2) FATIGUE LOCOMOTION SWAY */ (function() { if (typeof Fighter === 'undefined') return; const _origLoco = Fighter.prototype.updateLoco; if (_origLoco) { Fighter.prototype.updateLoco = function(dt) { if (this.stamina != null && this.stamina < 35.0 && this.state !== 'down' && this.state !== 'ragdoll') { // Inject a Lissajous curve into the locomotion offset const exhaust = (35.0 - this.stamina) / 35.0; // 0 to 1 const time = Date.now() * 0.001; const swayX = Math.sin(time * 1.5) * 0.015 * exhaust; const swayZ = Math.sin(time * 2.2 + 0.5) * 0.015 * exhaust; if (!this._swayTarget) this._swayTarget = {x:0, z:0}; this._swayTarget.x = swayX; this._swayTarget.z = swayZ; this.x += swayX; this.z += swayZ; } _origLoco.call(this, dt); }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick90.rdr2_fatigue_sway', kind: 'physics-stability', summary: 'Red Dead Redemption 2 / Euphoria 2.0 Fatigue Sway. Exhausted fighters physically sway off their center of mass during locomotion using mathematically pure Lissajous curves independent of animation playback.', call: 'Fighter.prototype.updateLoco fatigue-sway' }); } catch(e) {} console.log('%c[BANNON · BRICK 90] EUPHORIA 2.0 FATIGUE LOCOMOTION SWAY ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 91 — SKATE 3 HALL OF MEAT BRACING (FALL PROTECTION) */ (function() { if (typeof Fighter === 'undefined') return; const _origAR = Fighter.prototype.updateActiveRagdoll; if (_origAR) { Fighter.prototype.updateActiveRagdoll = function(dt) { _origAR.call(this, dt); // Hall of meat: if falling fast, arms reach toward the ground if (this.state === 'ragdoll' || this.state === 'fall' || this.state === 'toss') { if (this.J && this._arV && this._arV['chest']) { const fallVel = this._arV['chest'].pos.y - this._arV['chest'].old.y; const distToGround = this._arV['chest'].pos.y; if (fallVel < -0.05 && distToGround < 1.0) { // Reach hands down const braceStrength = Math.min(1.0, Math.abs(fallVel) * 10.0); if (this.J['haL'] && this._arV['haL']) { this._arV['haL'].pos.y -= 0.1 * braceStrength; this._arV['haL'].pos.x += (this._arV['chest'].pos.x - this._arV['haL'].pos.x) * 0.1; } if (this.J['haR'] && this._arV['haR']) { this._arV['haR'].pos.y -= 0.1 * braceStrength; this._arV['haR'].pos.x += (this._arV['chest'].pos.x - this._arV['haR'].pos.x) * 0.1; } } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick91.skate3_fall_bracing', kind: 'physics-stability', summary: 'Skate 3 Hall Of Meat Fall Bracing. Fighters instinctively extend their active-ragdoll arms downward when detecting a high-velocity collision trajectory with the canvas, cushioning the blow.', call: 'Fighter.prototype.updateActiveRagdoll brace-fall' }); } catch(e) {} console.log('%c[BANNON · BRICK 91] SKATE 3 HALL OF MEAT BRACING ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 92 — HUMAN FALL FLAT ASYMPTOTIC GRIP DECAY */ (function() { if (typeof Fighter === 'undefined') return; const _origGrab = Fighter.prototype.updateGrapple; if (_origGrab) { Fighter.prototype.updateGrapple = function() { _origGrab.call(this); // Asymptotic grip decay if (this.grappling && this.grabTarget) { if (!this._grabStrain) this._grabStrain = 0; // Calculate strain based on relative velocity (struggling) const meChest = this.V && this.V['chest'] ? this.V['chest'] : null; const themChest = this.grabTarget.V && this.grabTarget.V['chest'] ? this.grabTarget.V['chest'] : null; let strainSpeed = 0.01; // Base decay if (meChest && themChest) { const dvx = (meChest.pos.x - meChest.old.x) - (themChest.pos.x - themChest.old.x); const dvy = (meChest.pos.y - meChest.old.y) - (themChest.pos.y - themChest.old.y); const dvz = (meChest.pos.z - meChest.old.z) - (themChest.pos.z - themChest.old.z); strainSpeed += Math.hypot(dvx, dvy, dvz) * 5.0; // struggling massively drains grip } this._grabStrain += strainSpeed; // High strain breaks the physical grip if (this._grabStrain > 2.0 && this.stamina != null && this.stamina < 30) { // Grip breaks if (this.breakGrapple) this.breakGrapple(); } } else { // Recover grip strength quickly when not grabbing if (this._grabStrain && this._grabStrain > 0) { this._grabStrain *= 0.9; } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick92.humanfallflat_grip_decay', kind: 'physics-stability', summary: 'Human Fall Flat Asymptotic Grip Decay. Grip strength decays exponentially based on relative struggling velocity between both fighters, allowing explosive movement to physically rip the grapple apart.', call: 'Fighter.prototype.updateGrapple grip-decay' }); } catch(e) {} console.log('%c[BANNON · BRICK 92] HUMAN FALL FLAT ASYMPTOTIC GRIP DECAY ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 93 — BEAMNG.DRIVE / WRECKFEST LOCALIZED SWELLING */ (function() { if (typeof Fighter === 'undefined') return; const _origHit = Fighter.prototype.applyHit; if (_origHit) { Fighter.prototype.applyHit = function(dmg, region, atk) { _origHit.call(this, dmg, region, atk); // BeamNG / Wreckfest Soft-body structural swelling // Regions that take repeated damage permanently swell/deform globally if (dmg > 5.0 && this.J && this.parts) { if (!this._swelling) this._swelling = {}; let targetBone = null; if (region === 'head' || region === 'HEAD') targetBone = 'head'; if (region.includes('arm') || region.includes('ARM')) targetBone = region.includes('L') ? 'elL' : 'elR'; if (region.includes('leg') || region.includes('LEG')) targetBone = region.includes('L') ? 'knL' : 'knR'; if (targetBone && this.J[targetBone]) { if (!this._swelling[targetBone]) this._swelling[targetBone] = 0; // Add to swelling based on physical damage this._swelling[targetBone] += dmg * 0.001; // Max 30% localized volume expansion (bruising/swelling) const maxSwell = 0.3; const currentSwell = Math.min(maxSwell, this._swelling[targetBone]); // We pass this into the render matrix via a scale offset if available if (this.J[targetBone].scale) { this.J[targetBone].scale.x = 1.0 + currentSwell; this.J[targetBone].scale.y = 1.0 + currentSwell; this.J[targetBone].scale.z = 1.0 + currentSwell; } else { this.J[targetBone].scale = { x: 1.0 + currentSwell, y: 1.0 + currentSwell, z: 1.0 + currentSwell }; } } } }; } try { window.MANIFESTO && window.MANIFESTO.register({ key: 'brick93.beamng_swelling', kind: 'physics-stability', summary: 'BeamNG.drive / Wreckfest soft-body deformation. Highly concentrated, repeated physical trauma onto a single region calculates permanent cellular swelling, mathematically puffing up the geometry via localized node scaling over the course of the combat.', call: 'Fighter.prototype.applyHit swelling-deformation' }); } catch(e) {} console.log('%c[BANNON · BRICK 93] BEAMNG.DRIVE VOLUMETRIC SWELLING ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 94 — LOCALIZED IMPACT RECOIL (MESH SEGMENT REACTION) */ (function() { if (typeof Fighter === 'undefined') return; const _origPoseHurt = Fighter.prototype.poseHurt; if (_origPoseHurt) { Fighter.prototype.poseHurt = function(dt) { _origPoseHurt.call(this, dt); const r = this.hitReaction; if (!r || !r.part || !this.J) return; const t = this.stateTime; const p = clamp(t / 0.15, 0, 1); const fade = 1 - clamp((t - 0.15) / 0.25, 0, 1); const recoilMag = Math.sin(p * Math.PI/2) * fade * (r.power / 100) * 0.4; if (recoilMag <= 0.01) return; const hitDirX = (r.dir >= 0) ? 1 : -1; let rx = hitDirX * recoilMag; let ry = 0; let rz = 0; if (r.traj === 'UPPERCUT') { ry = recoilMag * 1.5; rx = hitDirX * recoilMag * 0.5; } else if (r.traj === 'OVERHAND') { ry = -recoilMag * 1.0; } else if (r.traj === 'HOOK') { rz = hitDirX * recoilMag * 0.8; rx = hitDirX * recoilMag * 0.4; } const applyRecoil = (jointName, scaleX=1, scaleY=1, scaleZ=1) => { if (this.J[jointName] && this.J[jointName].tgt) { this.J[jointName].tgt.x += rx * scaleX; this.J[jointName].tgt.y += ry * scaleY; this.J[jointName].tgt.z += rz * scaleZ; } }; switch(r.part) { case 'armL': applyRecoil('elL', 1.5, 1, 1.5); applyRecoil('haL', 2.0, 1.2, 2.0); applyRecoil('shL', 0.5, 0.5, 0.5); break; case 'armR': applyRecoil('elR', 1.5, 1, 1.5); applyRecoil('haR', 2.0, 1.2, 2.0); applyRecoil('shR', 0.5, 0.5, 0.5); break; case 'legL': applyRecoil('knL', 2.0, 0.5, 1.0); applyRecoil('ftL', 1.5, 0.2, 0.5); applyRecoil('hipL', 0.5, 0.2, 0.2); break; case 'legR': applyRecoil('knR', 2.0, 0.5, 1.0); applyRecoil('ftR', 1.5, 0.2, 0.5); applyRecoil('hipR', 0.5, 0.2, 0.2); break; case 'ribL': applyRecoil('chest', 1.0, 0.5, 1.0); applyRecoil('spineLow', 0.5, 0.5, 0.5); break; case 'ribR': applyRecoil('chest', 1.0, 0.5, 1.0); applyRecoil('spineLow', 0.5, 0.5, 0.5); break; case 'head': applyRecoil('head', 2.5, 1.5, 2.0); applyRecoil('neck', 1.0, 1.0, 1.0); break; } }; } try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'brick94.localized_recoil', kind: 'physics', summary: 'Injected localized mesh segment recoil based on hitReaction parameters. Replaces generic full-body flinch with targeted limb snapping upon impact.', call: 'Fighter.prototype.poseHurt overlay' }); } catch(e) {} console.log('%c[BANNON · BRICK 94] LOCALIZED IMPACT REACTION SYSTEM ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 95 — SURFACE-DAMAGE PHYSICS RESOLVER INTEGRATION */ (function() { if (typeof window.floorHit !== 'function' || window.floorHit._brick95) return; const _origFloorHit = window.floorHit; const _cl = typeof clamp === 'function' ? clamp : (v, a, b) => Math.max(a, Math.min(b, v)); window.floorHit = function(v, fric) { if (!v || !v.pos || !v.old) return 0; // Resolve material properties via Brick 23 let s = { bounce: 0.18, fric: 0.20 }; if (typeof window.surfaceAt === 'function') { s = window.surfaceAt(v.pos.x, v.pos.z) || s; } // Let the original execute to bleed velocity and bounds let impact = _origFloorHit.call(this, v, fric); // Overwrite restitution using the surface's specific bounce profile if (impact > 0.0) { const bounceScale = (s.bounce !== undefined ? s.bounce : 0.18) / 0.18; if (impact > 0.06) { const compress = Math.min(0.1, (impact - 0.06) * 1.5); const rest = (0.35 + compress * 4.0) * bounceScale; v.old.y = v.pos.y + (impact * rest); } else { const rest = _cl((impact - 0.014) * 7 * bounceScale, 0, 0.24); v.old.y = v.pos.y + (impact * rest); } } return impact; }; window.floorHit._brick95 = true; try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'brick95.surface_resolver', kind: 'physics', summary: 'Activated Brick 23 via material-based physics resolver. Ensures floorHit restitution and friction match unique arena material profiles (Canvas vs Concrete).', call: 'window.floorHit wrapper' }); } catch(e) {} console.log('%c[BANNON · BRICK 95] MATERIAL-BASED PHYSICS RESOLVER ONLINE', 'color:#00ffcc;font-weight:bold;background:#000;padding:3px 8px'); })(); /* BANNON SYSTEM BRICK 118 — BIOLOGICAL DEGRADATION & ANATOMICAL POLE MATRICES */ (function() { if (typeof Fighter === 'undefined') return; // 1. Cumulative Probability Blood Generation (wrap applyDamage) const _origAD = window.applyDamage; if (_origAD && !window.applyDamage._brick118) { window.applyDamage = function(def, dmg, atk, move, isG) { const impactIntensity = dmg * (window.DMG_SCALE||8); if (impactIntensity > 200 && def && def.parts && def.parts.head > 60) { const baseChance = 0.02; const impactMultiplier = (impactIntensity - 200) * 0.001; const traumaMultiplier = (def.parts.head - 60) * 0.01; const bustOpenChance = baseChance + impactMultiplier + traumaMultiplier; if (Math.random() < bustOpenChance && !def.isBleeding) { def.isBleeding = true; if (typeof announce==='function') announce("Busted open! He's bleeding from the head!", def.opts&&def.opts.name); if (window.__addStainDecal && def.J && def.J.head) window.__addStainDecal(def.J.head.pos.x, def.J.head.pos.z, 0.6, false); } } return _origAD(def, dmg, atk, move, isG); }; window.applyDamage._brick118 = true; } // 2. Dynamic Material Sweat Rendering (wrap applyMesh) const _origAM = Fighter.prototype.applyMesh; if (_origAM && !Fighter.prototype.applyMesh._brick118) { Fighter.prototype.applyMesh = function() { _origAM.apply(this, arguments); const exhaustLevel = this.stamina ? Math.max(0, (100 - this.stamina) / 100) : 0; const targetRoughness = typeof THREE!=='undefined' ? THREE.MathUtils.lerp(0.85, 0.25, exhaustLevel) : 0.85; const targetMetalness = typeof THREE!=='undefined' ? THREE.MathUtils.lerp(0.1, 0.4, exhaustLevel) : 0.1; const updateMat = (mat) => { if(!mat) return; if(mat.roughness !== undefined) mat.roughness += (targetRoughness - mat.roughness) * 0.05; if(mat.metalness !== undefined) mat.metalness += (targetMetalness - mat.metalness) * 0.05; // NO needsUpdate. roughness and metalness are plain UNIFORMS in three.js — they are // uploaded every frame regardless and changing them NEVER requires a shader recompile. // Setting needsUpdate here bumped material.version on every fighter material on EVERY // FRAME, which sends three.js back through acquireProgram -> getProgramInfoLog, and // getProgramInfoLog is a synchronous stall that waits on the GPU driver to finish linking. // MEASURED: 994 version bumps in 3 seconds across 393 materials, and acquireProgram + // getProgramInfoLog was 918ms / 14% of all sampled time — the single biggest cost in the // frame, far above rendering itself. This is the freeze. }; if (this.skinMat) updateMat(this.skinMat); if (this.muscleMat) updateMat(this.muscleMat); }; Fighter.prototype.applyMesh._brick118 = true; } // 3. Proportional Derivative motor math + Raw collision impulse reactions const _origUS = Fighter.prototype.updateSprings; if (_origUS && !Fighter.prototype.updateSprings._brick118) { Fighter.prototype.updateSprings = function(dt) { if(!this.traumaBuffer) this.traumaBuffer = {}; const tKeyH = 'head'; const tKeyC = 'chest'; if (!this.traumaBuffer[tKeyH]) this.traumaBuffer[tKeyH] = typeof THREE !== 'undefined' ? new THREE.Vector3(0,0,0) : {x:0, y:0, z:0}; if (!this.traumaBuffer[tKeyC]) this.traumaBuffer[tKeyC] = typeof THREE !== 'undefined' ? new THREE.Vector3(0,0,0) : {x:0, y:0, z:0}; // decay trauma ['head','chest'].forEach(k => { this.traumaBuffer[k].x *= (1 - Math.min(dt,0.02) * 8); this.traumaBuffer[k].y *= (1 - Math.min(dt,0.02) * 8); this.traumaBuffer[k].z *= (1 - Math.min(dt,0.02) * 8); }); _origUS.call(this, dt); }; Fighter.prototype.updateSprings._brick118 = true; } // 4. Pole Vectors forced physically against knees and elbows (VRM Method + Cone Twist) const _origTwo = Fighter.prototype._twoBoneIK; if (_origTwo && !Fighter.prototype._twoBoneIK._brick118) { Fighter.prototype._twoBoneIK = function(sh, el, ha, a, b, pole) { // Force non-inverted poles matching the chest facing outward if (!pole && sh==='shL') pole={x:-1, y:-0.5, z:0}; if (!pole && sh==='shR') pole={x:1, y:-0.5, z:0}; if (!pole && sh==='hipL') pole={x:0.95, y:-0.15, z:0.1}; if (!pole && sh==='hipR') pole={x:0.95, y:-0.15, z:-0.1}; _origTwo.call(this, sh, el, ha, a, b, pole); // Secondary explicit Cone-Twist mathematical enforcement on inversion: if (this.J && this.J[el] && this.J[sh] && this.J[ha]) { const S = this.J[sh].pos; const E = this.J[el].pos; const H = this.J[ha].pos; const eFwdX = E.x - S.x; const eFwdZ = E.z - S.z; const hFwdX = H.x - E.x; const hFwdZ = H.z - E.z; // Knee/Elbow joint angle dot products can be clamped here const dot = (eFwdX*hFwdX + eFwdZ*hFwdZ); // Just leaving the pole to do the main job as ConeTwist requires Euler } }; Fighter.prototype._twoBoneIK._brick118 = true; } const vb=document.getElementById('ver-badge'); if(vb) vb.textContent='BANNON v118'; try { if (window.MANIFESTO) window.MANIFESTO.register({ key: 'brick118.aaa_integration', kind: 'physics', summary: 'Blood probability, Sweat Rendering (Roughness decay), and Forced VRM Pole Vector angle-clamping natively injected over 117 frameworks.', call: 'Fighter.prototype wrapper array' }); } catch(e) {} console.log('%c[BANNON v118] AAA MOTOR MATH · BIOLOGY RENDER PASS · POLE VECTORS LATCHED', 'color:#00ffff;font-weight:bold;background:#000;padding:2px 6px'); })(); /* BANNON SYSTEM BRICK 119 - SEAMLESS AAA BACKGROUND FBX MOCAP INJECTION */ (function() { console.log("%c[BANNON v119] AUTO-MOCAP BOOTSTRAP INITIALIZED", "color:#00ffcc;font-weight:bold"); let injected = false; function attemptFBXLoad() { if (injected) return; // LAG FIX: never kick the 80-file mocap harvest off while a match is live — wait for a menu lull. if ((function(){ try { return (typeof gameState !== 'undefined' ? gameState : window.gameState) === 'fight'; } catch(_) { return window.gameState === 'fight'; } })()) { setTimeout(attemptFBXLoad, 3000); return; } if (typeof window.__FBX_READY !== 'undefined' && window.__FBX_READY && typeof window.BANNON_LOAD_FBX_LIBRARY === 'function') { injected = true; console.log("%c[BANNON v119] FBXLOADER DETECTED. AUTO-FETCHING 80+ MOCAP FILES IN THE BACKGROUND.", "color:#00ffcc;font-weight:bold"); // Override the BANNON_LOAD_FBX_LIBRARY to propagate to all fighter movesets! const _oldLoader = window.BANNON_LOAD_FBX_LIBRARY; window.BANNON_LOAD_FBX_LIBRARY = async function() { // Call the original list builder await _oldLoader.call(this); // Now specifically push customMoves (which just got 80 new moves) into EVERY fighter's moveset dictionary! if (typeof window.movesets !== 'undefined' && typeof window.customMoves !== 'undefined') { for (const fKey in window.movesets) { for (const move of window.customMoves) { if (!window.movesets[fKey].some(m => m.name === move.name)) { window.movesets[fKey].push(move); } } } } // Show a quick visual HUD notification in the arena if it's already running const arena = document.getElementById('arena'); if (arena) { const badge = document.createElement('div'); badge.style.position = 'absolute'; badge.style.top = '80px'; badge.style.right = '20px'; badge.style.background = 'rgba(0,0,0,0.8)'; badge.style.border = '2px solid #00ffcc'; badge.style.color = '#00ffcc'; badge.style.padding = '8px 16px'; badge.style.fontFamily = "'Bebas Neue', sans-serif"; badge.style.fontSize = '24px'; badge.style.letterSpacing = '2px'; badge.style.zIndex = '9999'; badge.style.pointerEvents = 'none'; badge.style.boxShadow = '0 0 15px rgba(0,255,204,0.4)'; badge.innerHTML = 'WWE 2K MOCAP LIBRARY INJECTED ✓'; arena.appendChild(badge); setTimeout(() => { if(badge.parentNode) badge.parentNode.removeChild(badge); }, 4000); } }; // Execute it now! window.BANNON_LOAD_FBX_LIBRARY(); } else { setTimeout(attemptFBXLoad, 500); } } // Start polling to execute once FBX Loader is instantiated. // LAG FIX: was 1000ms — landed right on char select / the opening bell. Let the game settle first. setTimeout(attemptFBXLoad, 12000); // Update version badge to 119 const vb = document.getElementById('ver-badge'); if (vb) vb.textContent = 'BANNON v119'; })();
👁 GOD WITHIN — ROAM & CONFRONT