Difference between revisions of "Tutorial for code structure"
(Created page with "'''Eskarn's tutorial for code structure''' This is an introduction on how to code in XStoryPlayer The coding language is based off C++ I strongly recommend using Notepad ++...") |
|||
(2 intermediate revisions by the same user not shown) | |||
Line 7: | Line 7: | ||
I am in no way a master of this stuff but the tutorial should help | I am in no way a master of this stuff but the tutorial should help | ||
+ | |||
+ | |||
+ | |||
+ | [https://www.dropbox.com/s/qdxv5xjxxke8ca4/Tutorial%20for%20code%20structure.pdf?dl=0 PDF VERSION] | ||
+ | PDF versions do not get updated as regularly | ||
Line 242: | Line 247: | ||
These say that the current line has ended | These say that the current line has ended | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | state.dyn.me.do.changingcases = NEXT;</syntaxhighlight> | + | state.dyn.me.do.changingcases = NEXT; |
+ | </syntaxhighlight> | ||
And thats it do this | And thats it do this | ||
Without the ; | Without the ; | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | state.dyn.me.do.changingcases = NEXT</syntaxhighlight> | + | state.dyn.me.do.changingcases = NEXT |
+ | </syntaxhighlight> | ||
This line never ends and will result in an error | This line never ends and will result in an error | ||
Line 291: | Line 298: | ||
You can add in custom timers but i will not cover this because most people wont need them | You can add in custom timers but i will not cover this because most people wont need them | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | loc.ts = GetTs(); loc.</syntaxhighlight> | + | loc.ts = GetTs(); loc. |
+ | </syntaxhighlight> | ||
+ | stands for local which means this is only stored inside this innercase | ||
− | So <syntaxhighlight lang="cpp">loc.ts</syntaxhighlight> | + | So |
+ | <syntaxhighlight lang="cpp"> | ||
+ | loc.ts | ||
+ | </syntaxhighlight> | ||
+ | is a varaible we are setting it could be <syntaxhighlight lang="cpp">loc.howyagoingm8</syntaxhighlight> but ts is eaiser because we know what it means timeset or something like that | ||
− | <syntaxhighlight lang="cpp">GetTs();</syntaxhighlight> | + | <syntaxhighlight lang="cpp"> |
+ | GetTs(); | ||
+ | </syntaxhighlight> | ||
+ | is a function in another file somewhere that gets the game time | ||
− | So we are saying that <syntaxhighlight lang="cpp">loc.ts</syntaxhighlight> | + | So we are saying that |
+ | <syntaxhighlight lang="cpp"> | ||
+ | loc.ts | ||
+ | </syntaxhighlight> | ||
+ | is whatever the current gametime is | ||
this next part is a condition | this next part is a condition | ||
− | if <syntaxhighlight lang="cpp">loc.ts</syntaxhighlight> | + | if |
− | <syntaxhighlight lang="cpp">[loc.ts < state.dyn.me.do.ts] return;</syntaxhighlight> | + | <syntaxhighlight lang="cpp"> |
+ | loc.ts | ||
+ | </syntaxhighlight> | ||
+ | is less then the current time then go back up the top | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | [loc.ts < state.dyn.me.do.ts] return; | ||
+ | </syntaxhighlight> | ||
− | The inner case will stay the same but it will reset and run the <syntaxhighlight lang="cpp">loc.ts</syntaxhighlight> | + | The inner case will stay the same but it will reset and run the |
+ | <syntaxhighlight lang="cpp"> | ||
+ | loc.ts | ||
+ | </syntaxhighlight> | ||
+ | again and the time will update until | ||
− | <syntaxhighlight lang="cpp">loc.ts</syntaxhighlight> | + | <syntaxhighlight lang="cpp"> |
− | <syntaxhighlight lang="cpp">[loc.ts < state.dyn.me.do.ts] return;</syntaxhighlight> | + | loc.ts |
+ | </syntaxhighlight> | ||
+ | is greater then the time then it will no longer return back to the start | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | [loc.ts < state.dyn.me.do.ts] return; | ||
+ | </syntaxhighlight> | ||
Then it will run the code under it which in our case is | Then it will run the code under it which in our case is | ||
− | + | <syntaxhighlight lang="cpp"> | |
− | + | state.dyn.me.do.timersarefun = START2; | |
− | + | </syntaxhighlight> | |
− | + | and that will move it to the next innercase | |
− | + | ||
− | + | theres 2 main timers | |
+ | <syntaxhighlight lang="cpp"> | ||
+ | do_set_timer(6); | ||
+ | do_set_timer2(6); | ||
[loc.ts < state.dyn.me.do.ts] return; | [loc.ts < state.dyn.me.do.ts] return; | ||
− | [loc.ts < state.dyn.me.do.ts2] return;</syntaxhighlight> | + | [loc.ts < state.dyn.me.do.ts2] return; |
+ | </syntaxhighlight> | ||
These timers dont work well with other timers but very raly will 2 timers be needed | These timers dont work well with other timers but very raly will 2 timers be needed | ||
Now this is a bit more advanced but ill add it anyway | Now this is a bit more advanced but ill add it anyway | ||
I found this works well if you need multiple timers running at the same time | I found this works well if you need multiple timers running at the same time | ||
− | <syntaxhighlight lang="cpp">[loc.ts >= state.dyn.me.do.ts] | + | <syntaxhighlight lang="cpp"> |
+ | [loc.ts >= state.dyn.me.do.ts] | ||
{ | { | ||
Line 338: | Line 378: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Then we can do some more | Then we can do some more | ||
− | <syntaxhighlight lang="cpp">[loc.ts == state.dyn.me.do.ts & state.dyn.me.do.timersarefun == START2 ]</syntaxhighlight> | + | <syntaxhighlight lang="cpp"> |
+ | [loc.ts == state.dyn.me.do.ts & state.dyn.me.do.timersarefun == START2 ] | ||
+ | </syntaxhighlight> | ||
if loc.ts is equal to ts and timersarefun is equal to START2 | if loc.ts is equal to ts and timersarefun is equal to START2 | ||
− | <syntaxhighlight lang="cpp">[loc.ts == state.dyn.me.do.ts | state.dyn.me.do.timersarefun == START2 ]</syntaxhighlight> | + | <syntaxhighlight lang="cpp"> |
+ | [loc.ts == state.dyn.me.do.ts | state.dyn.me.do.timersarefun == START2 ] | ||
+ | </syntaxhighlight> | ||
if loc.ts is equal to ts or timersarefun is equal to START2 | if loc.ts is equal to ts or timersarefun is equal to START2 | ||
But wait theres even more | But wait theres even more | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | state.dyn.me.do.playwithvalues = 1;</syntaxhighlight> | + | state.dyn.me.do.playwithvalues = 1; |
+ | </syntaxhighlight> | ||
This sets playwithvalues to whatever is set | This sets playwithvalues to whatever is set | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | state.dyn.me.do.playwithvalues += 1;</syntaxhighlight> | + | state.dyn.me.do.playwithvalues += 1; |
+ | </syntaxhighlight> | ||
This adds a the value to the exsisting varaible | This adds a the value to the exsisting varaible | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | state.dyn.me.do.playwithvalues -= 1;</syntaxhighlight> | + | state.dyn.me.do.playwithvalues -= 1; |
+ | </syntaxhighlight> | ||
This subtracts the value to the exsisting varaible | This subtracts the value to the exsisting varaible | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | state.dyn.me.do.playwithvalues *= 1;</syntaxhighlight> | + | state.dyn.me.do.playwithvalues *= 1; |
+ | </syntaxhighlight> | ||
This multiplys the value of the exsisting variable by whatever is set | This multiplys the value of the exsisting variable by whatever is set | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | state.dyn.me.do.playwithvalues /= 1;</syntaxhighlight> | + | state.dyn.me.do.playwithvalues /= 1; |
+ | </syntaxhighlight> | ||
This divides the value of the exsisting variable by whatever is set | This divides the value of the exsisting variable by whatever is set | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | state.dyn.me.do.playwithvalues ^= state.dyn.me.do.valuedoesnotexsist;</syntaxhighlight> | + | state.dyn.me.do.playwithvalues ^= state.dyn.me.do.valuedoesnotexsist; |
+ | </syntaxhighlight> | ||
This ones a little bit diffrent it sets a value even if it does not exsist | This ones a little bit diffrent it sets a value even if it does not exsist | ||
− | We can even do things like this<syntaxhighlight lang="cpp"> | + | We can even do things like this |
+ | <syntaxhighlight lang="cpp"> | ||
state.dyn.me.do.playwithvalues = state.dyn.me.do.somevalue; | state.dyn.me.do.playwithvalues = state.dyn.me.do.somevalue; | ||
− | state.dyn.me.do.playwithvalues += state.dyn.me.do.somevalue;</syntaxhighlight> | + | state.dyn.me.do.playwithvalues += state.dyn.me.do.somevalue; |
+ | </syntaxhighlight> | ||
Ok lets move on to getting them to talk | Ok lets move on to getting them to talk | ||
This is the basic talk function | This is the basic talk function | ||
− | <syntaxhighlight lang="cpp">talk.s = "hello";</syntaxhighlight> | + | <syntaxhighlight lang="cpp"> |
+ | talk.s = "hello"; | ||
+ | </syntaxhighlight> | ||
There are ways we can control this | There are ways we can control this | ||
Line 378: | Line 432: | ||
talk.dur = 6000;//Time in milliseconds 1000 milliseconds is 1 second | talk.dur = 6000;//Time in milliseconds 1000 milliseconds is 1 second | ||
talk.delay = 4000; | talk.delay = 4000; | ||
− | + | </syntaxhighlight> | |
We can even use a case to control what is said | We can even use a case to control what is said | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | Rnd(3);</syntaxhighlight> | + | Rnd(3); |
+ | </syntaxhighlight> | ||
+ | This is a function to randomly select a value between the set number | ||
0 is included so its 0 1 2 but (3) | 0 is included so its 0 1 2 but (3) | ||
− | + | <syntaxhighlight lang="cpp"> | |
loc.rnd = Rnd(3); | loc.rnd = Rnd(3); | ||
case (loc.rnd) | case (loc.rnd) | ||
Line 402: | Line 458: | ||
It adds 1 to the count variable and adds a 5 second timer and goes back up the top and will do this until we change the state which will happen when the count reaches 4 then the condition will be met and it will move to the next innercase | It adds 1 to the count variable and adds a 5 second timer and goes back up the top and will do this until we change the state which will happen when the count reaches 4 then the condition will be met and it will move to the next innercase | ||
− | + | <syntaxhighlight lang="cpp"> | |
[START] | [START] | ||
{ | { | ||
Line 442: | Line 498: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Thats it for now the rest you will have to figure out on your own my | + | Thats it for now the rest you will have to figure out on your own my suggestion is to open every game file you can and see how things are done |
− | All i had was the tutorials that XPA did and the rest iv | + | All i had was the tutorials that XPA did and the rest iv learned by either tinkering around or asking |
− | If you need help feel free to ask on the forums but try to figure it out first you | + | If you need help feel free to ask on the forums but try to figure it out first you don't learn by people doing it for you |
Latest revision as of 03:14, 13 January 2016
Eskarn's tutorial for code structure
This is an introduction on how to code in XStoryPlayer The coding language is based off C++
I strongly recommend using Notepad ++ its awesome
I am in no way a master of this stuff but the tutorial should help
PDF VERSION PDF versions do not get updated as regularly
There will be no pictures and I'm not going to focus on story's but rather the code involved
Where to start
Each character in the game has a run.dat
<*state_run> res = true; case (state.dyn.me.do.state) { [RUN0] run0_state(); [RUN1] run1_state(); [RUN2] run2_state(); [RUN3] run3_state(); [RUN4] run4_state(); } </state_run>
This file keeps running the set state in this case it will be [RUN0] until changed and that will happen when the story progresses
If it did not keep running the function we would not be able to do things like timers and the whole game would just stop well the characters atleast
So we are currently running run0_state which is in another file
run0_state.dat
<run0_state> <- opening code goes in here </run0_state> <- closing
i think these would be called functions im not to sure but im gonna call em functions
Everything between the opening function line and the closing function line will run when we tell it to
Now we move onto cases
Cases go in functions and give us more control
Cases can be called whatever you want past the do and every case needs an opening bracket and a closing bracket { }
This tells the engine that the case is between the brackets Without a opening bracket the case would never have anything in it Without a closing bracket the case would never end
Both ending in errors
case (state.dyn.me.do.whateveryouwanttocallit) { <- opening bracket } <- closing bracket
So we have a case what now
Now we can add in i really dont know what to call em but im gonna go with innercase
case (state.dyn.me.do.whateveryouwanttocallit) { <- opening bracket [NONE] { <- opening bracket } <- closing bracket } <- closing bracket
Now we still need an opening bracket and a closing bracket { } to tell the innercase what belongs in it
This is where having a organised system to your code helps This examples a little bit pointless because there's only 2 opening brackets and 2 closing brackets
But when you have 50 opeing and 49 closing brackets its really hard to find the missing one
This is my system and it works for me and this code ill explain that a bit later
Here is an example of non orgnised code It's chaos but again its a small scale example some of my dunegon files are 4k lines
But as you can see its hard to tell where the brackets are and what is happening So lets clean it up
case (state.dyn.me.do.orgsystem) { [NONE] { [more code bits] { bla bla bla code bla code [even more code] ya more code } [wow more code] { bla code } } [NEXT] { [more code bits] { bla bla bla code bla code [even more code] ya more code } [wow more code] { bla code } } }
My system is below it looks a lot more cleaner and all the brackets line up so you can see if you are missing one and using notepad ++ it shows the connecting brackets
Now im using tabs to move the code across and this is not the best practice because some programming languages do not recognize tabs or they do different things and break
My brother who is a coder uses 3 spaces instead of tab but because this programming language does not care i'm using tabs
Moral of the story is to use what you are comfortable with and what works with the current programming language you are working on
case (state.dyn.me.do.orgsystem) { [NONE] { [more code bits] { bla bla bla code bla code [even more code] { ya more code } } [wow more code] { bla code } } [NEXT] { [more code bits] { bla bla bla code bla code [even more code] { ya more code } } [wow more code] { bla code } } }
So by now you should know how to structure your brackets { }
Now onto moving between innercases
We can call the innercases whatever we want so long as they are all in capitals
We are at [NONE] and we want to move to [NEXT]
So we will use
state.dyn.me.do.changingcases = NEXT; state.dyn.me.do.changingcases = BOOBIES1234; case (state.dyn.me.do.changingcases) { [NONE] { } [NEXT] { } [BOOBIES1234] { } }
Now we have semicolons ;;;;;;;;;
These say that the current line has ended
state.dyn.me.do.changingcases = NEXT;
And thats it do this Without the ;
state.dyn.me.do.changingcases = NEXT
This line never ends and will result in an error
Now to actually change the case we would need to trigger something so lets introduce timers
case (state.dyn.me.do.timersarefun) { [NONE] { do_set_timer(6); state.dyn.me.do.timersarefun = START; } [START] { loc.ts = GetTs(); [loc.ts < state.dyn.me.do.ts] return; state.dyn.me.do.timersarefun = START2; } [START2] { } }
First part of the timers are setting the time duration
do_set_timer(6);
do_set_timer is a function in another file and we are giving it the infomation of (6) this is seconds
You can add in custom timers but i will not cover this because most people wont need them
loc.ts = GetTs(); loc.
stands for local which means this is only stored inside this innercase
So
loc.ts
loc.howyagoingm8
GetTs();
is a function in another file somewhere that gets the game time
So we are saying that
loc.ts
is whatever the current gametime is this next part is a condition
if
loc.ts
is less then the current time then go back up the top
[loc.ts < state.dyn.me.do.ts] return;
The inner case will stay the same but it will reset and run the
loc.ts
again and the time will update until
loc.ts
is greater then the time then it will no longer return back to the start
[loc.ts < state.dyn.me.do.ts] return;
Then it will run the code under it which in our case is
state.dyn.me.do.timersarefun = START2;
and that will move it to the next innercase
theres 2 main timers
do_set_timer(6); do_set_timer2(6); [loc.ts < state.dyn.me.do.ts] return; [loc.ts < state.dyn.me.do.ts2] return;
These timers dont work well with other timers but very raly will 2 timers be needed Now this is a bit more advanced but ill add it anyway
I found this works well if you need multiple timers running at the same time
[loc.ts >= state.dyn.me.do.ts] { }
Next is operators
[loc.ts == state.dyn.me.do.ts] if loc.ts is equal to ts [loc.ts != state.dyn.me.do.ts] if loc.ts is not equal to ts [loc.ts > state.dyn.me.do.ts] if loc.ts is greater then ts [loc.ts >= state.dyn.me.do.ts] if loc.ts is greater then or equal to ts [loc.ts <= state.dyn.me.do.ts]if loc.ts is less then or equal to ts
Then we can do some more
[loc.ts == state.dyn.me.do.ts & state.dyn.me.do.timersarefun == START2 ]
if loc.ts is equal to ts and timersarefun is equal to START2
[loc.ts == state.dyn.me.do.ts | state.dyn.me.do.timersarefun == START2 ]
if loc.ts is equal to ts or timersarefun is equal to START2
But wait theres even more
state.dyn.me.do.playwithvalues = 1;
This sets playwithvalues to whatever is set
state.dyn.me.do.playwithvalues += 1;
This adds a the value to the exsisting varaible
state.dyn.me.do.playwithvalues -= 1;
This subtracts the value to the exsisting varaible
state.dyn.me.do.playwithvalues *= 1;
This multiplys the value of the exsisting variable by whatever is set
state.dyn.me.do.playwithvalues /= 1;
This divides the value of the exsisting variable by whatever is set
state.dyn.me.do.playwithvalues ^= state.dyn.me.do.valuedoesnotexsist;
This ones a little bit diffrent it sets a value even if it does not exsist
We can even do things like this
state.dyn.me.do.playwithvalues = state.dyn.me.do.somevalue; state.dyn.me.do.playwithvalues += state.dyn.me.do.somevalue;
Ok lets move on to getting them to talk
This is the basic talk function
talk.s = "hello";
There are ways we can control this
talk.dur = 6000;//Time in milliseconds 1000 milliseconds is 1 second talk.delay = 4000;
We can even use a case to control what is said
Rnd(3);
This is a function to randomly select a value between the set number 0 is included so its 0 1 2 but (3)
loc.rnd = Rnd(3); case (loc.rnd) { [0] talk.s = "random0"; [1] talk.s = "random1"; [2] talk.s = "random2"; }
So what we are saying here is loc.rnd is a number between 0-2 and the case is what ever number that loc.rnd is then the whatever that number is the innercase will run
Here's another example but a bit more controlled
So this starts in start and set the count variable then make s 6 second timer and moves to START2
When it gets to START2 it waits till the 6 seconds are over then says say0
It adds 1 to the count variable and adds a 5 second timer and goes back up the top and will do this until we change the state which will happen when the count reaches 4 then the condition will be met and it will move to the next innercase
[START] { state.dyn.me.do.count = 0; do_set_timer(6); state.dyn.me.do.state2 = START2; } [START2] { loc.ts = GetTs(); [loc.ts < state.dyn.me.do.ts] return; case (state.dyn.me.do.count) { [0] talk.s = "say0"; [1] talk.s = "say1"; [2] talk.s = "say2"; [3] talk.s = "say3"; [4] talk.s = "say4"; } [state.dyn.me.do.count == 4] { state.dyn.me.do.state2 = NEXT; } state.dyn.me.do.count += 1; do_set_timer(5); } [NEXT] { }
Thats it for now the rest you will have to figure out on your own my suggestion is to open every game file you can and see how things are done
All i had was the tutorials that XPA did and the rest iv learned by either tinkering around or asking
If you need help feel free to ask on the forums but try to figure it out first you don't learn by people doing it for you