Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // mockup of some "script definition" that generates a Source Engine CFG script
- // i'm too dumb to actually implement this tho
- // so i'm just gonna use shellscripts to automatically generate it
- // and just use this as pseudo-code reference.
- // The implementation of conditional logic and setters in a Source Engine
- // CFG script uses this approach:
- // // SWITCH
- // alias print>0 "echo 0" // these are called conditionals. main logic
- // alias print>1 "echo 1"
- // alias print>2 "echo 2"
- // alias printwithfeeling>0 "echo 0!"
- // alias printwithfeeling>1 "echo 1!"
- // alias printwithfeeling>2 "echo 2!"
- // // these are setters.
- // // all logical aliases that depend on this variable ("a")
- // // are assigned to its respective conditional
- // alias a=0 "alias print print>0; alias printwithfeeling printwithfeeling>0"
- // alias a=1 "alias print print>1; alias printwithfeeling printwithfeeling>1"
- // alias a=2 "alias print print>2; alias printwithfeeling printwithfeeling>2"
- // a=1 // variable assignment
- // print // logical alias call
- // a=2
- // printwithfeeling
- //
- // The following are examples of what you could do with this approach:
- // // COPY
- // alias copy>0 "b=0"
- // alias copy>1 "b=1"
- // alias a=0 "alias copy copy>0"
- // alias a=1 "alias copy copy>1"
- // a=1
- // copy
- //
- // // NOT
- // alias not>0 "b=1"
- // alias not>1 "b=0"
- // alias a=0 "alias not not>0"
- // alias a=1 "alias not not>1"
- // a=1
- // not
- //
- // // AND
- // alias and>0 "c=0"
- // alias and>1>0 "c=0"
- // alias and>1>1 "c=1"
- // alias a=0 "alias and and>0"
- // alias a=1 "alias and and>1"
- // alias b=0 "alias and>1 and>1>0"
- // alias b=1 "alias and>1 and>1>1"
- // a=1; b=0
- // and
- //
- // // OR
- // alias or>0>0 "c=0"
- // alias or>0>1 "c=1"
- // alias or>1 "c=1"
- // alias a=0 "alias or or>0"
- // alias a=1 "alias or or>1"
- // alias b=0 "alias or>0 or>0>0"
- // alias b=1 "alias or>0 or>0>1"
- // a=1; b=0
- // or
- // The following is a 2nd possible implementation. Currently unused in
- // final script generation.
- // It's slower but is more flexible.
- // It is originally from https://github.com/ArgosOfIthaca/scalu/wiki/Article:-From-aliases-to-arithmetic#conditional-logic
- // // SWITCH
- // alias 2 ""
- // alias 1 ""
- // alias 0 ""
- // alias print>0 "echo 0"
- // alias print>1 "echo 1"
- // alias print>2 "echo 2"
- // // logical assignment of aliases is done when alias is invoked
- // // instead of when the variable is assigned
- // // the variable is an alias itself that is executed
- // // Amount of alias assignments is equal to # of possible values
- // // instead of # of aliases that depend on the variable
- // alias print "alias 0 print>0; alias 1 print>1; alias 2 print>2; a"
- // alias printwithfeeling>0 "echo 0!"
- // alias printwithfeeling>1 "echo 1!"
- // alias printwithfeeling>2 "echo 2!"
- // alias printwithfeeling "alias 0 printwithfeeling>0; alias 1 printwithfeeling>1; alias 2 printwithfeeling>2; a"
- //
- // alias a "1" // variable assignment
- // print // logical alias call
- // alias a "2"
- // printwithfeeling
- config {
- // Script name must come before all its aliases, followed by a period.
- // (e.g. MOVEP.alias)
- name MOVEP;
- // The following are to-be automatic defaults.
- alias_length_limit 31;
- console_command_length_limit 510;
- // required since some script alias names wouldn't fit the limit
- // (e.g. "MOVEP.setDir>FALSE>FALSE>FALSE")
- // note: naturally, public aliases don't use code names so they can
- // be easily reassigned in-game or in other scripts. both aliases and
- // variable setters can either be public or private
- use_script_alias_code_names 1;
- // note: alias names are case-insensitive
- // note: script aliases with codenames are formatted as
- // "{scriptname}.@{alias_codename}"
- // code-named script aliases are similar to youtube video links in that it
- // serves as a unique identifier for the alias. they're fine since we won't
- // expect people to look at the cfg itself to see the logic of the
- // script, and instead, we expect them to look at the script definition.
- alias_code_name_charset "0123456789abcdefghijklmnopqrstuvwxyz_%$";
- }
- // Arithmetic expressions on enums are modular
- enum keyState {
- RELEASE;
- PRESS;
- }
- enum moveDirection {
- N; // no value = symbolic = can't do arithmetic and can only be used when explicitly referenced
- F 0.0;
- FL 0.5;
- L 1.0;
- BL 1.5;
- B 2.0;
- BR 2.5;
- R 3.0;
- FR 3.5;
- }
- enum cardinalDirection {
- 0 F;
- 1 L;
- 2 B;
- 3 R;
- }
- enum socdMode {
- NORMAL;
- NONULL;
- HITBOX;
- NONBOX;
- }
- // Variables
- // NOTE: Should always have a predefined/default value!
- // Examples of batch creating keyed variables from enum types
- // bool is an example of a built-in type.
- // Maybe i'll add more such as ints, strings and floats with specified sizes.
- bool pressed[cardinalDirection] = FALSE
- bool final[cardinalDirection] = FALSE
- //keyState currentIState = RELEASE
- cardinalDirection currentIDirection = F
- moveDirection finalDir = N
- public socdMode socdMode = NONULL
- // Aliases
- // Variables that are local to methods are mostly used to implement batch direct
- // conditional aliases and avoid using setter aliases to implement logic, such as in
- // +move[cardinalDirection]
- // With handleInput as an example, alias conditionals of all possible values of the
- // local variables' enum types will be generated
- // (handleInput>{F,L,B,R}>{RELEASE,PRESS}), e.g. handleInput>B>PRESS
- // This is done because SETTERS ARE REALLY TOUGH ON SCRIPT PERFORMANCE WITH ALL
- // ITS ALIAS ASSIGNMENTS
- // As a general rule, it is better to define and use predefined aliases instead
- // of relying on setter aliases when it comes to conditional logic, which is why
- // The first method of conditional logic is preferred.
- // are set to default behaviors for debugging
- void sendCustomCmd (finalDir) {
- // Example of console command that references a variable
- public >finalDir {[echo finalDir = {finalDir}]}
- }
- void handleInput (keyState state, cardinalDirection dir) {
- // This is an example of a method/alias conditional.
- // Also an example of not using an enum in order to batch define conditionals
- // Also an example of nesting multiple local variables into one conditional defintion
- >state>dir {
- //currentIState = state;
- currentIDirection = dir;
- sendMoveCmd>state>dir;
- pressed[dir] = state; // enum type auto casting; state is evaluated as either TRUE OR FALSE; can also be manually set with (bool) state
- handleSocd>state>dir;
- setDir;
- sendCustomCmd;
- }
- }
- // _ = no variable used, manual conditional definition
- // still benefits from not using global variables to conditionally set handleSocd
- // meaning no setters directly set hancdleSocd
- // meaning handleSocd can't be called directly
- // meaning the conditionals (handleSocd>RELEASE, etc.) must be called directly
- void handleSocd (keyState _) {
- >RELEASE (cardinalDirection dir) {
- >dir (pressed[dir+2]) { // if no enum type is specified, assume the reference of a global variable
- >FALSE {
- final[dir] = FALSE;
- }
- >TRUE {
- final[dir] = FALSE;
- final[dir+2] = TRUE;
- // This is why setDir doesn't use a local variable
- // Makes the upcoming "setDir" process currentIDirection as the press of the opposite direction
- //currentIState = PRESS // This part is unnecessary actually
- currentIDirection = dir+2;
- sendMoveCmd>PRESS>dir+2;
- }
- }
- }
- >PRESS (cardinalDirection dir) {
- >dir (pressed[dir+2]) {
- >FALSE {
- final[dir] = TRUE;
- }
- >TRUE {
- handleSocdMode>dir;
- }
- }
- }
- }
- void handleSocdMode (cardinalDirection dir) {
- >dir (moveMode) {
- >NORMAL {
- final[dir+2] = FALSE;
- final[dir] = FALSE;
- }
- >NONULL {
- final[dir+2] = FALSE;
- sendMoveCmd>RELEASE>dir+2;
- final[dir] = TRUE;
- }
- >HITBOX {
- // Example of an anonymous conditional function
- lambda (dir) {
- >F, >B {
- final[F] = TRUE
- final[B] = FALSE
- sendMoveCmd>PRESS>F
- sendMoveCmd>RELEASE>B
- currentIDirection = F
- }
- // First example of default case
- >... {handleSocdMode>dir>NORMAL}
- }
- }
- >NONBOX {
- // Example of an anonymous conditional function
- lambda (dir) {
- >F, >B {
- final[F] = TRUE
- final[B] = FALSE
- sendMoveCmd>PRESS>F
- }
- // First example of default case
- >... {handleSocdMode>dir>NONULL}
- }
- }
- }
- }
- void setDir (currentIDirection) {
- // Example of a global variable batch defining conditionals for
- // expressions referencing it to work
- >currentIDirection (final[currentIDirection]) {
- >FALSE (final[currentIDirection+1], final[currentIDirection+3]) {
- >FALSE>FALSE {finalDir = N}
- >FALSE>TRUE {finalDir = {currentIDirection + 3}} // auto cast
- >TRUE >FALSE {finalDir = {currentIDirection + 1}} // auto cast
- >TRUE >TRUE {finalDir = N}
- }
- >TRUE (final[currentIDirection+1], final[currentIDirection+3]) {
- >FALSE>FALSE {finalDir = currentIDirection}
- // Example of the use of a function in an expression
- // e.g. if currentIDirection is R, then this evaluates to BR
- >FALSE>TRUE {finalDir = diagonalDir>R>currentIDirection}
- // e.g. if currentIDirection is B, then this also evaluates to BR
- >TRUE >FALSE {finalDir = diagonalDir>L>currentIDirection}
- >TRUE >TRUE {finalDir = currentIDirection}
- }
- }
- }
- // Script methods that return nothing are simply actual aliases. Methods that
- // do return a value, are a special case.
- // If it simply returns a value and/or interacts with variables in a read-only
- // manner, it acts as a function that is used by the script generator to
- // determine and evaluate the returned value.
- // If it is a similar case but it also performs actual operations on methods and
- // variables, then it is both an actual alias and a function. If the method is
- // invoked in an expression of a variable assignment, the script generator will
- // evaluate it as the execution of the alias and, simultaneously, the assignment
- // of said variable to the returned value. This means that NO SETTERS THAT
- // INCLUDE THE FUNCTION IN ANY WAY ARE DEFINED (e.g. MOVEP.finalDir=diagonalDir>L>F).
- // SETTERS ARE SIMPLE DECLARATIONS OF A VARIABLE TO EVERY POSSIBLE VALUE OF ITS
- // ENUM TYPE.
- // In this case, it is simply a function that serves readability.
- moveDirection diagonalDir (cardinalDirection _) {
- >L (cardinalDirection dir) {return dir + 0.5} // auto cast
- >R (cardinalDirection dir) {return dir - 0.5} // auto cast
- }
- void sendMoveCmd (keyState _) {
- >RELEASE (cardinalDirection _) {
- // examples of direct console commands
- >F {[-forward]}
- >B {[-back]}
- >L {[-moveleft]}
- >R {[-moveright]}
- }
- >PRESS (cardinalDirection _) {
- >F {[+forward]}
- >B {[+back]}
- >L {[+moveleft]}
- >R {[+moveright]}
- }
- }
- // An example of a bifurcated/bind alias
- // In the actual CFG script, the +/- should always be the first character in
- // the alias, so it will start ahead of the script name in order to work in
- // keybindings. (i.e. "+MOVEP.move>F" instead of "MOVEP.+moveF")
- // NOTE: Bifurcated aliases are always public, since... you need them in order
- // to bind them to keys, DUH!
- bind move {
- // Return types are defined for both press (+) and release (-)
- // NOTE: For this alias, it can be referenced as "+move" or "-move"
- // in other parts of this script definition (but it's not, though).
- void + (cardinalDirection dir) {handleInput>PRESS>dir}
- void - (cardinalDirection dir) {handleInput>RELEASE>dir}
- }
- // Possible generation optimizations/features:
- // - If an alias calls another that has no dependence on a variable, like
- // a conditional, then the alias can just evaluate it as the entire logic of
- // the other to avoid alias calls. I could see this in sendMoveCmd, move, and
- // the default case in handleSocdMode>dir>HITBOX. This would make the alias
- // a function, lowering the alias count. This could also be done for setters
- // setting an alias to a conditional with only one line of logic with no spaces.
- // - Warn for unused variables and aliases (already one in the form of
- // currentIState)
- // - Public variable values menu with variable and value descriptions?
- // (Public alias menu not possible tho)
- // - Logic in aliases that come before or after its conditionals will end up
- // before or after all places where the alias is called. However, this cannot
- // be done for variable-dependent logic.
Advertisement
Add Comment
Please, Sign In to add comment