This could cause problems with functions that take states as parameters but use them to set them internally instead of passing them through the A_Jump interface back to the caller, like A_Chase or A_LookEx.
This required some quite significant refactoring because the entire state resolution logic had been baked into the compiler which turned out to be a major maintenance problem.
Fixed this by adding a new builtin type 'statelabel'. This is an opaque identifier representing a state, with the actual data either directly encoded into the number for single label state or an index into a state information table.
The state resolution is now the task of the called function as it should always have remained. Note, that this required giving back the 'action' qualifier to most state jumping functions.
- refactored most A_Jump checkers to a two stage setup with a pure checker that returns a boolean and a scripted A_Jump wrapper, for some simpler checks the checker function was entirely omitted and calculated inline in the A_Jump function. It is strongly recommended to use the boolean checkers unless using an inline function invocation in a state as they lead to vastly clearer code and offer more flexibility.
- let Min() and Max() use the OP_MIN and OP_MAX opcodes. Although these were present, these function were implemented using some grossly inefficient branching tests.
- the DECORATE 'state' cast kludge will now actually call ResolveState because a state label is not a state and needs conversion.
- removed AMinotaurFriend::IsOkayToAttack. The condition it checks (i.e. friendliness with player) is already covered by the base version of this function so this is quite redundant.
- removed a few 'virtual' qualifiers from functions that never get overridden.
Syntax-wise I chose to make it as strict as possible to reduce the chance of errors: Virtual base functions must be declared with the 'virtual' keyword, and overrides in child classes with the 'override' keyword. This way any mismatch in parameters that otherwise would cause silent failure will outright produce a compile error.
- made 'DamageMultiply' an actor property and moved the initialization of ConversationRoot to the property handler for the compiler to get this stuff out of the type classes.
- consolidate default initialization into one function which performs all the required setup. The original implementation did this when adding the fields but that cannot work because at that time no defaults have been created yet.
- fixed: When deriving a class the child class's defaults also must initialize the copied parent fields with special initialization. This part was completely missing.
- removed DECORATE code for parsing native classes because it's no longer needed.
- made some tests about calling script code from native functions.
* scriptified A_SkullAttack to have something to test
* changed the A_SkullAttack call in A_PainShootSkull.
* use a macro to declare the function pointer. Using local static variable init directly results in hideous code for the need of being thread-safe (which, even if the engine was made multithreaded is not needed here.)
* Importsnt node here: Apparently passing an actor pointer to the VMValue constructor results in the void * version being called, not the DObject * version.
- added an 'exact' parameter to FThinkerIterator's Next function. This is mainly for scripting which allows to do a lot more checks natively when running the iterator while looking for one specific class.
- added support for global variables to the code generator - not the compiler, though. For the handful of entries this is needed for it may just as well be done manually. So far FLevelLocals level is the only one being exported.
- fixed: The VM disassembler truncated 64 bit pointers to 15 digits because the output buffer was too small.
- resolve entire FxSequences instead of aborting on the first failed entry. This allows to output all errors at once.
- exported thinker iterator and drop item chain to scripting. Unlike its native counterpart the script-side iterator is wrapped into a DObject to allow proper handling for memory management.
- fixed: The VMFunctionBuilder only distinguished between member and action functions but failed on static ones.
- fixed: FxAssign did not add all needed type casts. Except for purely numeric types it will now wrap the expression in an FxTypeCast. Numeric handling remains unchanged for both performance reasons and not altering semantics for DECORATE.
- exported all internal flags as variables to scripting. They still cannot be used in an actor definition.
- make ATAG_STATE the same as ATAG_GENERIC. Since state pointers exist as actual variables they can take both values which on occasion can trigger some asserts.
- gave PClass a bExported flag, so that scripts cannot see purely internal classes. Especially the types like PInt can cause problems.
Todo: we need readonly references to safely expose the actor defaults. Right now some badly behaving code could overwrite them.
- fixed: FxMinusSign trashed local variables that were used with negation.
- fixed: FxConditional only handled ints and floats, but not pointers and strings.
- fixed: A 'no states in non-actors' error was triggered, even for classes without any states.
- fixed several occurenced where vectors were treated as floats. NOTE: The entire codegen.cpp file needs to be carefully reviewed for bad use of the REGT_ constants, there's probably more places where using them has broken some type checks.
- fixed: committed test version of zscript.txt instead of changed actor.txt by accident.
Initialization and assignment for strings is working with this commit.
- swapped parameters of two-parameter VelToAngle method, so that internal and script version are in line.
- fixed parameter asserts to handle NULL pointers properly.
- fixed: ZCCCompiler did not process array access nodes.
- fixed: Function argument names were not placed in the destination list by the compiler.
- scriptified several trivial functions from p_actionfunctions.cpp.
- disabled the assert in PType::GetRegType. This assert blocks any use to check for types that are incompatible with function parameters.
- pass the default parameter constants to the native functions. At the moment this is not used yet.
- use the function defaults to complete argument lists to script functions.
- fixed all default values that got flagged by the expression evaluator as non-constant. Most were state labels and colors which were defaulted to "". The proper value is null for states and 0 for colors.
- also replaced all "" defaults for names with "none".
- fixed: Script functions did not receive the function name when being created.
- relaxed the asserts for PARAM_STATE, because the VM knows nothing about ATAG_STATE. Any state variable's content (e.g. Actor.SeeState) will receive ATAG_GENERIC, rather than ATAG_STATE.
- added a 'NeedResult' flag so that certain operations can create shorter code if the result of the expression is not needed. So far only used for postdecrement/increment statements on local variables (which is the most frequent case where this matters.)
- fixed postincrement and decrement for local variables. Due to the result preservation semantics it created faulty code.
- removed 'self' as a dedicated token. Internally this gets handled as a normal but implicitly named variable so the token just gets in the way of proper processing.
- removed P_ prefix from SpawnMissile export.
- fixed a crash with misnamed function exports.
- allow class extensions.
These are separate blocks in different files that get concatenated to one class body for processing. The reason is to allow spreading the many functions in Actor over multiple files, so that they remain manageable. For example, all the Doom action functions should be in their respective files, but their symbols need to be in Actor. To extend a class, both files need to be in the same translation unit, so it won't allow user-side extension of internal classes.
- added a TESTN instruction. This is like TEST but negates the operand. This was added to avoid flooding the constant table with too many case labels. With TEST and TESTN combined, all numbers between -65535 and 65535 can be kept entirely inside the instruction. Numbers outside this range still use a BEQ instruction.
- fixed emission of the self pointer in FxVMFunctionCall. I did not realize that the self expression only sets up a register for the value, not pushing it onto the stack.
This will restrict them to the only classes that may use them: Weapon and CustomInventory.
Note: Should a mod surface which uses them improperly the better solution would be a warning message and NULLing the bogus code pointer instead of leaving them in Inventory.
- added a descriptive name to all types for error messages.
- added a generic type cast node to the code generator.
- added a few more cast operations to the 'cast' VM instruction.
- extended FxClassTypeCast to handle all possible input that can be cast to a class pointer, not just names.
- ANIMATED contained definitions for Doom, Heretic, and Strife, all
crammed into a single file. This meant that animations from one game
could erroneously make their way into maps for another game that
provided custom textures with names that matched textures that animated
in the other game. There are now three separate ANIMATED lumps with only
the animations defined for the original game and no others. The one
that gets loaded depends on the game being played.
- Added documentation for the ANIMATED file format to the comment for
FTextureManager::InitAnimated(), since I had to figure it out from the
code.
- fixed a few problems that were encountered during conversion:
* action specials as action functions were not recognized by the parser.
* Player.StartItem could not be parsed.
* disabled the naming hack for PowerupType. ZScript, unlike DECORATE will never prepend 'Power' to the power's name, it always needs to specified by its full name.
* states and defaults were not checked for empty bodies.
* the scope qualifier for goto labels was not properly converted to a string, because it is an ENamedName, not an FName.
- started with the AST converter. So far it only deals with direct function calls with simple constants as parameters.
- added an error condition for the defaults block to get rid of some asserts.
- fixed uninitialized counter variable in DECORATE parser.
- allow dottable_id of xxx.color so that the property parser can parse 'powerup.color'.
- fixed crash with actor replacement in script compiler.
- add the lump number to tree nodes because parts of the property parser need that to make decisions.
- removed test stuff.
- converted inventory.txt, player.txt and specialspot.txt to ZSCRIPT. These were the minimal files required to allow actor.txt to parse successfully.
- removed the converted files from the DECORATE include list so that these are entirely handled by ZSCRIPT now.
- split FinishActor into several functions. While DECORATE can, ZSCRIPT cannot do all this in one go.
- split the state finalization into several class-specific virtual functions.
- Sets the absolute amount of an inventory actor.
- Limits itself to the range [0, MaxAmount]. Setting beyondMax to true disregards the MaxAmount. Default is false.
- switched the types of the internal 'self' and 'stateowner' parameters so that they get assigned correctly. I can't tell if this will error out if fields get accessed from the caller with the wrong class, but for actual scripting to work these must be correct.
The committed 'actor.txt' can be parsed successfully, with the exception of a few subclass references that cannot be resolved yet.
This adds:
* builtin types color, state and sound.
* ending a parameter list with an ellipsis to declare a varargs list. (A_Jump uses this.)
* allowing to declare optional arguments by giving them a default value.
* adding an 'action' qualifier for function declarations.
- fixed: The tree nodes for classes and struct members were stored in the global tree nodes table.
- sort variable declarations into their own list for processing.
This uses a different algorithm as the old implementation - instead of recursively resolving unknown symbols it will first collect all constants from all scopes and then process them in one operation, doing multiple passes over the list until no more constants can be resolved anymore.