argent77 Posted April 18, 2023 Share Posted April 18, 2023 (edited) Normally there is no way to execute cutscene scripts directly by spell effect. You are either forced to summon an invisible helper creature or have to use variables in conjunction with a global script to initiate a cutscene. In both cases there is a small chance that scripting can be interrupted or delayed by external events. However, opcode 298 allows you to execute the hardcoded cutscene script CUT250A.BCS. This effect is normally used to trigger the "Teleport to the Pocket Plane" cutscene in BG2-ToB, but it basically functions in all EE games (even in PST:EE). It is possible to hook into CUT250A.BCS and extend it to allow execution of arbitrary cutscene content. It only works in EE games however, since it makes use of the StartCutSceneEx() script action. The actual scripting would look like this: Spoiler CUT250A.BCS (hardcoded cutscene script executed by opcode 298): // Calls another cutscene script with activated trigger evaluation IF True() THEN RESPONSE #100 CutSceneId(Player1) StartCutSceneEx("CUT250B",TRUE) END CUT250B.BCS (new script with the actual cutscene content): // Ensures that the cutscene script is left in a valid state IF True() THEN RESPONSE #100 CutSceneId(Player1) SetGlobal("CUT250","GLOBAL",0) END // Execution of the original "teleport to pocket plane" script IF Global("CUT250","GLOBAL",0) THEN RESPONSE #100 CutSceneId(Player1) // ... EndCutSceneMode() END // Append custom scripting here: // Each new cutscene should use a unique Global("CUT250","GLOBAL") value. IF Global("CUT250","GLOBAL",1) THEN RESPONSE #100 CutSceneId(Player1) // ...custom cutscene content... EndCutSceneMode() END To make your own custom cutscene work you have to retrieve a free Global("CUT250","GLOBAL") value and use it in the cutscene, as shown above. Additionally you have to set the variable (e.g. via opcode 365) in the SPL, ITM or EFF resource along with opcode 298 to trigger the desired cutscene. The attached zip archive contains a WeiDU library with a function that largely automates the process. All you need is to provide the cutscene script and a way to execute the spell effect. This WeiDU example script for BGEE/BG2EE/EET adds a new ring ("myring.itm") to the game that can be used to trigger a cutscene without the use of helper creatures or global scripting: Spoiler BACKUP "weidu_external/backup/Cutscene-Example" AUTHOR "Argent77" BEGIN "Example: Cutscene triggered by spell effect" REQUIRE_PREDICATE (GAME_IS "bgee bg2ee eet") "BGEE, BG2EE or EET required." INCLUDE "%MOD_FOLDER%/lib/a7-cutscene_customization.tph" // Our cutscene script. // Trigger section can be empty if "CUT250" guard variable is the only condition. <<<<<<<< .../inlined/cutscene.baf IF THEN RESPONSE #100 CutSceneId(Player1) MoveViewObject(Myself,INSTANT) DisplayStringHead(Myself,~Cutscene triggered by a spell effect.~) Wait(4) EndCutSceneMode() END >>>>>>>> // Installs the cutscene for use with opcode 298 LAF EXTEND_CUT250 STR_VAR baf_file = ".../inlined/cutscene.baf" RET value // can be used later to set the required global variable END // Cutscene is triggered by an item ability (reusing Sandthief's Ring) COPY_EXISTING "ring05.itm" "override/myring.itm" SAY NAME2 "Cutscene Ring" SAY IDENTIFIED_DESC "Executes a cutscene when used." WRITE_SHORT 0x42 0 // remove Lore requirement // Discarding old effects LPF DELETE_SPELL_EFFECT INT_VAR opcode_to_delete = "-1" END // Setting required variable Global("CUT250","GLOBAL",%value%) LPF ADD_ITEM_EFFECT INT_VAR opcode = 265 // Modify global variable target = 1 // Self parameter1 = value // Variable is set to the result of the EXTEND_CUT250 function timing = 9 // Instant/Permanent STR_VAR resource = "CUT250" // Variable name END // Adding cutscene trigger LPF ADD_ITEM_EFFECT INT_VAR opcode = 298 // Pocket Plane target = 1 // Self timing = 1 // Instant/Permanent until death END Note: This feature can potentially interfere with the return location from the Pocket Plane if it is used while the party is present in the Pocket Plane. That's why I recommend to use it only for events where the party is not currently present in the Pocket Plane. Otherwise, this issue can be worked around using script actions StorePartyLocations() and RestorePartyLocations() in place of the ExitPocketPlane() action. a7-cutscene_customization-v1.zip Edited April 25, 2023 by argent77 Added compatibility note Quote Link to comment
subtledoctor Posted April 19, 2023 Share Posted April 19, 2023 Very interesting! I would recommend creating, or if it already exists appending to, a simple .2DA table that lists which values have already been used for the ("CUT250","GLOBAL") variable. In fact it would probably make sense to write a little function that either creates this .2DA file or finds the next unused value for the variable. That way any number of mods could do this and they would not get in each others' way. Quote Link to comment
argent77 Posted April 19, 2023 Author Share Posted April 19, 2023 Such a 2DA table would only serve as reference for modders though. The attached library already takes care of finding a free variable value for use with new cutscenes, so there shouldn't be any conflicts between different mods using this method. Quote Link to comment
marchitek Posted April 22, 2023 Share Posted April 22, 2023 On 4/18/2023 at 7:01 PM, argent77 said: CUT250A.BCS (hardcoded cutscene script executed by opcode 298): // Calls another cutscene script with activated trigger evaluation IF True() THEN RESPONSE #100 CutSceneId(Player1) StartCutSceneEx("CUT250B",TRUE) END StartCutSceneMode() is also included there right? I'm wondering if I can execute with this script without entering cutscene mode. Quote Link to comment
argent77 Posted April 22, 2023 Author Share Posted April 22, 2023 StartCutSceneMode() is automatically initiated by opcode 298. You could immediately call EndCutsceneMode() before executing more of your script, but you'll still notice the UI vanishing for a short moment. Quote Link to comment
marchitek Posted April 22, 2023 Share Posted April 22, 2023 2 hours ago, argent77 said: StartCutSceneMode() is automatically initiated by opcode 298. You could immediately call EndCutsceneMode() before executing more of your script, but you'll still notice the UI vanishing for a short moment. Got it. Thanks! Quote Link to comment
subtledoctor Posted April 22, 2023 Share Posted April 22, 2023 On 4/19/2023 at 4:22 AM, argent77 said: The attached library already takes care of finding a free variable value for use with new cutscenes, so there shouldn't be any conflicts between different mods using this method. Ah, I didn’t realize that was already included. Quote Link to comment
marchitek Posted April 25, 2023 Share Posted April 25, 2023 One more question from my side. Browsing IESDP I came up on ExitPocketPlane action. Is it somehow interfere with this solution? Quote Link to comment
argent77 Posted April 25, 2023 Author Share Posted April 25, 2023 1 hour ago, marchitek said: One more question from my side. Browsing IESDP I came up on ExitPocketPlane action. Is it somehow interfere with this solution? Yes, that can indeed interfere if a cutscene is triggered this way inside the Pocket Plane itself. I have added a note about it to the opening post. The issue can be worked around by using the StorePartyLocations()/RestorePartyLocations(), but that's not completely foolproof either. It's best to limit this feature to events that don't happen inside the Pocket Plane. Quote Link to comment
subtledoctor Posted October 17, 2023 Share Posted October 17, 2023 So, who is out there using this to recreate PS:T spells in BG2? Hmm? Quote Link to comment
Recommended Posts
Join the conversation
You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.