Arena Fighter Blueprint, Build a 2-Player Fighting Game
JVDesignStudio - https://jvdesignstudio.co.uk/workshops/unreal-fighter-workshop.html

Offline reference pack for this workshop.
This is a companion copy of the build steps, so you can follow along without
the website. Open the workshop online for the interactive screenshots, videos
and the copy buttons.

What you build: Arena Fighter Blueprint, Build a 2-Player Fighting Game

--------------------------------------------------------------------
STEP-BY-STEP BUILD
--------------------------------------------------------------------

## STEP 1 SETUP - Choose Your Opponent
- Before wiring a single node, you need to decide: AI or Human? This choice changes which Input Bindings and AI Controller nodes you'll wire later. Pick a mode then connect the BeginPlay flow.

## STEP 2 PROJECT - Event BeginPlay',x:4,y:20,w:148,h:58,lp:[],rp:[{id:'r1',type:'exec',label:''}]}, {id:'n2',type:'func',title:'Set Opponent Mode',x:174,y:10,w:148,h:58,lp:[{id:'l2',type:'exec',label:''},{id:'l2m',type:'string',label:'Mode'}],rp:[{id:'r2',type:'exec',label:''}],vf:{hint:'ai or human',val:''}}, {id:'n3',type:'func',title:'Init Fighter Actors',x:340,y:20,w:148,h:58,lp:[{id:'l3',type:'exec',label:''}],rp:[]}, ],[{f:'r1',t:'l2'},{f:'r2',t:'l3'}],[{id:'n2',ok:v=>v==='ai'||v==='human'}]), extraHTML:` ⭐AI OpponentSolo play. The AI reacts, blocks, and attacks using a Behaviour Tree. ⭐2-Player LocalTwo players, one keyboard. P1: WASD+F+G+S. P2: Arrows+,+.+? `, boxes:[{t:'box-c',tx:'In Unreal, create a BP_GameMode, a BP_FighterP1 and a BP_FighterP2 (or BP_FighterAI). Your mode choice here links to which Pawn Controller gets possessed at game start.'}], quizHTML:` ⭐Knowledge Check+15 XP In Unreal Engine, what determines which Pawn Controller gets possessed at game start? AThe Level Blueprint BThe Game Mode CThe Player Controller Check Answer Continue → ⚡True or False+15 XP AI opponents use a Behaviour Tree to make decisions.TrueFalse You can only have one player in an Unreal fighting game.TrueFalse Check Answers `, onApply(v){ F.opponentMode = v['n2']==='human'?'human':'ai'; updateFighterCard(); sout('✅ Opponent mode set to: '+(F.opponentMode==='ai'?'AI Bot':'Human Player 2')); }}, /* -- STEP 2 -- FIGHTER PROJECT SETUP -- */ {title:'Fighter Project Setup
- Every fight needs a stage. Wire the level setup: spawn the ring mesh, set gravity, and fix the camera to a locked side-on perspective, the hallmark of the fighting genre.

## STEP 3 MOVE - Event BeginPlay',x:4,y:24,w:148,h:58,lp:[],rp:[{id:'r1',type:'exec',label:''}]}, {id:'n2',type:'func',title:'Spawn Ring Mesh',x:174,y:8,w:148,h:58,lp:[{id:'l2',type:'exec',label:''}],rp:[{id:'r2',type:'exec',label:''}]}, {id:'n3',type:'func',title:'Set Camera Side-On',x:340,y:8,w:148,h:58,lp:[{id:'l3',type:'exec',label:''}],rp:[{id:'r3',type:'exec',label:''}]}, {id:'n4',type:'func',title:'Set World Gravity',x:340,y:78,w:148,h:58,lp:[{id:'l4',type:'exec',label:''},{id:'l4g',type:'float',label:'Z Value'}],rp:[],vf:{hint:'e.g. -980',val:''}}, ],[{f:'r1',t:'l2'},{f:'r2',t:'l3'},{f:'r3',t:'l4'}],[{id:'n4',ok:v=>parseFloat(v) ⭐Knowledge Check+15 XP What camera setup is standard for a 2D fighting game? AFree-look third person BFirst person CFixed side-on perspective Check Answer Continue → ⭐Fill in the Blank+15 XP In Unreal Engine, gravity is measured in cm/s· and a typical value is . The camera should be fixed on the -axis. Check Answers `, onApply(v){ sout('? Stage ready! Gravity: '+v['n4']+' cm/s·, ring and camera spawned.'); }}, /* -- STEP 3 -- PLAYER MOVEMENT -- */ {title:'Player Movement
- Connect the Enhanced Input action to Character Movement. Wire IA_Move (A/D for P1) to Add Movement Input. Type the walk speed.

## STEP 4 JUMP - IA_Move (Triggered)',sub:'BP_FighterP1',x:4,y:24,w:160,h:58,lp:[],rp:[{id:'r1',type:'exec',label:''},{id:'r1v',type:'float',label:'Action Value'}]}, {id:'n2',type:'func',title:'Add Movement Input',x:190,y:8,w:148,h:58,lp:[{id:'l2',type:'exec',label:''},{id:'l2d',type:'float',label:'Scale'}],rp:[{id:'r2',type:'exec',label:''}]}, {id:'n3',type:'func',title:'Set Max Walk Speed',x:358,y:8,w:148,h:58,lp:[{id:'l3',type:'exec',label:''},{id:'l3s',type:'float',label:'Speed'}],rp:[],vf:{hint:'e.g. 500',val:''}}, ],[{f:'r1',t:'l2'},{f:'r1v',t:'l2d'},{f:'r2',t:'l3'}],[{id:'n3',ok:v=>parseFloat(v)>=200&&parseFloat(v) ⭐Knowledge Check+15 XP Which Unreal node feeds the direction value for character movement? AIA_Move (Action Value output) BEvent Tick (Delta Seconds) CGet Actor Location Check Answer Continue → ⭐Blueprint Code Challenge+20 XP Complete the Blueprint pseudocode for player movement: IA_Move (Triggered) ? ? Set Max Walk Speed() Check Code Hint: The node that moves the character is "Add Movement Input". A good walk speed is 500. `, onApply(v){ F.speed=parseFloat(v['n3'])||500; F.f_movement=true; updateFighterCard(); sout('✅ Movement live! A/D to move P1 at '+F.speed+' UU/s.'); }}, /* -- STEP 4 -- JUMP -- */ {title:'Jump & Gravity
- Wire the IA_Jump action to the Character's Launch Character node. Set launch velocity Z for jump height.

## STEP 5 HEALTH - IA_Jump (Started)',sub:'BP_FighterP1',x:4,y:24,w:148,h:58,lp:[],rp:[{id:'r1',type:'exec',label:'Started'}]}, {id:'n2',type:'func',title:'Launch Character',x:174,y:8,w:148,h:58,lp:[{id:'l2',type:'exec',label:''},{id:'l2z',type:'float',label:'Z Velocity'}],rp:[{id:'r2',type:'exec',label:''}],vf:{hint:'e.g. 700',val:''}}, ],[{f:'r1',t:'l2'}],[{id:'n2',ok:v=>parseFloat(v)>=400&&parseFloat(v) ⭐Predict What Happens+15 XP You set Launch Character Z Velocity to 1400 with gravity at -980. What happens? AThe fighter barely leaves the ground BThe fighter jumps very high with a long hang time CThe fighter gets stuck in mid-air Check Prediction ⚡True or False+15 XP Launch Character uses a Z velocity value to control jump height.TrueFalse Both fighters need separate IA_Jump input bindings.TrueFalse A Z velocity of 100 gives a high, floaty jump.TrueFalse Check Answers `, onApply(v){ F.f_jump=true; sout('✅ Jump unlocked! Z launch: '+v['n2']+'. Both fighters can now leave the ground.'); }}, /* -- STEP 5 -- HEALTH SYSTEM -- */ {title:'Health Component
- Create an Actor Component BP_HealthComp. Wire TakeDamage ? Subtract HP ? Check if HP = 0 ? Broadcast OnDeath. Type the starting HP.

## STEP 6 LIGHT - Event TakeDamage',sub:'BP_HealthComp',x:4,y:10,w:148,h:58,lp:[],rp:[{id:'r1',type:'exec',label:''},{id:'r1d',type:'float',label:'Damage'}]}, {id:'n2',type:'func',title:'Subtract Health',x:174,y:8,w:120,h:58,lp:[{id:'l2',type:'exec',label:''},{id:'l2d',type:'float',label:'Amount'}],rp:[{id:'r2',type:'exec',label:''},{id:'r2h',type:'float',label:'New HP'}]}, {id:'n3',type:'macro',title:'Branch (HP = 0?)',x:314,y:8,w:120,h:58,lp:[{id:'l3',type:'exec',label:''},{id:'l3c',type:'bool',label:'Cond'}],rp:[{id:'r3t',type:'exec',label:'True'},{id:'r3f',type:'exec',label:'False'}]}, {id:'n4',type:'custom',title:'Broadcast OnDeath',x:454,y:4,w:80,h:48,lp:[{id:'l4',type:'exec',label:''}],rp:[]}, {id:'n5',type:'func',title:'Set Start HP',x:454,y:68,w:80,h:48,lp:[{id:'l5',type:'exec',label:''},{id:'l5h',type:'float',label:'HP'}],rp:[],vf:{hint:'e.g. 100',val:''}}, ],[{f:'r1',t:'l2'},{f:'r1d',t:'l2d'},{f:'r2',t:'l3'},{f:'r3t',t:'l4'},{f:'r3f',t:'l5'}],[{id:'n5',ok:v=>parseFloat(v)>=50&&parseFloat(v) ⭐Knowledge Check+15 XP Why should OnDeath use a Broadcast Dispatcher instead of directly ending the game? AIt runs faster BIt uses less memory CIt decouples the health component from the game mode, so multiple systems can react Check Answer Continue → ⭐Order the Steps+15 XP Put the health system flow in the correct order: Branch: is HP = 0? TakeDamage event fires Broadcast OnDeath Subtract damage from HP Check Order Reset `, onApply(v){ F.hp=parseFloat(v['n5'])||100; GS.p1.maxHp=F.hp; GS.p2.maxHp=F.hp; resetRound(); updateFighterCard(); sout('✅ Health system active, each fighter starts with '+F.hp+' HP.'); }}, /* -- STEP 6 -- LIGHT ATTACK -- */ {title:'Light Attack
- Wire the IA_LightAtk action ? Play Animation Montage (light combo anim) ? call ApplyDamage on the opponent if the hitbox overlaps. Type the light hit damage.

## STEP 7 HEAVY - IA_LightAtk (Started)',sub:'BP_FighterP1',x:4,y:24,w:158,h:58,lp:[],rp:[{id:'r1',type:'exec',label:'Started'}]}, {id:'n2',type:'func',title:'Play Anim Montage',x:183,y:8,w:138,h:58,lp:[{id:'l2',type:'exec',label:''},{id:'l2m',type:'object',label:'Montage'}],rp:[{id:'r2',type:'exec',label:''}]}, {id:'n3',type:'func',title:'Hitbox Overlap?',x:341,y:8,w:120,h:58,lp:[{id:'l3',type:'exec',label:''}],rp:[{id:'r3',type:'exec',label:'Hit'},{id:'r3a',type:'object',label:'Actor'}]}, {id:'n4',type:'func',title:'Apply Damage',x:481,y:4,w:58,h:58,lp:[{id:'l4',type:'exec',label:''},{id:'l4d',type:'float',label:'Dmg'}],rp:[],vf:{hint:'e.g. 10',val:''}}, ],[{f:'r1',t:'l2'},{f:'r2',t:'l3'},{f:'r3',t:'l4'}],[{id:'n4',ok:v=>parseFloat(v)>=5&&parseFloat(v) ⭐Knowledge Check+15 XP Why should you use an Animation Notify to open/close the hitbox instead of leaving it always active? AIt makes the animation play faster BIt prevents phantom hits when the fighter isn't actually punching CIt reduces the file size of the Blueprint Check Answer Continue → ⭐Fill in the Blank+15 XP A light attack should be (fast/slow) with a startup around seconds. Light attacks are safe on . Check Answers `, onApply(v){ F.f_light=true; const d=parseFloat(v['n4'])||10; sout('? Light attack live! '+d+' damage · fast startup · press F to test.'); }}, /* -- STEP 7 -- HEAVY ATTACK -- */ {title:'Heavy Attack
- Wire the IA_HeavyAtk action to a slower montage with more damage. Type the heavy hit damage, it should be roughly 2· the light attack.

## STEP 8 BLOCK - IA_HeavyAtk (Started)',sub:'BP_FighterP1',x:4,y:24,w:158,h:58,lp:[],rp:[{id:'r1',type:'exec',label:'Started'}]}, {id:'n2',type:'func',title:'Play Heavy Montage',x:183,y:8,w:148,h:58,lp:[{id:'l2',type:'exec',label:''}],rp:[{id:'r2',type:'exec',label:''}]}, {id:'n3',type:'func',title:'Apply Heavy Damage',x:351,y:8,w:148,h:58,lp:[{id:'l3',type:'exec',label:''},{id:'l3d',type:'float',label:'Damage'}],rp:[],vf:{hint:'e.g. 20',val:''}}, ],[{f:'r1',t:'l2'},{f:'r2',t:'l3'}],[{id:'n3',ok:v=>parseFloat(v)>=10&&parseFloat(v) ⭐Predict What Happens+15 XP A heavy attack deals 40 damage with a 0.7s windup. The opponent has a fast light attack (0.3s). What is most likely to happen if both attack at the same time? AThe heavy attack always wins because it does more damage BBoth attacks cancel each other out CThe light attack hits first because its startup is shorter Check Prediction ⚡True or False+15 XP Heavy attacks should deal roughly 2x the damage of light attacks.TrueFalse A longer windup animation is the tradeoff for higher damage.TrueFalse Heavy attacks should have the same startup speed as light attacks.TrueFalse Check Answers `, onApply(v){ F.dmg=parseFloat(v['n3'])||20; F.f_heavy=true; updateFighterCard(); sout('? Heavy attack live! '+F.dmg+' damage · press G to test.'); }}, /* -- STEP 8 -- BLOCKING -- */ {title:'Block Mechanic
- Wire the IA_Block input to set a boolean IsBlocking. Wire TakeDamage to a Branch on IsBlocking, if true, reduce damage by 85%.

## STEP 9 COMBO - IA_Block',sub:'BP_FighterP1',x:4,y:10,w:148,h:58,lp:[],rp:[{id:'r1p',type:'exec',label:'Started'},{id:'r1r',type:'exec',label:'Completed'}]}, {id:'n2',type:'func',title:'Set IsBlocking True',x:174,y:4,w:148,h:48,lp:[{id:'l2',type:'exec',label:''}],rp:[{id:'r2',type:'exec',label:''}]}, {id:'n3',type:'func',title:'Set IsBlocking False',x:174,y:66,w:148,h:48,lp:[{id:'l3',type:'exec',label:''}],rp:[]}, ],[{f:'r1p',t:'l2'},{f:'r1r',t:'l3'}],[]), boxes:[{t:'box-t',tx:'Bind S (hold) for P1 block, ? for P2. In TakeDamage, Branch on IsBlocking: True ? multiply damage by 0.15. Give the blocked fighter a chip-damage sound cue.'}], quizHTML:` ⭐Knowledge Check+15 XP In the TakeDamage Blueprint, what does the Branch node check when blocking is implemented? AWhether the attacker is in range BWhether the IsBlocking boolean is true CWhether the defender has enough HP Check Answer Continue → ⭐Blueprint Code Challenge+20 XP Complete the block damage reduction logic: TakeDamage ? Branch(IsBlocking) True ? Damage · False ? Damage · Check Code Hint: Blocking reduces damage by 85%, so only 15% gets through (0.15). Unblocked is full damage (1). `, onApply(){ F.f_block=true; sout('✅ Blocking active! Hold S to block (P1). Damage reduced by 85% when blocking.'); }}, /* -- STEP 9 -- COMBO SYSTEM -- */ {title:'Combo Counter
- Wire each successful hit to Increment a Combo Counter. After X consecutive hits within a time window, add a Combo Multiplier. Wire a Reset on idle. Type your max combo length.

## STEP 10 SPECIAL - On Hit Landed',x:4,y:24,w:130,h:58,lp:[],rp:[{id:'r1',type:'exec',label:''}]}, {id:'n2',type:'func',title:'Increment Combo',x:156,y:8,w:128,h:58,lp:[{id:'l2',type:'exec',label:''}],rp:[{id:'r2',type:'exec',label:''},{id:'r2c',type:'int',label:'Count'}]}, {id:'n3',type:'func',title:'Set Combo Multiplier',x:305,y:8,w:148,h:58,lp:[{id:'l3',type:'exec',label:''},{id:'l3m',type:'float',label:'Mult'}],rp:[{id:'r3',type:'exec',label:''}]}, {id:'n4',type:'func',title:'Set Max Combo Hits',x:473,y:8,w:66,h:58,lp:[{id:'l4',type:'exec',label:''},{id:'l4n',type:'int',label:'Max'}],rp:[],vf:{hint:'e.g. 5',val:''}}, ],[{f:'r1',t:'l2'},{f:'r2',t:'l3'},{f:'r3',t:'l4'}],[{id:'n4',ok:v=>parseInt(v)>=2&&parseInt(v) ⭐Knowledge Check+15 XP What should reset the combo counter in a fighting game? ANo hit landing within the combo time window (e.g. 1.5s) BThe opponent blocking CThe player pressing a different button Check Answer Continue → ⭐Order the Combo Flow+15 XP Put the combo system steps in order: Increment combo counter Reset combo if timer expires Hit lands on opponent Apply combo multiplier to damage Check Order Reset `, onApply(v){ F.f_combo=true; F.combo=parseInt(v['n4'])||5; sout('✅ Combo system active! Max '+F.combo+' hits. Chain attacks to build combos!'); }}, /* -- STEP 10 -- SPECIAL MOVE -- */ {title:'Special Move
- Wire a Special Move using a gesture sequence, e.g. ↓↘→ + F (quarter-circle forward). Use an Input Buffer array. On match, trigger a high-damage attack.

## STEP 11 AI - Input Buffer Tick',x:4,y:24,w:138,h:58,lp:[],rp:[{id:'r1',type:'exec',label:''}]}, {id:'n2',type:'func',title:'Check Buffer Sequence',x:163,y:8,w:148,h:58,lp:[{id:'l2',type:'exec',label:''}],rp:[{id:'r2t',type:'exec',label:'Match!'},{id:'r2f',type:'exec',label:'No Match'}]}, {id:'n3',type:'func',title:'Trigger Special Attack',x:333,y:4,w:148,h:58,lp:[{id:'l3',type:'exec',label:''}],rp:[{id:'r3',type:'exec',label:''}]}, {id:'n4',type:'func',title:'Clear Input Buffer',x:333,y:72,w:148,h:48,lp:[{id:'l4',type:'exec',label:''}],rp:[]}, ],[{f:'r1',t:'l2'},{f:'r2t',t:'l3'},{f:'r2f',t:'l4'}],[]), boxes:[ {t:'box-c',tx:'An Input Buffer is an array of recent inputs stamped with time. Each Tick, append the current frame inputs and flush anything older than 0.3s.'}, {t:'box-t',tx:'Start simple: just press F+G simultaneously as the special trigger. Once that works, graduate to sequence inputs.'}, ], quizHTML:` ⭐Predict What Happens+15 XP Your Input Buffer stores the last 0.3 seconds of inputs. The player presses ?, ?, F in 0.2 seconds. What happens? AThe buffer matches the quarter-circle-forward sequence and triggers the special attack BOnly the F (light attack) fires because input buffers only store one input CNothing happens because 0.2s is too fast Check Prediction ⚡True or False+15 XP An Input Buffer is an array of recent inputs stamped with time.TrueFalse You should keep old inputs in the buffer forever.TrueFalse A good beginner special-move trigger is pressing two buttons simultaneously.TrueFalse Check Answers `, onApply(){ F.f_special=true; sout('✅ Special move wired! Press F+G together for a super attack.'); }}, /* -- STEP 11 -- AI CONTROLLER -- */ {title:'AI Behaviour Tree
- Create a BP_AIController and attach a Behaviour Tree (BT_Fighter). Wire BeginPlay ? Run Behaviour Tree. Inside the BT add: Approach ? Attack ? Block (with random weights). Connect Possess Pawn.

## STEP 12 HUD - Event BeginPlay',sub:'BP_AIController',x:4,y:24,w:148,h:58,lp:[],rp:[{id:'r1',type:'exec',label:''}]}, {id:'n2',type:'func',title:'Run Behaviour Tree',x:174,y:8,w:148,h:58,lp:[{id:'l2',type:'exec',label:''},{id:'l2bt',type:'object',label:'BT Asset'}],rp:[{id:'r2',type:'exec',label:''}]}, {id:'n3',type:'ai',title:'BT: Approach Target',x:342,y:4,w:148,h:48,lp:[{id:'l3',type:'exec',label:''}],rp:[{id:'r3',type:'exec',label:''}]}, {id:'n4',type:'ai',title:'BT: Attack (Random)',x:342,y:66,w:148,h:48,lp:[{id:'l4',type:'exec',label:''}],rp:[]}, ],[{f:'r1',t:'l2'},{f:'r2',t:'l3'},{f:'r3',t:'l4'}],[]), boxes:[ {t:'box-ai',tx:'The Behaviour Tree runs on a Selector: first try Attack (if in range), else Approach, else Block (random 20% chance). This gives the AI a natural rhythm.'}, {t:'box-t',tx:'Skip this step if you chose 2-Player Human mode, the AI controller won\'t be possessed in that case.'}, ], quizHTML:` ⭐Knowledge Check+15 XP In a Behaviour Tree, what node type tries children in order and stops at the first success? ASequence BParallel CSelector Check Answer Continue → ⭐Order the AI Priority+15 XP Put the AI Behaviour Tree actions in priority order (highest first): Block (random 20% chance) Attack (if in range) Approach target Check Order Reset `, onApply(){ F.f_ai=true; sout('✅ AI controller live! The bot will approach, attack, and block. Fight!'); }}, /* -- STEP 12 -- HUD & HEALTH BARS -- */ {title:'HUD & Health Bars
- Create a Widget Blueprint WBP_FightHUD. Add two Progress Bars (P1HP, P2HP), a Round timer text, and a Round counter. Wire Create Widget ? Add to Viewport on BeginPlay.

## STEP 13 ROUNDS - Event BeginPlay',sub:'BP_GameMode',x:4,y:24,w:148,h:58,lp:[],rp:[{id:'r1',type:'exec',label:''}]}, {id:'n2',type:'func',title:'Create WBP_FightHUD',x:174,y:8,w:148,h:58,lp:[{id:'l2',type:'exec',label:''}],rp:[{id:'r2',type:'exec',label:''},{id:'r2w',type:'object',label:'Widget'}]}, {id:'n3',type:'func',title:'Add to Viewport',x:342,y:8,w:136,h:58,lp:[{id:'l3',type:'exec',label:''},{id:'l3w',type:'object',label:'Target'}],rp:[{id:'r3',type:'exec',label:''}]}, {id:'n4',type:'func',title:'Bind HP to Progress Bar',x:342,y:76,w:136,h:48,lp:[{id:'l4',type:'exec',label:''}],rp:[]}, ],[{f:'r1',t:'l2'},{f:'r2',t:'l3'},{f:'r2w',t:'l3w'},{f:'r3',t:'l4'}],[]), boxes:[{t:'box-t',tx:'Bind the P1HP ProgressBar percent to (CurrentHP / MaxHP) using a Binding function in the Widget. Repeat for P2. The timer text binds to the GameMode timer variable.'}], quizHTML:` ⭐Knowledge Check+15 XP How do you bind a health bar's fill percentage to the fighter's current HP in Unreal? AUse a Binding function on the Progress Bar percent: CurrentHP / MaxHP BSet the bar width manually every frame in the Level Blueprint CUse a material instance to change the bar colour Check Answer Continue → ⭐Blueprint Code Challenge+20 XP Complete the HUD setup flow: BeginPlay ? ? ? Bind HP Check Code Hint: First you create the widget, then add it to the viewport. `, onApply(){ F.f_hud=true; sout('✅ HUD live! Health bars and timer now visible during the fight.'); }}, /* -- STEP 13 -- ROUND SYSTEM -- */ {title:'Round System (Best of 3)
- Wire the OnDeath dispatcher ? Award Round Win ? Check if Wins = 2 ? if True show Victory Screen, else Reset Round. Wire a 99-second countdown timer.

## STEP 14 🚀 LAUNCH - On Fighter Death',x:4,y:24,w:138,h:58,lp:[],rp:[{id:'r1',type:'exec',label:''},{id:'r1p',type:'object',label:'Fighter'}]}, {id:'n2',type:'func',title:'Award Round Win',x:164,y:8,w:136,h:58,lp:[{id:'l2',type:'exec',label:''},{id:'l2p',type:'object',label:'Winner'}],rp:[{id:'r2',type:'exec',label:''},{id:'r2w',type:'int',label:'Wins'}]}, {id:'n3',type:'macro',title:'Branch (Wins = 2)',x:320,y:8,w:130,h:58,lp:[{id:'l3',type:'exec',label:''},{id:'l3c',type:'bool',label:'Cond'}],rp:[{id:'r3t',type:'exec',label:'Match Win'},{id:'r3f',type:'exec',label:'Next Round'}]}, {id:'n4',type:'func',title:'Show Victory Screen',x:470,y:4,w:68,h:48,lp:[{id:'l4',type:'exec',label:''}],rp:[]}, {id:'n5',type:'func',title:'Reset Round',x:470,y:66,w:68,h:48,lp:[{id:'l5',type:'exec',label:''}],rp:[]}, ],[{f:'r1',t:'l2'},{f:'r2',t:'l3'},{f:'r3t',t:'l4'},{f:'r3f',t:'l5'}],[]), boxes:[{t:'box-f',tx:'Best of 3 means first to 2 round wins takes the match. Show a "Round 2" / "Round 3" splash screen between rounds with a short Delay before resetting fighters.'}], quizHTML:` ⭐Predict What Happens+15 XP P1 has won 1 round. P2 has won 1 round. P1 knocks out P2 in Round 3. What should the game do? AStart Round 4 BShow the Victory Screen, P1 reached 2 wins first CReset both players' win counts and start over Check Prediction ⚡True or False+15 XP "Best of 3" means the first player to win 2 rounds takes the match.TrueFalse A round timer prevents matches from going on forever.TrueFalse When the timer runs out, the round is a draw with no winner.TrueFalse Check Answers `, onApply(){ F.f_rounds=true; sout('✅ Round system: Best of 3. First to 2 round wins takes the match!'); }}, /* -- STEP 14 -- FIGHTER NAME & LAUNCH -- */ {title:'Name Your Fighter & Launch!
- Connect Game Start → Sequence → Enable all systems. Type your fighter's name then hit Launch, the full fighting game is ready!
