Luftwaffe

Forge Extension is the continuation of work on the Cortex Mod by Xethyr from 2013-2014 after the earlier developers Motive (2010-2012), DaFranker (2010) and SpriteLayer/zerg96 (2010) had stopped contributing.https://github.com/FabianPonce/CortexEngine/commits/master Forge was created out of frustration with the limitations of Cortex at the time. Significant features added were "gamesetups" (a method of saving and loading units), a UI toolbar, the advanced attachment command @attach+, user blacklists, and various other commands and tweaks.
Forge was developed from 2013-2014 before Xethyr began to argue that there were too many deep architectural issues with the Cortex codebase. Fixing the engine would require an entire overhaul and reworking from the very basics. Xethyr split from Cortex in late 2014 to briefly develop the Wyvern Roleplaying Engine, a new roleplaying engine built from scratch intended to fix deep flaws in the Cortex engine.https://github.com/nmosfet/wyvern-rp Wyvern development stopped by mid 2015, and Xethyr left the community altogether in early 2016.
== Issues with Cortex in 2013 ==
The following highlights the major issues of Cortex in 2013:
* Saving/Loading : Cortex had no method of saving units that were created. This led to problems where players would work on creating scenery for hours, only for the effort to be wasted by players leaving. They were forced to waste hours recreating scenery, hoping that enough players would stay.
* Removing Trolls : At the time, there was no way of removing players before a game started. There would often be a race between the host banning a troll and the troll ruining the game - a battle sometimes determined by who was smart enough to past the code in from the clipboard first!
* Attachment Complexity : The main method of making complex "attach models" was using "Attack Missiles," special actors that did not change the main actor for a unit for further attachments. The system was primitive and limited in nature.
* Creating Scenery : Creating scenery often involved spawning single units and applying visual commands on them separately, an inefficient process.
== Features Added in Forge ==
Features found from the Cortex Forge release logs and codebase.https://github.com/nmosfet/cortex-forge/releases
=== General ===
Note: All gamesetups, blacklists, and aliases do not save across maps created by different authors unless authors have coded in shared banks with common maps.
* Gamesetups:
** gamesetup save [name] and gamesetup load [name] allows players to save/load their units and their visual related commands. Gamesetups have poor compatibility with splicers and may glitch upon loading in too large chunks. They are not particularly efficient - the code for recreating the setup executes all at once and has the potential to lag or crash other players.
* Blacklists:
** Disables or bans blacklisted players at the game start, accessible on the lower half of the forge sidebar.
* Permissions:
** Allow host to prevent players in their games from using certain commands, accessible in a way similar to the above.
* Clan Tags:
** Clan tags are now displayed next to player's names.
* The ability to use !ban, !disable, !enable, !disable, !promote, !demote on non-players (e.g. Computer, Hostile, or Neutral) was removed.
* repeat # [command1; command2; ...]
** Causes the commands to be repeated # times.
* toggleanon, greentext, and sage:
** Toggleanon sets player name in chat to "Anonymous." Using a ">" before a message causes the message to be tinted green (anon or otherwise). Typing "sage" without anything else causes a newline to be printed to chat.
* replacemodel (or replaceeffect) [source] [dest]
** Replaces the "source" model/effect with the "dest" model.
* !fruit - map decoration!
* sound and !soundtrack
* !xml
** Toggles whether XML code can be used.
* !weather
* !mapbounds [x] [y]
 
=== Unit Related ===
* Caches:
** Units contain "command caches" that show the history of visual related commands on a unit. Accessed by using @cache to see the number of caches and @cache # to view specific cache. These are used by gamesetups to recreate units.
* @copy +visual:
** Allows copying a unit along with all customizations to the model. Not using +visual will not copy the visual part of the unit, only the data and items visible when selected.
* @undo #:
** Recreates a unit with the last # of commands from the cache removed. This command may break splicers.
* @subtitle [text]:
** Adds a subtitle to a unit under its name.
* @statbars [on/off]:
** Sets units' statbars on or off.
* @form and @squad:
** @form sets units in a specified formation. Supports rectangles, circles, and stars. @squad links units into a "squad." When one unit in a squad is selected, all the units become selected. Orders to one unit also translate to the rest of the squad. Squads can maintain formations. @squad break breaks the squad and makes units individual again. Note: @squad is extremely glitchy and often breaks, causing significant game lag. 
* @attach+:
** Attach+ is an advanced version of the command @attach. See @attach+ for details.
* @position [x] [y] [z]:
** Using @position displays a units coordinates. @position [x] [y] [z] sets a unit to that (x,y,z) coordinate.
* @actrmsg [msg]:
** Sends an actor message to the unit's main actor. These can be used to manipulate actors directly, such as the wireframe or creating overhead text effects. Note: actor messages are case sensitive. ModelSwap would work but modelswap will not.
* @tooltip [text] and @tooltip sub [text]:
** Sets the units' tooltip or sub-tooltip.
 
=== Doodad Commands ===
* _doodad
** Allows mouse-click based creation of "doodad" models directly on the map.
* _select
** Allows select of doodad models on the map. These include default doodads made by the terrainer.
* _clearhalos
** Removes "halos", the selection around doodads when using _select. 
* _remove
** Removes doodads selected.
* _removearea [radius]
** Removes doodads in a radius. Also effective in clearing unselectable stains.
* _destroy [radius]
** Destroys all actors in a radius. Can be destructive, but can be effective if _removearea fails to clear a stain.
* _tint, _scale, _face, _height, _modelswap, _animspeed
** Visual related for doodads.
 
=== Region Commands ===
* #select or #select [circle]
** Mouse-click based selection of rectangular or circular regions.
* #create [name]
** If a region is selected by #select, #create instead makes a region out of the selection. #create can be used independently and creates a small radius if nothing is selected to apply it to.
* #cancel
** Stops selection.
* #reveal [name]
** Makes the region visible.
 
=== UI ===
* Player Profiles
** Allows players to provide information about themselves and their interests.
* Command Guide
** List of commands, their syntax, and examples. Intended as a guide and to help new players.
* Search Catalog
** Allows players to search game data (e.g. Actors, Units, Models, etc...)
* Model Previewer
** Allows previewing of models, with a search function.
* Alias Editor
** Lists the players' aliases and allows for their modification. Considered by some to be a far more effective means of creating longer description aliases.
* Permissions
** Lists players in the game and allows you to put them on your blacklist and to set their permissions to use commands (when you are the host).
* Chat Log (Experimental)
** In the Development Branch of Forge, there is a chat log for messages when units use @say.
== Critical Examination of Forge ==
Forge inherited the Cortex codebase, which had coding architecture and style issues. Forge did not address these issues, instead another layer of code that contained flaws of its own. The result is a codebase that became even more complex and still loaded with flaws.
A common argument in the Cortex community is that poor coding does not matter if the product works; this arguement is itself flawed, as poor coding results in 1.) difficulty in debugging, 2.) difficulty for new developers, and 3.) inefficiency. Consider the bug "@setname breaks at 7 players." Due to the complexity of how @setname works (which is described below), players in the community have failed for years to figure out the bug behind this issue. More organized coding would have resulted in no error in the first place.
This section examines a few critical technical issues, both with architectural design and specific code, in Forge and in the Cortex Engine that Forge inherited.
 
=== Bloat ===
Forge added impractical features. !fruit and toggleanon are examples. While they may have made good jokes at the time, they serve little purpose in an engine where battle.net limitations dictate efficient use of coding space. The Cortex Engine contains numerous outdated and useless features that have not been removed.
 
=== Poor Coding Syntax ===
Cortex lacks documentation and comments in the code. It is difficult to determine what certain files do and where certain functions are located. These complexities result in issues when new developers are attempting to learn the codebase.
The syntax is not standard for coding. Consider this block of constants in Cortex/Common/Global.galaxy:
// Max players supported by SC2.
const int libcrtx_max_players = 16;
// Custom value indeces
const int libcrtx_unit_custom_value_guid = 0;
const int libcrtx_unit_custom_value_texttag = 1;
const int libcrtx_unit_custom_value_waygate = 2;
The constants are lower case. Traditionally, coders will capitalize all constants so that they are easily distinguished. While this does not harm the code itself, it can complicate examination of the code and figuring out what things are functions and what things are these constants.
 
=== Complexity ===
Cortex is a complex engine with many different modules. Few of the different files in the codebase have descriptions of what they do, and there are many cases where cortex executes code redundantly or inefficiently.
Consider the file Cortex/Common/SharedData.galaxy. This file contains arrays of variables for all players, such as:
point[libcrtx_max_players] libcrtx_mouse_positions;
Which represents the mouse cursor position for every player.
But in other files also contain these arrays of variables. Cortex/Chat.galaxy contains the variable array:
bank[libcrtx_max_players] libcrtx_alias_banks;
There is no distinction at whether Cortex/Common/SharedData.galaxy contains all commonly shared variables. These variables are scattered across various files.
There are also large portions of the codebase that are completely unused. Consider this block from Cortex/Common/ComputerAI.galaxy:
bool libcrtx_ai_is_enabled()
{
	return true;
}
void libcrtx_ai_start()
{
}
These two functions were blanked due to a conflict with a Blizzard Patch, yet left in the code and serve no purpose for existing.
It is ultimately quite difficult to figure out the source and purposes of various functions and variables in the Cortex codebase. Debugging Cortex generally involves going through a maze of files to figure out what code interacts with what other code, which may be a major contributor to the lack of recent updates and improvements to the cortex engine.
 
=== @setname ===
A constant issue in Forge is the "@setname breaks at 7 players." bug. However, no one has successfully diagnosed this issue. This does not diagnose the problem, but shows the difficulty in figuring out the issue. Consider the code for setting a unit's name in Cortex/Commands/ChatCommands.galaxy:
void libcrtx_assign_name_to_unit(unit u, string name)
{
	bank b;
	UnitSetCustomValue(u, libcrtx_unit_custom_value_guid, IntToFixed(libcrtx_command_chat_guid_counter));
	b = libcrtx_player_banks[EventPlayer()];
	if( b == null )
	{
		// create a new bank!
		b = BankLoad(libcrtx_bank_prefix + "chatsystem", EventPlayer());
		libcrtx_player_banks[EventPlayer()] = b;
	}
	BankValueSetFromString(b, "chat", IntToString( libcrtx_command_chat_guid_counter ), name );
	libcrtx_command_chat_guid_counter = libcrtx_command_chat_guid_counter + 1;
}
// Sadly, the return type must be text because blizzard has no TextToString() wtf?
text libcrtx_get_name_from_unit(unit u)
{
	string s;
	bank b = libcrtx_player_banks[EventPlayer()];
	if( b == null )
	{
		s = CatalogFieldValueGet(c_gameCatalogUnit, UnitGetType(u), "Name", UnitGetOwner(u));
		if( StringSub(s, 1, 10) == "Unit/Name/" ) {
			//libcrtx_write_success("FAILED TO LOAD BANK: RETURNING UNIT/NAME/");
			return StringExternal(s);
		}
	}
	// Convert to int, then to string so we don't end up with "832.00" which isn't the same as "832" in a string.
	s = BankValueGetAsString( b, "chat", IntToString(FixedToInt( UnitGetCustomValue(u, libcrtx_unit_custom_value_guid)) ) );
	if( s == "" ) // no name.
	{
		// Perform catalog lookup
		s = CatalogFieldValueGet(c_gameCatalogUnit, UnitGetType(u), "Name", UnitGetOwner(u));
		if( StringSub(s, 1, 10) == "Unit/Name/" ) {
			//libcrtx_write_success("FAILED TO FIND BANK STRING: RETURNING UNIT/NAME/");
			return StringExternal(s);
		}
	}
	//libcrtx_write_success(IntToString(FixedToInt( UnitGetCustomValue(u, libcrtx_unit_custom_value_guid))) + " : " + s);
	
	return StringToText(s);
}
This code was inherited from Cortex and uses a complex "bank" variable system. These banks are owned by each player. The banks purely exist to store unit names, inefficient compared to using the StarCraft engine's DataTable. The Wyvern Engine's method of setting a unit name simplifies the process with code located in wyvern/engine/unit.galaxy:
// libwyv_unit_set_name
// ===================
// Sets a unit's custom name into the global data table with format
// [unit_id]_NAME : [name]
void libwyv_unit_set_name(string name, unit u) {
	string key = FixedToString(UnitGetCustomValue(u, LIBWYV_UNIT_INDEX_ID), 0) + LIBWYV_UNIT_NAME_DATA_TABLE_IDENTIFIER;
	DataTableSetString(true, key, name);
}
The primary code of @setname is done in 2 lines - a far cry from the well over 10 lines in Cortex.
 
=== Lag from Large Gamesetups ===
Players often note that large gamesetups tend to cause significant lag. This is due to a large number of units and code being executed at the same time. The issue is in this loop in Cortex/Commands/Cache/GameSetups.galaxy:
	//load units
	i = BankKeyCount(libcrtx_gameSetup_bank[player], gamesetup_name + "_unit") - 1;
	while(i >= 0) {
		// ...
		// DO LOADING HERE
		// ...
		i -= 1;
	}
The while loop executes a large amount of code all at the same time, causing lag for all players. A way to stop lag would be adding stalls:
	//load units
	i = BankKeyCount(libcrtx_gameSetup_bank[player], gamesetup_name + "_unit") - 1;
	while(i >= 0) {
		// ...
		// DO LOADING HERE
		// ...
		i -= 1;
		Wait(0.0, c_timeReal);
	}
Adding a Wait for 0 seconds forces asynchronous loading. The game will continue with a slight pause between loading each unit, creating a far lesser draw on the machines of involved players. However, the caveat with the Wait 0 seconds is that a player can run commands while loading units, which may conflict with the load and damage the procedure, making a complete removal of the player and a restart of the process necessary.
== Wyvern Roleplaying Engine ==
The Wyvern Roleplaying Engine was created in December 2014 by the same developer who worked on Forge to address the codebase issues in Forge and Cortex described above. It was was written from scratch to improve how modules were structured in the original Cortex codebase, containing the improvements of Forge and integrating them into a new engine. While Wyvern functioned as a clone of Cortex's structure in early 2015, by 2016 Wyvern's internal architecture had diverged significantly from Cortex.
The most notable improvement was consolidating player variables, a bane existing to this day of the Cortex Engine. Wyvern's command system uses funcrefs rather than the Triggers used by Cortex.
By early 2016, Wyvern was not used by any maps other than Xethyr's own Wyvern testing maps. Wyvern development has stopped since early 2016. While Wyvern had the potential to succeed the cortex engine, it was never opened to the mainstream and remains a nice dream to the cortex community.
 
 
 
Category:Revise
Category:Engine
Category:Maps