Simple Autotext/Cutscenes [4.15]

crazygrouptrio

Active member
For anyone looking for a simple or less intrusive way to make cutscenes for your game, this may be for you! Using this method you can have all 4 entries of a text group flow together (or even space them out if you prefer) without having to dig deep into the code. You could make things like this!
c96JwMR.gif

Short version of how this works, is we make a monster action that brings up a text entry based on a numbered variable. Each entry sets up the variable for the next entry, so we can use the same monster action over and over to bring up the next text entry within the group. Note that if you have done anything else that effects how text boxes or monster actions work this may not work. But it works fine out of the box. So let's set it up!

EDIT: Consider this method "finicky" as it seems to misbehave depending on other scripts being used. This method doesn't mess with your files much, but ALWAYS MAKE A BACKUP ANYWAY.

First we need to make two user variables:
  • npc_autotext
    textaction
Just go to user variables, add those 2 variables and just leave them set at 0. We're done here now.

Next we need to add the monster ai script to bring up the text.
Code:
	LDA textaction
	CMP #$03
	BNE +
	JMP textFour
	+
	LDA textaction
	CMP #$02
	BNE +
	JMP textThree
	+
	LDA textaction
	CMP #$01
	BNE +
	JMP textTwo
	+
	LDA textaction
	CMP #$00
	BNE +
	JMP textOne
	+
	RTS
	
	textFour:
	LDA #$03  ;;<<-- it will use the "Text 4" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	LDA #$00
 	STA textaction
	RTS
	
	textThree:
	LDA #$02  ;;<<-- it will use the "Text 3" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	
	LDA #$03
	STA textaction
	
	RTS
	textTwo:
	LDA #$01  ;;<<-- it will use the "Text 2" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	
	LDA #$02
	STA textaction
	RTS
	
	textOne:
	LDA #$00  ;;<<-- it will use the "Text 1" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	
	LDA #$01
  	STA textaction
	RTS
Go ahead and save this script, then go to script settings and add it to whatever AI Action slot you have available (remember to change the project label for it as well!) As stated above, this script runs an autotext function based on what the textaction variable is set to. E.g. When it runs the first time, it sees the textaction variable is at 0, so it runs the script for bringing up text entry 1 then sets the variable to 1. So the next time this SAME action script runs it will see that the variable is set to 1 and run the script for text entry 2, and so on. Neat right?

Now we need to be able to use a button to make this text proceed. Dale Coop's script for the autotext input works here.
Code:
LDA textboxHandler
    AND #%00010000 ;; if the b button is pressed
                    ;; but the box + text have been activated
                    ;; and also the 'do box' bit is OFF
                    ;; that means this is ready to "go away".
                    
    BEQ checkToTurnTheTextboxOn ;; hasn't started yet
    
    ;; begin turning the textbox off.
    LDA gameHandler
    ORA #%00100000
    STA gameHandler
    ;;; are we turning this on or off?
    ;;; check for more
    ;;; check for 'choice'.
  
    LDA #$00
    STA updateNT_offset
    STA updateNT_H_offset
    STA updateNT_V_offset
	
	STA npc_autotext	;;<-- dale_coop: for autotext tiles
    
    LDA #%10001000
    STA textboxHandler
    RTS
   
checkToTurnTheTextboxOn:  
	LDA npc_autotext	;;<-- dale_coop: for autotext tiles
	BEQ +
	JMP ++
+
    LDA npc_collision
    BEQ noNPCcollision
++	
    LDA textboxHandler
    AND #%10000000
    BNE noNPCcollision
    LDA gameHandler
    ORA #%00100000
    STA gameHandler
    ;;; are we turning this on or off?
    ;;; check for more
    ;;; check for 'choice'.

turnTheTextboxOn:
  
    LDA #%10000000
    STA textboxHandler
    
noNPCcollision:
    RTS
Go ahead and add this to your input scripts and set it to whatever button press you like. (I prefer the A button).

Now for the fun part, actually implementing this into our cutscene. We'll just do a basic setup right now. Make your monster and set up its first 4 action steps just like this.
NSDxv85.png

I like to set the end action timer to 2 for some wiggle room dealing with other monster's animations, but whatever you want should be fine as long as it isn't 0. Also note DO NOT use "end animation" with monsters using the Text Action. The reason this code works is that the end action timer is put on hold while a text box is on screen, and then resumes when the text leaves. So when you set the timer, that timer won't actually start until the text entry is over. End Animation on the other hand IS NOT put on hold while text is on screen. This can mess up your timing for other actions if the player skips through the text.

So what does all this mean? Well, any other monsters actions need to be setup between text entries. Like in the example above, the face on the left is set to a talking animation in action step 1 with a timer of 1 to make sure it advances within the end of the timer of the text action monster. The 2nd action is an idle face with a timer of 3 to make sure it doesn't appear for the 2nd text entry, then advances to action step 3 talking animation again for the 3rd text entry. In short it's a lot of math and coordination between actions. I find it easier to set all my text actions to 1 monster, but you can spread the actions around to other monsters in the scene if you prefer. As long as you don't exceed 4 text actions per screen.

Make sure the last end action is a warp to screen to get off the screen (and probably shouldn't be the same action as your last text action). If you don't plan to use all 4 text entries in a screen, you may want to add these 2 lines to your Warp to Screen script:
Code:
LDA #$00
    STA textaction
This resets the textaction variable to 0, so the text on the next screen will start with the first text entry. The textaction script does this on its own after text entry 4, but adding it to the warp to screen would probably be more stable anyway.

Now all you need to do is use your own method for hiding the HUD and the player. For hiding the player I find adding this script near the top of DrawSprites works best:
Code:
CPX player1_object
	BNE +
	LDA screenType
	CMP #$F9 ;; #249 ;whatever screen type you want
	BNE +
	RTS
	+
In this instance all screens using type 249 will skip drawing the player (which also shouldn't allow the player to use controls).

That's it! I hope this helps out some of you who have been struggling with cutscenes and look forward to seeing how you're able to use this!
 

CGdfc

New member
incredible tutorial, good job, it worked very well, I had to make some changes for the warp but I can pass the scenarios well.

but i have a little problem, how do i remove the hud in these screen scenes?
if i use the hide_hud of the screen_info properties nothing works.
 

dale_coop

Moderator
Staff member
You could modify the script assigned to the "Handle HUD" (in Project Settings > Script Settings), at the beginning, just after the "HandleHudData:" line, add this code:

Code:
	;; if the "hide hud" flag is set on the screen Infos:
	LDA screenFlags
	AND #%00000001
	BEQ +
	RTS
	+
 

CGdfc

New member
dale_coop said:
You could modify the script assigned to the "Handle HUD" (in Project Settings > Script Settings), at the beginning, just after the "HandleHudData:" line, add this code:

Code:
	;; if the "hide hud" flag is set on the screen Infos:
	LDA screenFlags
	AND #%00000001
	BEQ +
	RTS
	+

Hi dale_coop :)

I already had that code in the script, it still doesn't work for me.
this is my script:

Code:
HandleHudData:
	LDA screenFlags
	AND #%00000001
	BEQ +
	RTS
+
	LDA textboxHandler
	BEQ +
	RTS
+

	LDA HudHandler
	AND #%10000000
	BNE +
	RTS
+
	;; we may have to test to see if any other tiles are updating this frame.
	;; and skip if there are tiles updating.
	;; NOW let's find which element might be updating.
	LDA ActivateHudUpdate
	BEQ + ;; hud is not currently being updated
	;; HUD IS being currently activated
	JMP UpdateHudTiles
+ 
	;;;;;;;;;;;;;;;;;; FIRST, reset values:
	LDA #$00
	STA updateCHR_counter
	STA updateCHR_offset
	STA hudElementTilesMax	;; dale_coop fix for the hud updating issue (when 2 updates called at the same time)
	
;;; CHECK FIRST ELEMENT
	LDA DrawHudBytes
	AND #%10000000 
	BEQ +
	;; do first element
	LDY #$00
	JSR LoadHudElementInfo
	LDA #BOX_0_ASSET_0_STRING
	STA updateHUD_STRING
	LDA #BOX_0_ASSET_0_IMAGE
	STA updateHUD_IMAGE
	HudUpdateForNumericDisplay #BOX_0_ASSET_0_STRING
	JMP UpdateHudTiles
+
;;; CHECK SECOND ELEMENT
	LDA DrawHudBytes
	AND #%01000000 
	BEQ +
	;; do second element
	LDY #$01
	JSR LoadHudElementInfo
	LDA #BOX_0_ASSET_1_STRING
	STA updateHUD_STRING
	LDA #BOX_0_ASSET_1_IMAGE
	STA updateHUD_IMAGE
	HudUpdateForNumericDisplay #BOX_0_ASSET_1_STRING
	JMP UpdateHudTiles
+
+++++
;;; CHECK THIRD ELEMENT
	LDA DrawHudBytes
	AND #%00100000 
	BEQ +
	;; do third element
	LDY #$02
	JSR LoadHudElementInfo
	LDA #BOX_0_ASSET_2_STRING
	STA updateHUD_STRING
	LDA #BOX_0_ASSET_2_IMAGE
	STA updateHUD_IMAGE
	HudUpdateForNumericDisplay #BOX_0_ASSET_2_STRING
	JMP UpdateHudTiles
+
;;; CHECK FOURTH ELEMENT
	LDA DrawHudBytes
	AND #%00010000
	BEQ +
	;; do fourth element
	LDY #$03
	JSR LoadHudElementInfo
	LDA #BOX_0_ASSET_3_STRING
	STA updateHUD_STRING
	LDA #BOX_0_ASSET_3_STRING
		LDA #BOX_0_ASSET_3_IMAGE
	STA updateHUD_IMAGE
	HudUpdateForNumericDisplay #BOX_0_ASSET_3_STRING
	JMP UpdateHudTiles
+
;;; CHECK FIFTH ELEMENT
	LDA DrawHudBytes
	AND #%00001000 
	BEQ +
	;; do fifth element
	LDY #$04
	JSR LoadHudElementInfo
	LDA #BOX_0_ASSET_4_STRING
	STA updateHUD_STRING
		LDA #BOX_0_ASSET_4_IMAGE
	STA updateHUD_IMAGE
	HudUpdateForNumericDisplay #BOX_0_ASSET_4_STRING
	JMP UpdateHudTiles
+
;;; CHECK SIXTH ELEMENT
	LDA DrawHudBytes
	AND #%00000100 
	BEQ +
	;; do sixth element
	LDY #$05
	JSR LoadHudElementInfo
	LDA #BOX_0_ASSET_5_STRING
	STA updateHUD_STRING	
	LDA #BOX_0_ASSET_5_IMAGE
	STA updateHUD_IMAGE
	HudUpdateForNumericDisplay #BOX_0_ASSET_5_STRING
	JMP UpdateHudTiles
	
+
;;; CHECK SEVENTH ELEMENT
	LDA DrawHudBytes
	AND #%00000010
	BEQ +
	;; do seventh element
	LDY #$06
	JSR LoadHudElementInfo
	LDA #BOX_0_ASSET_6_STRING
	STA updateHUD_STRING
		LDA #BOX_0_ASSET_6_IMAGE
	STA updateHUD_IMAGE
	HudUpdateForNumericDisplay #BOX_0_ASSET_6_STRING
	JMP UpdateHudTiles
+
;;; CHECK EIGHTH ELEMENT
	LDA DrawHudBytes
	AND #%00000001 
	BEQ +
	;; do eigthth element.
	LDY #$07
	JSR LoadHudElementInfo
	LDA #BOX_0_ASSET_7_STRING
	STA updateHUD_STRING
		LDA #BOX_0_ASSET_7_IMAGE
	STA updateHUD_IMAGE
	HudUpdateForNumericDisplay #BOX_0_ASSET_7_STRING
	JMP UpdateHudTiles
+
	
	;; end of checking element bits.
	RTS
	
	
	
UpdateHudTiles:
	
	;;; one of the hud bits was flipped.
	;;; now we have all the necessary data to do the update
	;;; FIRST check the type of asset.
	LDA updateHUD_ASSET_TYPE
	BEQ + ;; is not zero asset type
	JMP notHudElement0
+
	;;;; generally, this is for the Var Image type.
	.include SCR_HUD_ELEMENT_0
	;;; rts is in the script
notHudElement0:
	CMP #$01
	BEQ +
	JMP notHudElement1
+

	.include SCR_HUD_ELEMENT_1
	;; rts is in the script
notHudElement1:
	CMP #$02
	BEQ +
	JMP notHudElement2
+
	.include SCR_HUD_ELEMENT_2
	;; rts is in the script
notHudElement2:
	;;; elements 1 and 2 have no mid-frame updates.
	CMP #$03
	BEQ +
	JMP notHudElelement3
+
	.include SCR_HUD_ELEMENT_3 
	;;; rts is in the script
	
notHudElelement3:

HandleHudData_direct:


SkipHandleHudData:

	RTS
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
LoadHudElementInfo:
	;;; hud element loaded into y.
	LDA HudActive,y
	STA updateHUD_active
	LDA HudInverse,y
	STA updateHUD_inverse
	LDA HudAssetTypes,y
	STA updateHUD_ASSET_TYPE
	LDA HudAssetX,y
	STA updateHUD_ASSET_X
	LDA HudAssetY,y
	STA updateHUD_ASSET_Y
	;LDA HudImage,y
	;STA updateHUD_IMAGE
	LDA HudBlank,y
	STA updateHUD_BLANK
	LDA HudRow,y
	STA updateHUD_ROW
	LDA HudColumn,y
	STA updateHUD_COLUMN
	LDA HudMaxValue,y
	STA hudElementTilesFull
	RTS
	
	
	
	
	
GetHudDrawPositionAndOffset:
	;; keep in mind, a HUD will always be in the first nametable.
	LDA #BOX_0_ORIGIN_X
	STA tileX
	LDA #BOX_0_ORIGIN_Y
	STA tileY 
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	JSR coordinatesToMetaNametableValue
	;; establishes updateNT_pos and updateNT_pos+1
	;;; FIRST, IF this has been tripped, blank all of the values
	LDA updateHUD_ASSET_Y
	ASL
	ASL
	ASL
	ASL
	ASL
	STA temp
	ORA updateHUD_ASSET_X
	STA temp
	
	LDA updateHUD_ASSET_Y
	LSR 
	LSR
	
	STA temp1
	
	LDA updateNT_pos 
	CLC
	ADC temp
	CLC
	ADC updateHUD_offset
	STA updateHUD_fire_Address_Lo
	LDA updateNT_pos+1
	ADC temp1
	STA updateHUD_fire_Address_Hi
	RTS
 

dale_coop

Moderator
Staff member
This is strange, make sure your screen has the "hide hud" set... and if it's a scrolling screen, it might not work (or maybe you need to set it to the first screen of the scrolling part... or all the screens?)
Or maybe you are using a sprite hud (like chronosv2 one)?
in that case, you will need to add that code in the sprite hud script.
 

CGdfc

New member
dale_coop said:
This is strange, make sure your screen has the "hide hud" set... and if it's a scrolling screen, it might not work (or maybe you need to set it to the first screen of the scrolling part... or all the screens?)
Or maybe you are using a sprite hud (like chronosv2 one)?
in that case, you will need to add that code in the sprite hud script.

no no, my game uses single screen, no scroll.
hide hud doesn't work, it basically locks everything.
without doing that, everything else works, including disappearing to the player.
the problem is the HUD I don't know how to remove it for this screen (I also use 249).
I don't know what script you mean.
salute
 

CGdfc

New member
I think I have solved it, it seems that the problem was the npc that I used to make the auto texts (very large in size)
 

Bucket Mouse

Active member
Hey, you might like to know....cancelling out the player sprite the way you do (in DrawSprites) only prevents the player sprite from being visible. You can still move the invisible player sprite, and load another screen if you hold one of the directional buttons long enough.

It needs one extra line. Here is the corrected version that deactivates the player sprite entirely:

Code:
CPX player1_object
	BNE +
	LDA screenType
	CMP #$F9 ;; #249 ;whatever screen type you want
	BNE +
	DeactivateCurrentObject
	RTS
	+

Also, there's one other issue, which I can't resolve yet: if you use the > symbol to break up the text, the screen freezes. I've asked Dale for help on this.
 

crazygrouptrio

Active member
Bucket Mouse said:
Hey, you might like to know....cancelling out the player sprite the way you do (in DrawSprites) only prevents the player sprite from being visible. You can still move the invisible player sprite, and load another screen if you hold one of the directional buttons long enough.

It needs one extra line. Here is the corrected version that deactivates the player sprite entirely:

Code:
CPX player1_object
	BNE +
	LDA screenType
	CMP #$F9 ;; #249 ;whatever screen type you want
	BNE +
	DeactivateCurrentObject
	RTS
	+

Also, there's one other issue, which I can't resolve yet: if you use the > symbol to break up the text, the screen freezes. I've asked Dale for help on this.
Thank you for your line suggestion to the tutorial ( I guess since the player can't move while text is on the screen its never been a problem for me :lol: ) I'm not sure about the issue with > however. I setup this script again and it seems to work fine as is in that regard. The only time I encountered a problem with > is when I warped from one "cutscene" screen to another. Then it would get stuck. I tried the suggestion posted in the fb group of removing
Code:
; LDA npc_collision
; BEQ noNPCcollision
from the input script but that definitely caused other problems... Unfortunately I do not have time at the moment to dive deep into it, but I put a warning up in the tutorial so anyone can know its a possibility. Hopefully someone more qualified than I has a fix for it :oops:
 

dale_coop

Moderator
Staff member
Ok, I tested the scripts from the tutorial Page 1. And it works great for me (even the ">").
In those scripts, it's the lines with:
Code:
	STA npc_autotext
That will make the code (">") working correctly.

So, Bucket Mouse, I'd suggest you to check that your scripts are the same than the ones on page 1.
Maye you changed something (I suspect you add already a "activate_text_box" script assigned to your inputs... and you kept it, instead of replacing it with the new one, from this tutorial?)
 

Bucket Mouse

Active member
They are the same. And it's only your script -- no repeats. This IS your script exactly, isn't it???

Code:
LDA textboxHandler
    AND #%00010000 ;; if the b button is pressed
                    ;; but the box + text have been activated
                    ;; and also the 'do box' bit is OFF
                    ;; that means this is ready to "go away".
                    
    BEQ checkToTurnTheTextboxOn ;; hasn't started yet
    
    ;; begin turning the textbox off.
    LDA gameHandler
    ORA #%00100000
    STA gameHandler
    ;;; are we turning this on or off?
    ;;; check for more
    ;;; check for 'choice'.
  
    LDA #$00
    STA updateNT_offset
    STA updateNT_H_offset
    STA updateNT_V_offset
	
	STA npc_autotext	;;<-- dale_coop: for autotext tiles
    
    LDA #%10001000
    STA textboxHandler
    RTS
   
checkToTurnTheTextboxOn:  
	LDA npc_autotext	;;<-- dale_coop: for autotext tiles
	BEQ +
	JMP ++
+
    LDA npc_collision
    BEQ noNPCcollision
++	
    LDA textboxHandler
    AND #%10000000
    BNE noNPCcollision
    LDA gameHandler
    ORA #%00100000
    STA gameHandler
    ;;; are we turning this on or off?
    ;;; check for more
    ;;; check for 'choice'.

turnTheTextboxOn:
  
    LDA #%10000000
    STA textboxHandler
    
noNPCcollision:
    RTS

It's come to this....I've attached the graphics files, routines and save file of my project to this post. Inspect it all for yourself, and please let me know just WHAT I'm doing wrong. And let me know when you've got this so I can delete the file.
 

dale_coop

Moderator
Staff member
Ok, it's a small error in the TextAction.asm script... the bug is the ">" will not work with the first Text.... on the other Texts (Text 2, 3, 4) it works.
This morning, I tested with Text 2, it' the reason it was working for me.

Here's a fixed "TextAction.asm" script:
Code:
	LDA textaction
	CMP #$03
	BNE +
	JMP textFour
	+
	LDA textaction
	CMP #$02
	BNE +
	JMP textThree
	+
	LDA textaction
	CMP #$01
	BNE +
	JMP textTwo
	+
	LDA textaction
	CMP #$00
	BNE +
	JMP textOne
	+
	RTS
	
	textFour:
	LDA #$03  ;;<<-- it will use the "Text 4" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	LDA #$00
 	STA textaction
	RTS
	
	textThree:
	LDA #$02  ;;<<-- it will use the "Text 3" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	
	LDA #$03
	STA textaction
	
	RTS
	textTwo:
	LDA #$01  ;;<<-- it will use the "Text 2" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	
	LDA #$02
	STA textaction
	RTS
	
	textOne:
	LDA #$00  ;;<<-- it will use the "Text 1" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	
	LDA #$01
  	STA textaction
	RTS
 

crazygrouptrio

Active member
dale_coop said:
Ok, it's a small error in the TextAction.asm script... the bug is the ">" will not work with the first Text.... on the other Texts (Text 2, 3, 4) it works.
This morning, I tested with Text 2, it' the reason it was working for me.

Here's a fixed "TextAction.asm" script:
Code:
	LDA textaction
	CMP #$03
	BNE +
	JMP textFour
	+
	LDA textaction
	CMP #$02
	BNE +
	JMP textThree
	+
	LDA textaction
	CMP #$01
	BNE +
	JMP textTwo
	+
	LDA textaction
	CMP #$00
	BNE +
	JMP textOne
	+
	RTS
	
	textFour:
	LDA #$03  ;;<<-- it will use the "Text 4" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	LDA #$00
 	STA textaction
	RTS
	
	textThree:
	LDA #$02  ;;<<-- it will use the "Text 3" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	
	LDA #$03
	STA textaction
	
	RTS
	textTwo:
	LDA #$01  ;;<<-- it will use the "Text 2" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	
	LDA #$02
	STA textaction
	RTS
	
	textOne:
	LDA #$00  ;;<<-- it will use the "Text 1" of your screen
	STA textVar
	LDA #$01
	STA npc_autotext
	;; activate the text-box:
	LDA gameHandler
	ORA #%00100000
	STA gameHandler
	LDA #%10000000
	STA textboxHandler
	
	LDA #$01
  	STA textaction
	RTS
Thanks for the fix Dale! I'll update the tutorial to reflect this.
 
Top Bottom