Cutscenes

Talk about Severance Blade of Darkness modifications and maps here. No tips or tech support questions please, use the forum above. Note that the game is rated 18 so some content may be unsuitable for younger readers.

Moderators: prospero, Ade

User avatar
prospero
Ancient Dragon
Posts: 1725
Joined: Wed Nov 21, 2001 1:42 am
Location: United Kingdom

Postby prospero » Sat Nov 20, 2010 11:45 pm

Hi Fynjy. [:)]

All the cutscenes in the main game are done by animating the camera in 3dsmax and exporting to files with the extension <b>.cam</b>.

But it's quite easy to use Python script to do them. You need to have a series of nodes. For each node you need two sets of coordinates - The camera position and the camera target position. In Python:

Code: Select all

cam.Position = 2000,1000,-4000 cam.TPos = 2000,1000,-8000
Then use this function to move the camera:

Code: Select all

def MoveCamera1(): x,y,z=cam.Position tx,ty,tz=cam.TPos x2,y2,z2= 3000, -6000, 8000 tx2,ty2,tz2=7000, -8000, 9000 AuxFuncs.MoveCamFromTo(x,y,z, x2,y2,z2, tx,ty,tz, tx2,ty2,tz2, 8.0, MoveCamera2)
When the function is called, the camera will move from it's present position and target to the second set in 8 seconds and when finished the function at the end (MoveCamera2) will be called. So you can chain as many moves as you like. The start coords of one function need to be the finish coords of the previous one.

There is also a module Abrecam.py which handles camera moves, but it can be limiting in certain cases.


That's the basics. [:D]

Sir Random
Dragon
Posts: 737
Joined: Thu Nov 15, 2001 12:58 am
Location: Ireland
Contact:

Postby Sir Random » Sun Nov 21, 2010 2:19 am

Hi Fynjy,

Any 'event' can be used as a 'trigger', but the commonest trigger is the EnterSector event, which calls a function (My_Cut_Scene) when the Player enters a certain sector (x,z,y):

darfuncs.EnterSecEvent(x, z, y, My_Cut_Scene)


You can move the Player (or an enemy) quite easily:

char=Bladex.GetEntity("Player1")
char.GoTo(x,z,y)

To make him run, insert:
char.GoToJogging=1


The best way to learn Blade scripting is to browse through the py files. DefFuncs.py contains the main functions for each map, so if you see something in the game that you want to copy, just check the .py files for that map to see how it was done.

User avatar
prospero
Ancient Dragon
Posts: 1725
Joined: Wed Nov 21, 2001 1:42 am
Location: United Kingdom

Postby prospero » Sun Nov 21, 2010 2:39 am

All sensible questions. [:)]

There is a file in every map called DefFuncs.py. This controls all the gameplay. All functions need to be in this file because it is executed when loading a saved game. The other files that create stuff are only executed on first load, otherwise you would keep getting more and more duplicate objects...

So any function, as a general rule should go in DefFuncs.py If you put them anywhere else they will only work in a 'live' game.

Ther are lots of built-in commands in the game to make things do things. To make a character move:

Code: Select all

per=Bladex.GetEntity("NameOfEntity") # assign the character to a variable per.GoToJogging = 1 # 1 for run, 0 for walk per.GoTo(2000,-1000,50000) #go to the defined position
There are lots of others...

import Actions
Actions.TurnToFaceEntity("NameOfEntity","NameOfAnotherEntity")

Actions.FreeBothhands("NameOfEntity") # sheathe weapons

I should mention that the GoTo command doesn't always work. The pathfinding facility in BOD is a bit unreliable. It depends on the map structure.

To get your timing right you can use a Scheduled Function...

Code: Select all

def DoStuff(): Bladex.AddScheduledFunc(Bladex.GetTime() + 2.8, DoSomething, ()) Bladex.AddScheduledFunc(Bladex.GetTime() + 7.5, DoSomethingElse, ())

This way you can time function calls from one master function.



btw. The only way to tilt the camera is to use 3dmax to animate it. I have done this and it's not easy. You need to export the map using

Code: Select all

Bladex.ExportWorld ("NameOfMap")
as a console command. This saves a file with ext

Code: Select all

.MBW
in the map folder. This is then imported into 3dmax and used as reference as a wireframe model to steer to camera around. You then export the animation to a <b>.cam</b> file

User avatar
prospero
Ancient Dragon
Posts: 1725
Joined: Wed Nov 21, 2001 1:42 am
Location: United Kingdom

Postby prospero » Mon Nov 22, 2010 5:37 pm

If you are running in D3D you need the window.dll which should go in the Bin/Raster folder. You can get it here....
http://www.dahlby.net/games/blade/


btw, here's a handy little function to save the current Player position to a .txt file:

Code: Select all

def WritePos(): char=Bladex.GetEntity("Player1") x=int(char.Position[0]) y=int(char.Position[1]) z=int(char.Position[2]) file = open("../../BODLoader/Mods/MyMapName/pos.txt","a") file.write("("+str(x)+","+str(y)+","+str(z)+")"+"\n") file.close() Bladex.AddInputAction("WritePos", 0) Bladex.AddBoundFunc("WritePos", WritePos) Bladex.AssocKey("WritePos", "Keyboard", "I", 1)
btw2. I tried to make a similar function to save the camerapos/targetpos. But for some reason, when in free camera mode it just saves where the camera was before you detached it. If anyone has the answer, it would speed up doing cutscenes a lot. Writing down all the coords is a PITA.[B)]

User avatar
prospero
Ancient Dragon
Posts: 1725
Joined: Wed Nov 21, 2001 1:42 am
Location: United Kingdom

Postby prospero » Mon Nov 22, 2010 10:52 pm

Welcome to BOD coding.[:D]

It does funny things now and then. The error in DefFuncs would have caused the rest of the files not to be read.

Sometimes when you paste in code you alter the indents. Doesn't matter how many spaces as long as they are all the same. Python users tend to favour 4 spaces, but I always use a tab.

btw. To get to the console input field you have to hover the cursor near the bottom until it turns to a double arrow and drag up to reveal a white area.

User avatar
prospero
Ancient Dragon
Posts: 1725
Joined: Wed Nov 21, 2001 1:42 am
Location: United Kingdom

Postby prospero » Tue Nov 23, 2010 1:34 am

Add

Code: Select all

import darfuncs

to the top of the file.[;)]


Press the windows key to enable the mouse and click on the BOD window to go back to the game.


If you change the file Lib/ConsoleOutput.py to look like this:


##################################################################

Code: Select all

import Console import sys DEBUG_FILE = 1 class ConsoleOutput: softspace=0 def write(self,message): if message is None: Console.ConsoleOutput("None") else: if DEBUG_FILE: dbg=open("Debug.txt","at") dbg.write (message) dbg.close() Console.ConsoleOutput(message) def flush(self): pass def InitConsole(): ConsoleOut=ConsoleOutput() sys.stderr=sys.stdout=ConsoleOut
###########################################################

....you will get a log of the saved console output in the Maps/WhateverMap folder called Debug.txt. Very useful as the console can be difficult to read when there is a lot going on.

Sir Random
Dragon
Posts: 737
Joined: Thu Nov 15, 2001 12:58 am
Location: Ireland
Contact:

Postby Sir Random » Tue Nov 23, 2010 4:11 am

If you have the console working, then most script errors will appear there so you can easily see where the mistake is in your code. If no errors appear, then you need to see if the function is being triggered.

To test your function, you could temporarily adapt Prospero's key code:

Bladex.AddInputAction("WritePos", 0)
Bladex.AddBoundFunc("WritePos", <font color="green">TheCutScene</font id="green">)
Bladex.AssocKey("WritePos", "Keyboard", "I", 1)

Then go to your start position and press I

User avatar
prospero
Ancient Dragon
Posts: 1725
Joined: Wed Nov 21, 2001 1:42 am
Location: United Kingdom

Postby prospero » Tue Nov 23, 2010 4:34 am

Another thing you can use are print statements,


print "Yaaaaay! It works!!!!"

Insert them at various points in your code and if they appear in the console you know all the code before is OK.

You can use try/except routines to catch errors without crashing the game...

Code: Select all

def SlightlyIffyFunction(): print "Calling doubtful code" try: per=Bladex.GetEntity("SomethingOrOther) except: print "This code is crap"

If the code in the try clause is OK, it will be executed. If there is anything wrong the code in the except clause is executed.


* There is a mistake in the code. Can you spot it? [:)]

User avatar
prospero
Ancient Dragon
Posts: 1725
Joined: Wed Nov 21, 2001 1:42 am
Location: United Kingdom

Postby prospero » Tue Nov 23, 2010 4:44 am

Sorry,,, missed your last post.

Rather than use the EnterSectorEvent you can do triggers like this:

# in any .py file except DefFuncs....

Code: Select all

sectstep1=Bladex.GetSector(28000, -1000.0, -50000) sectstep1.OnEnter=DoSomething # in DefFuncs... def DoSomething(sector, entity): if entity != "Player1": # so only the Player will trigger it. return # terminate function if not the Player ----- code here ------ sectstep1.OnEnter=None # cancel trigger or can be re-assigned to another function.

User avatar
prospero
Ancient Dragon
Posts: 1725
Joined: Wed Nov 21, 2001 1:42 am
Location: United Kingdom

Postby prospero » Thu Nov 25, 2010 12:23 am

To do an animation that is not in the character's animation set:

Code: Select all

per.Wuea=Reference.WUEA_ENDED per.LaunchAnimation("Tkn_alarm02")
When applied for the first time you can get a slight jolt as the game has to load the animation. To preload the animation you have to use a DefAnims.py file which is executed automatically as the map starts. Ther eis usually one in every map so you can check out the code.


or to do a generic:

Code: Select all

per.LaunchAnmType("hurt_f_big")
All 'human' types share the same mesh structure with 25 nodes. The 'monster' types don't and will crash the game if you try to apply the animations. Also the Prisoners have a different node number.

Sir Random
Dragon
Posts: 737
Joined: Thu Nov 15, 2001 12:58 am
Location: Ireland
Contact:

Postby Sir Random » Sun Jul 24, 2011 4:28 pm

1) If it's just for a cutscene, then I would use an actor instead of an enemy class. Actors do what they're told (usually) [:)]

dum=Bladex.CreateEntity("Actor1","Knight_Traitor", x,y,z)
dum.Orientation=1,1,0,0
dum.Static=1

dum.Actor=1
dum.Animation="Tkn_sleep_wall"
dum.TurnOn()


2) Are you using this line?

pers.Wuea=Reference.WUEA_ENDED

before launching the second animation?

What SetTmpAnmFlags() are you using for the Sleep anim?
The First parm should be "0" to make the animation interruptable:
SetTmpAnmFlags(<font color="red">0</font id="red">,0,1,0,1,1)


You can change an Actors animation at any time, but it can look jerky if the anims are out of sync.

User avatar
prospero
Ancient Dragon
Posts: 1725
Joined: Wed Nov 21, 2001 1:42 am
Location: United Kingdom

Postby prospero » Sun Jul 24, 2011 6:15 pm

If the animation isn't in the particular race animation set, you should really pre-load it using this code:

Code: Select all

Bladex.LoadSampledAnimation("..\\..\\Anm\\NameOfBMVFile.BMV","NameOfAnimation",1) Bladex.AddBipedAction("Knight_Traitor","WhateverNameYouWant","NameOfAnimation",0.0,1.0,0)
If the animation has a race prefix ("Tkn" in this case)that is different to the race you are using it for, you need to add the race name on as an extra argument at the end:

Bladex.LoadSampledAnimation("..\\..\\Anm\\NameOfBMVFile.BMV","NameOfAnimation",1,"Knight_Traitor")

You need to put this code somewhere where it will be executed in both a live and saved game. DefFuncs.py should work.

The interesting bit: The arguement ,1) at the end of the code decides whether the animation loops or not. (,0) for not).

Start the animation with:

per.Wuea=Reference.WUEA_ENDED
per.LaunchAnmType("WhateverNameYouWant")


With a bit of luck that might work.[:)]


Return to “Severance BoD: Modding Community”

Who is online

Users browsing this forum: No registered users and 2 guests