Jump to content


Photo

CutScene Scripting


  • Please log in to reply
No replies to this topic

#1 Yovaneth

Yovaneth

    The newly-appointed Master Builder of Baldur's Gate

  • Modder
  • 3058 posts

Posted 16 September 2008 - 04:29 AM


This started life as ?Cutscene Scripts By Max a.k.a Potencius? but by the time I had finished tidying it up, I had almost completely re-written it. However, I did keep to Max?s original layout style because it was simple, straightforward and understandable. - Yovaneth


Preface

Cutscene scripts are what you see in the game when the screen becomes unclickable. During cutscenes, characters and other things can perform actions without fear of interruption by the player. This is just a general overview and covers some things that might give you trouble.

A cutscene will always involve two or more scripts. The first script (the ?trigger script?) sets the game up for the follow-on script (the ?action script?) which drives the actual cutscene.


The Trigger Script

All trigger scripts require two main actions and have one optional action.

IF
  <CutScene_Triggers_Here> 
THEN
  RESPONSE#100 
	ClearAllActions()				// #1
	StartCutSceneMode()			   // #2
	StartCutScene("script_name")	// #3
END

Action Breakdown:

1. ClearAllActions(). This is optional, but makes sure that any actions being done (or are stacked to be done) by any .cre are cancelled before the cutscene starts.
2. StartCutSceneMode(). This action makes the screen unclickable by the player.
3. StartCutScene(?script_name?).This action references the script which actually performs the cutscene actions.

The Action Script

This is the script that actually drives the cutscene on-screen.

IF 
  <evaluation_triggers>() 					// #4 
THEN 
  RESPONSE#100 
	CutSceneID(<object>) 					// #5 
	<cutscene actions here> 
	EndCutSceneMode() 						// #6 
END

Action Breakdown:

4. <evaluation_triggers>(). Any triggers used here must evaluate to true to fire the cutscene. There is no reason why a simple TRUE() statement cannot be used but see also the final example.
5. CutSceneID(<object>). This action must be specified as the first action in a cutscene script. It signifies who (<object>) is performing the actions in the following commands.
6. EndCutSceneMode(). This makes the screen clickable again.

CutScene Actions

Actions in cutscene scripts can sometimes appear to be illogical in how they work. To force another .cre to perform an action you will need to make use of the ActionOverride() command. Any command that is not referenced by ActionOverride is performed by <object> i.e. the .cre that is running the script at that point.

IF 
  True() 
THEN 
  RESPONSE#100 
	CutSceneID(Player1) 
	ActionOverride("TROLL",Kill(Myself)) // #7 
	EndCutSceneMode() 
END

7. ActionOverride("TROLL",Kill(Myself)). This action has Player1 (the object in control of the cutscene) tell "TROLL" to kill himself. However, ActionOverride() can also be a bad thing to use in combination with certain other commands; in particular, commands that involve the use of a timer e.g. PlayDead().

IF 
  True() 
THEN 
  RESPONSE#100 
	CutSceneID(Player1) 
	ActionOverride("TROLL",PlayDead(180)) 
	MoveToObject("TROLL")
	EndCutSceneMode() 
END

In this script, right after Player1 tells "TROLL" to play dead, it is commanding him to move to "TROLL." However, he does not. With this combination, Player1 will only move to "TROLL" after the PlayDead() action is completed i.e. three minutes later. This is because the object running the cutscene must control the actions of all .cres involved in the cutscene. In this very simple case Player1 is controlling both his own actions and also those of ?TROLL?. The fix is fairly simple; use multiple scripting blocks within the cutscene and assign the actions to different objects using the CutSceneID(<object>) command.

IF 
  True() 
THEN 
  RESPONSE#100 
	CutSceneID("TROLL") 		//Assign the cutscene action to "TROLL"
	PlayDead(180) 					//TROLL plays dead
END 

IF 
  True() 
THEN 
  RESPONSE#100 
	CutSceneID(Player1) 		//Re-assign the cutscene action to Player1
	MoveToObject("TROLL") 		//Get Player1 to walk to TROLL
	EndCutSceneMode() 			//End the cutscene
END
This combination of statements make "TROLL" play dead while Player1 moves to him at the same time. Once Player1 has arrived at ?TROLL? the cutscene will end.

As a final example we?ll use the following scenario: after a long battle with the bad guys for possession of the escape portal, our party is scattered all over the landscape. We want them all to move towards the portal and once there, to be transported to the escape area. When Player1 arrives at the portal we will force the screen to fade to black and do the actual teleportation under cover of the darkness. When we arrive in the escape area the screen will fade back in. To achieve this, the area we are currently in also contains a trap region that recognises when Player1 is in front of the portal i.e. he/she is inside the trap's boundaries. The following is script run by the trap to see if Player1 is over the teleport region.

IF
  <TheBadGuysAreAllDead>
  IsOverMe([Player1])
  Global("Player1_Is_At_The_Portal","GLOBAL",0)
THEN
  RESPONSE #100
   SetGlobal("Player1_Is_At_The_Portal","GLOBAL",1)
END

Getting back to our escape cutscene: the trigger script:-

IF 
  <TheBadGuysAreAllDead>
THEN 
  RESPONSE#100
   SetGlobal("Escape_Portal_Is_Open","GLOBAL",1)
   ClearAllActions() 
   StartCutSceneMode() 
   StartCutScene("PORTJUMP") 
END

The action script-:

//Move player 1 to the escape portal
IF 
  Global("Escape_Portal_Is_Open","GLOBAL",1) 
THEN 
  RESPONSE#100 
	CutSceneID(Player1)
	MoveToPoint([x.y]) 
END

//Get the rest of the party to follow Player1
//You could use the MoveToPoint() command instead
IF 
  Global("Escape_Portal_Is_Open","GLOBAL",1) 
THEN 
  RESPONSE#100 
	CutSceneID(Player2)
	MoveToObject(Player1) 
END

IF 
  Global("Escape_Portal_Is_Open","GLOBAL",1) 
THEN 
  RESPONSE#100 
	CutSceneID(Player3)
	MoveToObject(Player1) 
END

IF 
  Global("Escape_Portal_Is_Open","GLOBAL",1) 
THEN 
  RESPONSE#100 
	CutSceneID(Player4)
	MoveToObject(Player1) 
END

IF 
  Global("Escape_Portal_Is_Open","GLOBAL",1) 
THEN 
  RESPONSE#100 
	CutSceneID(Player5)
	MoveToObject(Player1) 
END

IF 
  Global("Escape_Portal_Is_Open","GLOBAL",1) 
THEN 
  RESPONSE#100 
	CutSceneID(Player6)
	MoveToObject(Player1) 
END

//Player1 is at the escape portal (over the trap) so make everyone teleport out
IF
	Global("Player1_Is_At_The_Portal","GLOBAL",1)
THEN
	RESPONSE #100
	 SetGlobal("Escape_Portal_Is_Open","GLOBAL",2)
	 CutSceneID(Player1) 
	 FadeToColor([20.0],0) 						// Starts the fade to black 
	 Wait(2)									// Pause while the screen fades
	 LeaveAreaLUA("AREA","",[x.y],FACE) 					// Teleport out 
	 Wait(2) 
	 FadeFromColor([20.0],0) 					//Fade the screen back in
	 Wait(2) 								//Pause for the fade to complete
	 EndCutSceneMode()
END 

// As the script is running for all objects at the same time,
// we can make use of Player1?s fade timings and not repeat ourselves.
// The following actions will complete before Player1 ends the cutscene.

IF 
  Global("Escape_Portal_Is_Open","GLOBAL",2) 
THEN 
  RESPONSE#100 
	CutSceneID(Player2) 
	Wait(1) 
	LeaveAreaLUA("AREA","",[x.y],FACE) 
END 

IF 
  Global("Escape_Portal_Is_Open","GLOBAL",2) 
THEN 
  RESPONSE#100 
	CutSceneID(Player3) 
	Wait(1) 
	LeaveAreaLUA("AREA","",[x.y],FACE) 
END 

IF 
  Global("Escape_Portal_Is_Open","GLOBAL",2) 
THEN 
  RESPONSE#100 
	CutSceneID(Player4) 
	Wait(1) 
	LeaveAreaLUA("AREA","",[x.y],FACE) 
END 

IF 
  Global("Escape_Portal_Is_Open","GLOBAL",2) 
THEN 
  RESPONSE#100 
	CutSceneID(Player5) 
	Wait(1) 
	LeaveAreaLUA("AREA","",[x.y],FACE) 
END 

IF 
  Global("Escape_Portal_Is_Open","GLOBAL",2) 
THEN 
  RESPONSE#100 
	CutSceneID(Player6) 
	Wait(1) 
	LeaveAreaLUA("AREA","",[x.y],FACE) 
END

The main actions of any cutscene can always be stacked in Player1?s action list as Player1 is guaranteed to exist in every game.


[EDIT]Blocks replaced by speechmarks. Reminder to self - don't copy'n'paste from Word....

Edited by Yovaneth, 17 September 2008 - 01:40 AM.