Adding characters and basic code
Adding characters and basic code
Part 8 This is a long one
scene.ini Scene.ma tutorial.dat
Are up to this point with some extras like 2 of the walls stopped working for some reason so they were replaced
And a few duped items removed that were not meant to be there
Usually id make sure the scene is lighted a bit better and that all the walls were aligned but i wont for this tutorial feel free to do that yourself if you want
Part 8 what to do
we have our scene
we have lights
we have shadows
we have a background
we have collisions
we have doors
I know lets add in Saiko so she can see our scene i mean her house
Open our scene.ma up either the current one you have copied from this folder or your own
Each object and npc we add needs to know where to be placed we use waypoints to tell them where to spawn
Objects that are placed with a waypoint above the ground will fall down but npc's wont they will stand on that "hight level" and all their actions will be at this level
Things will spawn where the waypoint is facing but since its a cube that’s a little hard to know which face is the main one
Make a new Lambert texture and call is "waypointplayerface"
And texture the face where you spawn from ingame Go check if you need to In my scene its the side facing the apartment
Now that we have that make another Lambert and call it "WaypointNpcFace"
And texture the opposite side
Now we always know where they will face and we don’t have to test until we find it
Now we make Saiko's spawnpoint
Select the waypoint we have in the scene and go to
edit > duplicate special's little box
Make sure instance and parent are selected then click duplicate special
Do i have to do this every time
Yes otherwise it wont work
Well you can do Ctrl+Shift+D but we need to make sure its on those 2 settings first
next part is the names
The first box is what you want to call your waypoint and the 2nd box must be "waypointShape"
So rename the first box to "SaikoSpawn"
Notice how the 2nd box changes to SaikoSpawnShape instead of waypointShape
Just change it back to "waypointShape"
If doing multiple waypoints change it back last since its an instance changing any will change all back but their first box is unique to each box
Remember first box is what you want it to be and 2nd must be "waypointShape"
Now take our annoying little cube called SaikoSpawn and place it somewhere in the apartment facing the direction you want then save the scene
Next part is to tell her where to spawn
pack_tutorial\init\stories\tutorial\chars\saiko
And open her init.dat Change the scene_id and waypoint to below or whatever you called them
scene_id = TUTORIAL1; waypoint = "SaikoSpawn";
We will cover the rest in a little while
After that is done save the init.dat and run the filemaker
Then go say hello to Saiko
But she is currently deaf and blind so she wont respond and she does not have any code to do anything anyway aaand you cant touch her either but she is there
Now is a little while so lets cover the basics in Saiko's init file
There is too much to write here so open the initexplained.dat in the folder if you want to have a look
Phew can i have a nap now
No?
Ok lets continue
We will add in the 2 doorbells well 4 but only 2 will do anything other then ring
Make a small rectangle box in the scene and place it on the wall next to the door and use whatever material you want i chose the shiny door handles one
Then rename the object to Doorbell and copy it to the other doors
So we should have 4 doorbells
Next open the scene.ini
and add in
rb "DoorbellShape" { render {} // Door is rendered physics { } media { elem[0] { filename = "scenes/sounds/doorbell/doorbell1.wav"; type = AUDIO; stream = false; pos3d = true; pos3d_min = 1.0; start = false; loop = false; volume = 1.0; } } interact {} // Can open door by hand }
I added this above the doors
Add in 3 more and rename them correctly
Now we should have 4 doorbell rb's
Next open the tutorial.dat in the pack_tutorial\init\stories\tutorial\scenes
And add in
button_objecti DOORBELL1 { obj_name = "Doorbell"; }
Again i did this above the doors
Make 3 more and rename them correctly
Save everything and run the filemaker then go check out your doorbells
Remember when i said rename them correctly i didn’t and got errors...
Ding ding, Ding ding
Bells work
Ok lets make them do something
pack_tutorial\init\stories\tutorial\chars\saiko\brain\code\ref Then open up base_ref.dat
The difference between the 3 refs is
base ref is global commands like the door bell and the player passing events?
While run0_ref is stuff like player talking things that directly effect the npc?
The basic_ref i have no idea never used it
So in the base_ref add in under the //---
TUTORIAL1:DOORBELL1.hit = { talk.s = "hello"; }
TUTORIAL1:DOORBELL1.hit //<--- The name of the scene and its unique name then the action of hitting it talk.s = "hello"; //<--- Saiko will say anything you put between the ""
Save and go see what she says
Ding ding hello, Ding ding hello
Now that works lets do something a bit more useful with it
Let's add in Monica and get her out of the way
So in the Maya scene special dupe the waypoint Ctrl+Shift+D
Rename it to “MonicaSpawn” and then rename the 2nd box to “waypointShape” and position it behind Monica's door and rotate it correctly so it looks like she is opening the door
Next we need to add Monica into the scene
pack_tutorial\init\stories\tutorial\chars\monica init.dat Change these to match
cloth_type = CASUAL; scene_id = TUTORIAL1; waypoint = "MonicaSpawn";
And remove
pose_type = JOG pose_id = 0;
So she will go back to standing
Now save everything and run the filemaker then go see Monica ingame
Now lets incorporate the door bell into the scene
Open the tutorial.dat where the doors are located
And change Monica's door to be
door_objecti DOOR2 { q = 32; q_min = 0; q_max = 32; q_spring = 1; open = false; obj_name = "MonicaDoor"; }
The q min and max depends on the rotation of the door but if the handle is on the right then its max 32
So we have a locked door we need to make the doorbell tell Monica that someone is here
We need to open Monica's base_ref pack_tutorial\init\stories\tutorial\chars\monica\brain\code\ref And add in
TUTORIAL1:DOORBELL2.hit = { [state.dyn.me.do.state2 == NONE] { state.dyn.me.do.state2 = START; } }
This will tell Monica to do [START] inside her run when the doorbell is pressed but only once
Then open pack_tutorial\init\stories\tutorial\chars\monica\brain\code\run run0_state.dat
This is where we will make Monica do stuff
If you have some understanding of coding this will be easy if not this will be harder so i will add images to help also you can check out a later file to see it compleated
We now need to add our [START]
case (state.dyn.me.do.state2) { [NONE] { } [START] { talk.s = "coming"; do_set_timer(6); state.dyn.me.do.state2 = WALK_TO_DOOR; state.dyn.me.do.offended = WAITFOROFF; } }
case (state.dyn.me.do.state2) //<---- You can have multipul cases all working together [NONE] //<---- Innercase i guess i don’t really know what they would be called but NONE is the default { } [START] //<----- When we say state.dyn.me.do.state2 = START we are saying do this { talk.s = "coming";//<----- Whatever you want Monica to say when we press the doorbell do_set_timer(6); //<---- Wait for 6 seconds state.dyn.me.do.state2 = WALK_TO_DOOR; //<--- Go to the next innercase state.dyn.me.do.offended = WAITFOROFF; //<---- This one will be added a bit later but its incase we offend monica }
Next part is to get the door to open on its own as if monica opened it
[WALK_TO_DOOR] { loc.ts = GetTs(); [loc.ts < state.dyn.me.do.ts] return; // Open door loc.so.obj = TUTORIAL1:DOOR2; loc.so.par = DOOR_SET_STATUS; loc.so.val = DOOR_SETVAL_STATUS_OPEN; SetObject(loc.so); // Let door be open from now on loc.so.status = loc.so.val; SetObjState(loc.so); // Can see,hear from now on loc.state.can_see = true; loc.state.can_hear = true; SetCharState(loc.state); SetCanSee(true); SetCanHear(true); // I am in alerted state set_main_focus(STARE); do_set_timer(3); state.dyn.me.do.state2 = OPENING_DOOR; }
[WALK_TO_DOOR] { loc.ts = GetTs(); //<--- [loc.ts < state.dyn.me.do.ts] return; //<--- This section says wait for timer to finish and must be added for the timer to work // Open door loc.so.obj = TUTORIAL1:DOOR2; //<--- Our scene name then the door name loc.so.par = DOOR_SET_STATUS; //<-- What we are setting loc.so.val = DOOR_SETVAL_STATUS_OPEN; //<--- Saying we want the door to be open insted of closed SetObject(loc.so); //<--- Setting the above // Let door be open from now on loc.so.status = loc.so.val; SetObjState(loc.so); // Can see,hear from now on loc.state.can_see = true; loc.state.can_hear = true; SetCharState(loc.state); SetCanSee(true); SetCanHear(true); // I am in alerted state set_main_focus(STARE); //<--- Stare at the player do_set_timer(3); state.dyn.me.do.state2 = OPENING_DOOR; }
And then add
[OPENING_DOOR] { // Wait for door to open loc.ts = GetTs(); [loc.ts < state.dyn.me.do.ts] return; // If main not in view [!state.dyn.me.avatar.in_view] return; // Say hello talk.s = "Hello, can I help you?"; talk.delay = 500; do_set_timer(3); state.dyn.me.do.state2 = STANDING_IN_DOOR; }
[OPENING_DOOR] { // Wait for door to open loc.ts = GetTs(); [loc.ts < state.dyn.me.do.ts] return; // If main not in view [!state.dyn.me.avatar.in_view] return; //<--- If the player is not in sight then keep trying until they are // Say hello talk.s = "Hello, can I help you?"; talk.delay = 500; //<--- Wait half a second before talking do_set_timer(3); state.dyn.me.do.state2 = STANDING_IN_DOOR; }
Now we will add in the code for when Monica is offended getting Monica offended is easy just say something rude or whip something out
[OFFENDED] { loc.ts = GetTs(); [loc.ts < state.dyn.me.do.ts] return; // Slam Door loc.so.obj = TUTORIAL1:DOOR2; loc.so.par = DOOR_SET_Q; loc.so.val = 0; SetObject(loc.so); loc.so.par = DOOR_SET_QMIN; loc.so.val = 0; SetObject(loc.so); loc.so.par = DOOR_SET_QMAX; loc.so.val = 0; SetObject(loc.so); loc.so.par = DOOR_SET_QSPRING; loc.so.val = 1; SetObject(loc.so); // Let door be closed from now on loc.so.door_state_q = 0; loc.so.door_state_qmin = 0; loc.so.door_state_qmax = 0; loc.so.door_state_qspring = 1.33; SetObjState(loc.so); // Cannot see,hear from now on loc.state.scene_id = NONE; loc.state.can_see = false; loc.state.can_hear = false; SetCharState(loc.state); SetCanSee(false); SetCanHear(false); state.dyn.me.do.state2 = END; }
[OFFENDED] //<------ This is what we will use when monica gets offended { loc.ts = GetTs(); [loc.ts < state.dyn.me.do.ts] return; // Slam Door loc.so.obj = TUTORIAL1:DOOR2; loc.so.par = DOOR_SET_Q; //<--- Set the q to 0 so closed loc.so.val = 0; SetObject(loc.so); loc.so.par = DOOR_SET_QMIN; loc.so.val = 0; //<------ Set the min and max to 0 so it wont open SetObject(loc.so); loc.so.par = DOOR_SET_QMAX; loc.so.val = 0; SetObject(loc.so); loc.so.par = DOOR_SET_QSPRING; loc.so.val = 1; //<------- Set the spring to 1 so the door slams closed SetObject(loc.so); // Let door be closed from now on loc.so.door_state_q = 0; loc.so.door_state_qmin = 0; loc.so.door_state_qmax = 0; loc.so.door_state_qspring = 1.33; SetObjState(loc.so); // Cannot see,hear from now on loc.state.scene_id = NONE; //<---- Make monica stop seeing and listening loc.state.can_see = false; loc.state.can_hear = false; SetCharState(loc.state); SetCanSee(false); SetCanHear(false); state.dyn.me.do.state2 = END; //<---- We need to pass this to an empty innercase otherwise it can just infinity repeat the above }
Now after the closing bracket for the case but before the end of the state </run0_state>
add in
case (state.dyn.me.do.offended) { [WAITFOROFF] { [grel.offended != NONE] { do_set_timer(1); state.dyn.me.do.state2 = OFFENDED; state.dyn.me.do.offended = OFFENDED; } return; } }
case (state.dyn.me.do.offended)//<--- A new case that will work while the other one is going { [WAITFOROFF] { // talk.s = "waiting for offended"; //<--- This i added for debuging purposes to see if it was actually working [grel.offended != NONE] //<--- Is Monica offended if so do what is below { do_set_timer(1); state.dyn.me.do.state2 = OFFENDED; //<--- Go to the offended state above and slam the door state.dyn.me.do.offended = OFFENDED; //return; } return; } }
Save everything and go press Monica's doorbell then offend her
You don’t need to run the filemaker unless you have made changes to either the scene.ma or the scene.ini
Now that she can slam the door in your face lets get her to help you
Next thing we need to do is play with the NPL and its words
Now i don’t fully understand how to use the NPL so it is slow and painful for me and this is why my stories have limited player responses if there is a better way to do this i would like someone to let me know
Anyway go ingame and press Monica's doorbell then say something like
"im looking for saiko"
"hi im looking for saiko"
"i have a pizza for saiko"
then exit the game (F3)
Open the trace.txt in the XStoryPlayer3 folder
Look for CTALK this is what the player has just said
then the brain translates it
So if we say
CTALK: "im looking for saiko"
we get the following reactions
21:24:58 BRAIN: "state.code.ref.state.RUN0.look.word"
21:24:58 BRAIN: "state.code.ref.state.RUN0.look.if"
21:24:58 BRAIN: "state.code.ref.state.RUN0.look.get"
21:24:58 BRAIN: "state.code.ref.state.RUN0.activity.word"
21:24:58 BRAIN: "state.code.ref.state.RUN0.activity.if"
21:24:58 BRAIN: "state.code.ref.state.RUN0.activity.get"
21:24:58 BRAIN: "state.code.ref.state.RUN0.word.get"
21:24:58 BRAIN: "state.code.ref.basic.look.word"
21:24:58 BRAIN: "state.code.ref.basic.look.if"
21:24:58 BRAIN: "state.code.ref.basic.look.get"
21:24:58 BRAIN: "state.code.ref.basic.activity.word"
21:24:58 BRAIN: "state.code.ref.basic.activity.if"
21:24:58 BRAIN: "state.code.ref.basic.activity.get"
21:24:58 BRAIN: "state.code.ref.basic.word.get"
We have looking as an activity
And if we say
CTALK: "hi im looking for saiko"
We get
21:25:03 BRAIN: "state.code.ref.state.RUN0.hello.greet"
21:25:03 BRAIN: "state.code.ref.state.RUN0.hello.if"
21:25:03 BRAIN: "state.code.ref.state.RUN0.hello.get"
21:25:03 BRAIN: "state.code.ref.state.RUN0.value.greet"
21:25:03 BRAIN: "state.code.ref.state.RUN0.value.if"
21:25:03 BRAIN: "state.code.ref.state.RUN0.value.get"
21:25:03 BRAIN: "state.code.ref.state.RUN0.greet.get"
21:25:03 BRAIN: "state.code.ref.basic.hello.greet"
21:25:03 BRAIN: "state.code.ref.basic.hello.if"
21:25:03 BRAIN: "state.code.ref.basic.hello.get"
21:25:03 BRAIN: "state.code.ref.basic.value.greet"
21:25:03 BRAIN: "state.code.ref.basic.value.if"
21:25:03 BRAIN: "state.code.ref.basic.value.get"
21:25:03 BRAIN: "state.code.ref.basic.greet.get"
Where hi is the main word referenced as a greeting
CTALK: "i have a pizza for saiko"
21:25:09 BRAIN: "state.code.ref.state.RUN0.saiko.name.me.info"
21:25:09 BRAIN: "state.code.ref.state.RUN0.saiko.name.me.if"
21:25:09 BRAIN: "state.code.ref.state.RUN0.saiko.name.me.get"
21:25:09 BRAIN: "state.code.ref.state.RUN0.saiko.name.me.info"
21:25:09 BRAIN: "state.code.ref.state.RUN0.saiko.name.me.if"
21:25:09 BRAIN: "state.code.ref.state.RUN0.saiko.name.me.get"
21:25:09 BRAIN: "state.code.ref.state.RUN0.value.name.me.info"
21:25:09 BRAIN: "state.code.ref.state.RUN0.value.name.me.if"
21:25:09 BRAIN: "state.code.ref.state.RUN0.value.name.me.get"
21:25:09 BRAIN: "state.code.ref.state.RUN0.value.attr.me.info"
21:25:09 BRAIN: "state.code.ref.state.RUN0.value.attr.me.if"
21:25:09 BRAIN: "state.code.ref.state.RUN0.value.attr.me.get"
In this one we get Saiko's name referenced as a name
This is the annoying part each sentence we gave Monica has Saiko's name in it but only one sentence uses it
"im looking for saiko"
"hi im looking for saiko"
"i have a pizza for saiko"
We can add more then one at a time tho
saiko.name.me.get = { } basic.hello.get = saiko.name.me.get; basic.activity.get = saiko.name.me.get;
So each one will be directed to Saiko's name
The problem with this is if i was to just say
"hi im looking for saiko"
It would be the same as if i said
21:48:32 CTALK: "hello i like licking windows"
21:48:34 BRAIN: "state.code.ref.basic.hello.get"
So the response would be the same
Open Monica's run0_ref
pack_tutorial\init\stories\tutorial\chars\monica\brain\code\ref
And add in
saiko.name.me.get = { talk.s = "she lives across the hall"; talk.dur = 3000; talk.rem.s = "Bye"; talk.rem.dur = 1000; do_set_timer(6); state.dyn.me.do.state2 = OFFENDED; state.dyn.me.do.offended = OFFENDED; } basic.hello.get = saiko.name.me.get; basic.activity.get = saiko.name.me.get; saiko.word = saiko.name.me.get;
This will make Monica say she lives across the hall
then bye and she will go to her offended state which is just slamming the door if we had added other dialogue then we would have to make another like [CLOSEDDOOR] and closed the door that way
But what happens if the player does not talk to Monica and then presses Saiko's doorbell or presses Saiko's doorbell first
Well add this into Monica's base_ref.dat
TUTORIAL1:DOORBELL1.hit = { [state.dyn.me.do.state2 != NONE] { talk.s = "fine then"; do_set_timer(6); state.dyn.me.do.state2 = OFFENDED; state.dyn.me.do.offended = OFFENDED; } [state.dyn.me.do.state2 == NONE] { state.dyn.me.do.state2 = OFFENDED; state.dyn.me.do.offended = OFFENDED; } }
This will make it if you press Saiko's doorbell while Monica is standing there she will say fine then and close the door
Also if you press Saiko's doorbell first Monica will never answer her door
This will end part 8
In the next part there will be all the files needed
Next we will code Saiko since Monica is all done for now
Part 9 did not think you would make it