List of commits:
Subject Hash Author Date (UTC)
Add Confectioner Scripting Language (CSL) & change array separator to ; 8d980bfac5d649574f749b7c04a19af766f71091 mse 2021-09-11 12:31:58
Fix console /set bug 7c45e27e7f40472bea317b0316e4367135b49704 mse 2021-09-11 01:32:11
Scriptable lines@, ids@, bugfix 9f606fd2a793fd76a9d1b9e186434d231b973085 mse 2021-09-10 14:43:50
Add array scripting (@ operator, ARRLEN <array>) 3f098b3e0a04922c2c7a981b232efd8d08a8d9a0 mse 2021-09-10 14:02:39
Optimize script runtime a298b01c9b77192b7ed8aba3832a8ab51c9d389a mse 2021-09-09 06:57:49
Scriptable bg$, fg$, caption$ 0ad08aa3887118d2376f4fa7f8b7c66e0f164c73 mse 2021-09-06 11:04:38
Animation command: ANIM <loop|play> <bg|fg> <fps> <directory> 6066e2cae1dc29043902d46549f443c7b683fd88 mse 2021-09-06 06:42:13
Switch to C++17 489987b1b2749f37e0ac76594308635affbd24f2 mse 2021-09-05 10:51:02
Fix stats synchronization bug 3b6195c3321a6f10af43839cc00d24f301eddb3e mse 2021-09-05 04:45:58
Add top-level command: STRLEN, scriptable player name$ ec7a623cdc98b9832f35f0beb3e45179e6094436 mse 2021-09-05 03:17:47
Start work on animation system d2aafd6f46c719342054e3f256f972f4917f2231 mse 2021-09-05 02:41:28
Add string scripting with $ operator 20034a2b658ee8ad4f2082c44301c231b0323fc7 mse 2021-09-03 10:20:55
Enhance console /set command to support operators 61032844fcb833f04e2f6d1e123f8f0f89333107 mse 2021-09-02 11:06:00
Add scriptable bribing & remove hard-coded karma increment 41b4d79da6331b4b1ffd96f36ae1b032a869b482 mse 2021-08-31 17:51:29
Add floor operator (_) 819304b561d474e962afa7397ef68ffae83e8649 mse 2021-08-31 13:49:57
Switch inventories and stats to floating-point c6e4142e664648ca8f4aa913b48526093c985987 mse 2021-08-31 13:35:20
Switch scripting to floating-point & code comments eb067496f4edb4420c05a09dc034ad0a25ad1e56 mse 2021-08-31 11:06:01
Add top-level command: GOSUB 62e9520aec0471fe023ead290595f735a30eb806 mse 2021-08-26 09:31:27
Add persistent VN stats 2d1ffc35afd8ae0f477cbd5aac0559fc02571600 mse 2021-08-23 10:44:16
Bribes increase karma 643f0fc6da65316aa799bbe00cea2030e2c1ccd6 mse 2021-08-17 08:16:36
Commit 8d980bfac5d649574f749b7c04a19af766f71091 - Add Confectioner Scripting Language (CSL) & change array separator to ;
Author: mse
Author date (UTC): 2021-09-11 12:31
Committer name: mse
Committer date (UTC): 2021-09-11 12:31
Parent(s): 7c45e27e7f40472bea317b0316e4367135b49704
Signing key:
Tree: 13b615ff7c993493f0d841da7364a1031f6d8d0e
File Lines added Lines deleted
base/dialogue_en/init.csl 12 0
base/dialogue_en/init.json 4 12
include/dialogue.h 77 13
File base/dialogue_en/init.csl added (mode: 100644) (index 0000000..632ef04)
1 [init]
2 bg$:black
3 caption$:Game not found.
4 lines@:Test Controller Rumble;Quit
5 ids@:rumble;quit
6
7 [rumble]
8 :CALLBACK #RUMBLE 1.0 500
9 :GOSUB init
10
11 [quit]
12 :CALLBACK QUIT
File base/dialogue_en/init.json changed (mode: 100644) (index e494418..a6b197b)
1 1 { {
2 // init.json is currently the main entry point. CSL must be bootstrapped.
3 // When CSL supports comments and array indexing, init.csl can be loaded
4 // first instead.
2 5 "init": { "init": {
3 "bg": "black",
4 "caption": "Game not found.",
5 "lines": [ "Test Controller Rumble", "Quit" ],
6 "ids": [ "rumble", "quit" ]
7 },
8
9 "rumble": {
10 "exec": { "void": "CALLBACK #RUMBLE 1.0 500#DIALOGUE init" }
11 },
12
13 "quit": {
14 "exec": { "void": "CALLBACK QUIT" }
6 "exec": { "void": "GOSUB init.csl" }
15 7 } }
16 8 } }
File include/dialogue.h changed (mode: 100755) (index 61525e2..9486a26)
... ... class Talk {
62 62 double getVariable( std::string key ); double getVariable( std::string key );
63 63 void setVariable( const std::string &key, double valueNumber ); void setVariable( const std::string &key, double valueNumber );
64 64 int parseJSON( std::string &text ); int parseJSON( std::string &text );
65 int parseCSL( std::string &text );
65 66 std::string stringifyNumber( double n ); std::string stringifyNumber( double n );
66 67 std::string stringifyArray( const std::vector<std::string> &arr ); std::string stringifyArray( const std::vector<std::string> &arr );
67 68 Operation getOperation( std::string key, double valueNumber, const std::string &valueKey ); Operation getOperation( std::string key, double valueNumber, const std::string &valueKey );
 
... ... class Talk {
71 72 }; };
72 73
73 74 void Talk::go( const std::string &id ){ void Talk::go( const std::string &id ){
74 if( id.length() >= 5 && id.substr( id.length() - 5 ) == ".json" ){
75 if( ( id.length() >= 5 && id.substr( id.length() - 5 ) == ".json" )
76 || ( id.length() >= 4 && id.substr( id.length() - 4 ) == ".csl" ) ){
75 77 screens.clear(); screens.clear();
76 78 std::string filePath = file.substr( 0, file.find_last_of( '/' ) + 1 ) + id; std::string filePath = file.substr( 0, file.find_last_of( '/' ) + 1 ) + id;
77 79 append( filePath ); append( filePath );
 
... ... void Talk::append( std::string filePath ){
130 132 text += std::string( buf, len ); text += std::string( buf, len );
131 133 } }
132 134 fclose( stream ); fclose( stream );
133 if( parseJSON( text ) == 0 ){
134 file = filePath;
135 if( filePath.length() >= 5
136 && filePath.substr( filePath.length() - 5 ) == ".json" ){
137 if( parseJSON( text ) == 0 ) file = filePath;
138 }else{
139 if( parseCSL( text ) == 0 ) file = filePath;
135 140 } }
136 141 } }
137 142
 
... ... int Talk::parseJSON( std::string &text ){
277 282 return 0; return 0;
278 283 } }
279 284
285 int Talk::parseCSL( std::string &text ){
286 // SET CURRENT SCREEN TO "init".
287 // FOR LINE IN text:
288 // IF LINE[0] == '[':
289 // FIND ']' AND SET CURRENT SCREEN TO THE CONTENTS.
290 // ELSE:
291 // LEX AND ADD LINE TO exec.
292
293 auto GetScreenPointer = [&]( const std::string &id ){
294 for( Screen &s : screens ){
295 if( s.id == id ){
296 return &s;
297 }
298 }
299 screens.push_back( {} );
300 screens.back().id = id;
301 return &screens.back();
302 };
303
304 Screen *screen_ptr = GetScreenPointer( "init" );
305
306 auto Lex = [&]( std::string line ){
307 if( line.length() >= 2 && line[0] == '[' ){
308 line.erase( 0, 1 );
309 size_t bracket_at = line.find_last_of( ']' );
310 if( bracket_at == std::string::npos ) return;
311 line.erase( bracket_at );
312 if( line.length() > 0 && line != screen_ptr->id )
313 screen_ptr = GetScreenPointer( line );
314 }else{
315 size_t colon_at = line.find_first_of( ':' );
316 if( colon_at == std::string::npos ) return;
317 std::string val_str = line.substr( colon_at + 1 );
318 char* p;
319 double num = std::strtod( val_str.c_str(), &p );
320 Operation o = getOperation(
321 line.substr( 0, colon_at ),
322 num,
323 ""
324 );
325 // If defining a string or array, or value is non-numeric,
326 // treat value as a string.
327 if( o.op == '$' || o.op == '@' || *p ) o.valueKey = val_str;
328 // Add the operation to the screen pointer.
329 screen_ptr->exec.push_back( o );
330 }
331 };
332
333 // Lex the text line by line.
334 size_t start = 0, end = 0;
335 while( ( end = text.find_first_of( "\r\n", start ) ) != std::string::npos ){
336 Lex( text.substr( start, end - start ) );
337 start = end + 1;
338 }
339 Lex( text.substr( start ) );
340
341 return 0;
342 }
343
280 344 // If n can be losslessly round-tripped between a double, a long long, // If n can be losslessly round-tripped between a double, a long long,
281 345 // and a double, return a string without a decimal. Otherwise, return a // and a double, return a string without a decimal. Otherwise, return a
282 346 // string with sprintf-style floating-point notation. // string with sprintf-style floating-point notation.
 
... ... std::string Talk::stringifyNumber( double n ){
291 355 } }
292 356 } }
293 357
294 // Return a #-separated list of strings with each string's # characters
295 // escaped as: \#
358 // Return a ;-separated list of strings with each string's ; characters
359 // escaped as: \;
296 360 std::string Talk::stringifyArray( const std::vector<std::string> &arr ){ std::string Talk::stringifyArray( const std::vector<std::string> &arr ){
297 361 std::string result; std::string result;
298 362 for( size_t i = 0; i < arr.size(); i++ ){ for( size_t i = 0; i < arr.size(); i++ ){
299 // Add separating # characters.
300 if( i > 0 ) result += "#";
301 // Replace # characters with \# and add the fragments to result.
363 // Add separating ; characters.
364 if( i > 0 ) result += ";";
365 // Replace ; characters with \; and add the fragments to result.
302 366 const std::string &str = arr[i]; const std::string &str = arr[i];
303 367 size_t start = 0, end = 0; size_t start = 0, end = 0;
304 while( ( end = str.find( '#', start ) ) != std::string::npos ){
305 result += str.substr( start, end - start ) + "\\#";
368 while( ( end = str.find( ';', start ) ) != std::string::npos ){
369 result += str.substr( start, end - start ) + "\\;";
306 370 start = end + 1; start = end + 1;
307 371 } }
308 372 result += str.substr( start ); result += str.substr( start );
 
... ... void Talk::operate( Operation o ){
346 410 if( !success ) it->second = {}; if( !success ) it->second = {};
347 411 // Parse the array. // Parse the array.
348 412 size_t start = 0, off = 0, end = 0; size_t start = 0, off = 0, end = 0;
349 while( ( end = o.valueKey.find( '#', start + off ) ) != std::string::npos ){
350 // Allow \# escaping. TODO: \\ escaping.
413 while( ( end = o.valueKey.find( ';', start + off ) ) != std::string::npos ){
414 // Allow \; escaping. TODO: \\ escaping.
351 415 if( end > 0 && o.valueKey[end - 1] == '\\' ){ if( end > 0 && o.valueKey[end - 1] == '\\' ){
352 416 // Remove the \ character from the string. // Remove the \ character from the string.
353 417 o.valueKey.erase( end - 1, 1 ); o.valueKey.erase( end - 1, 1 );
354 // `end` now points to the character after the #.
418 // `end` now points to the character after the ;.
355 419 off = end - start; off = end - start;
356 420 continue; continue;
357 421 } }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/mse/ConfectionerEngine

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/mse/ConfectionerEngine

Clone this repository using git:
git clone git://git.rocketgit.com/user/mse/ConfectionerEngine

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main