Updating GameStudio

GameStudio/A6 updates are free for anyone who purchased a Gamestudio/A6 version from Conitec. They are available on the forum and on the download page. Updating is easy: you'll need about 4 mouse clicks to get your Gamestudio version up to date. You don't need to be an expert and normally don't need to edit any scripts. However you must be able to understand and follow the instructions below.

Installing the Update

Q. Why am I getting an error message ("Can't update" or "Error 36") after attempting to update?
A. You have given a wrong folder, or some files in your folder were set to read-only. Another possibility is that you've started the update program out of a command shell - start it just by double clicking in the icon instead.

Q. Why am I getting "Error 37" or "Error 39"?
A. Your download was aborted, or the file is corrupted for other reasons. Download again. A download manager, like GetRight, enhances transfer reliability. Another possibility is that the file was modified by a virus on your system.

Q. I'm getting "Can't update file xxxx" or "Access to file xxx denied".
A. There can be several reasons why a file in the Gamestudio folder is not accessible. Maybe WED or MED or another file was still running or still open, or a file or folder was set to system, read/only, or to restricted access. That file was not updated in that case. For updating you need to log in with administrative rights in a Window 2000, ME or XP system. Set the write protection property of your whole Gamestudio folder to 'Not Write Protected'. Make sure that all files are closed and accessible, and update again. You can repeat the update process as often as you want. If in doubt, the following method should help: set the read/only attribute of all files in the installation folder, and then set it back again for all files.

Q. I'm getting script error messages when starting my level.
A. This is the typical problem after updating. There are 3 possible reasons. Your template scripts are not updated, you are using an object that has the same name as one of the new variables or functions, or you have a syntax error in your script that was not detected by prior versions. If you're using the A6 templates, open WED->File->Project Manager and apply the Update function to the used scripts. Otherwise just go and fix the script errors.

Q. I've checked my template scripts and am still getting script error messages on certain commands.
A. If you get an error message on a certain engine function or variable, look in the manual to check whether this function exists at all. Long-abandoned A3 or A4 instructions are kept for a while for compatibility reasons, but are finally removed from the compiler after several years. Replace them by proper C-Script syntax.

Q. The keyboard shortcuts of WED don't work anymore.
A. Open WED->Preferences and set Key->Default->Apply.

Q. Strange things are happening when I run my project.
A. See compatibility notes below.

Version 6.60 compatibility notes

Version 6.60 is 100% code compatible to its predecessor. Below you'll find a list all differences that could lead to a different behavior of 6.60 compared to 6.40, or require small adaptions. When updating from an older version than 6.40, read the version 6.40 compatilibity notes!

Please note: due to a severe bug with the collision detection (see bugs), version 6.50 was replaced by version 6.60.

New features implemented in V6.60

ent_setmesh can be used to change the mesh of an entity, f.i. for adding lightmapping data.

move_friction now also works for the OBB collision detection.

bmap_to_alpha creates an alpha channel for an intransparent bitmap.

The CD device is now opened at the first cd_play call rather than at engine startup, thus saving 1..2 seconds startup time when a CD is in the player.

For the watched entity now also the nearest collision obstacle is displayed (if any). If an entity is stuck, the reason can be determined this way.

Toggle and Radio buttons can now be put on a panel, and the button_state function can read or change the state of a button.

In Customize panels, horizonal sliders can now be defined with the // cntl: slider comment tag.

Setting a panel size that exceeds the panel bitmap size creates a repeating background pattern on the panel.

Entities with transparent and intransparent skins are now rendered in both passes (transparent and intransparent). This allows to have an entity with transparent parts without sorting errors on its intransparent parts..

The joy_buttons variable can be used to check the states of up to 32 joystick buttons.

The on_exit function is executed just before the engine exits due to a sys_exit call.

The mouse_dir3d vector can be used to trace a ray to or from the mouse position.

The d3d_caps variable contains information about the capabilities of the 3D hardware device.

The last_error variable indicates errors of the last level_load function.

Sounds can be paused and resumed by snd_pause and snd_start.

An unlimited number of resources and resource files is now supported. The engine error messages 1005 and 1006 are not issued anymore.

dll_open can be used to open a DLL from a different path than the acknex_plugins folder. The DLL is automatically closed.

A matTangent matrix in a shader is a hint for the engine to generate tangents on the third texture coordinate set (TEXCOORD2). This has the advantage that a bumpmap effect can be directly assigned to a model skin without the need to assign a special material with the TANGENT flag.

str_cursor can be used to determine the cursor position within an edited string.

num_lights gives the number of currently active dynamic lights, and is indicated in the 'count' column of the Statistics Panel.

file_str_readto can read an arbitrary number of characters from a file into a string.

file_find can be used to find certain strings in a file.

txt_sort sorts strings in a text.

txt_for_dir can produce a directory listing of certain files in a folder.

New features implemented in V6.50

Model shaders now support several skins per mesh subset, f.i. for normal maps. The skin assignments are detected automatically by the engine. Any additional skins that belong to a subset must immediately follow the skin that is assigned to that subset. For instance, let's assume that an entity has 3 mesh subsets, and the following skin assignments:

Skin1 -> assigned to subset 1
Skin2 -> unassigned (normal map for subset 1)
Skin3 -> subset 2
Skin4 -> unassigned (normal map for subset 2)
Skin5 -> subset 3
Skin6 -> unassigned (normal map for subset 3)
Skin7 -> unassigned
Skin8 -> unassigned

The 3 subsets are rendered in 3 passes, where the assigned skin is always entSkin1 and the normal map is always entSkin2. In render pass 1, Skin1 is used for entSkin1, Skin2 for entSkin2, Skin7 for entSkin3, and Skin8 for entSkin4. In render pass 2, Skin3 is used for entSkin1, Skin4 for entSkin2, Skin7 for entSkin3, and Skin8 for entSkin4. In render pass 3, Skin5 is used for entSkin1, Skin6 for entSkin2, Skin7 for entSkin3, and Skin8 for entSkin4.

 P  The COMMAND statement can be used to define engine command line options in a starter window definition.

command_str can be used to control the script by command line options.

The C-Script Workshop was updated to version 6.40 and 6.50. Outdated methods and keywords were replaced.

SED Watches are now saved and restored when exiting and re-starting SED. SED should now be able to find the Gamestudio path automatically, so the path field was removed from SED Preferences.

SED Debug mode was improved. Entities and all other script objects can now be added to the Watch list. The SED cursor is now automatically placed at the current source line when single stepping in the engine. The F10 key is now the default key for single stepping both in the engine and in SED. SED does not crash anymore when something unexpected is encountered, f.i. when it is terminated while the engine window is still open.

When started without giving a file name, the engine now changes the current directory to it's own folder. This ensures that published engines will find their files even when run from within a different folder.

When using the engine as model viewer, the model is now set to the me pointer. This way entity properties can be changed, and entity functions can be called at runtime after pressing Tab.

A6.50 renders high-polygon models remarkably faster than its predecessors (worst case level: 6.50 - 82 fps; 6.31 / 6.40 - 38 fps). Of course, in normal levels and with low-polygon models the fps gain will be smaller.

WED can now display models, map and terrain entities with their textures, separately in the 3D and 2D views. For this, select View / Draw Entitites (2D) resp. Draw Entitites (3D) for selecting between textured, solid, and wireframe mode. Only supported by the GXL2DX9 Dlls.

Stencil buffer shadows previously used a clipping algorithm that predicted the shadow size. The shadow was drawn when its predicted 'footprint' on the floor entered the view frustrum. This caused shadows to be cast even from far away objects, but led to early shadow disappearance of objects high above the floor or very close to the camera. The prediction algorithm did more harm than good, and was thus removed. Shadows are now drawn when the object is within or close to the view frustrum. This avoids the "shadow disappearance" effect, but causes shadows to be not visible when the object is out of the view.

New template: MtlFX.wdl. This is the template for the future standard shader collection. It currently contains 4 shaders:

fx_terraintex3 assigns the well-known multitexture shader to a terrain. This template replaces the MtlTerrainMulti.wdl.

fx_water_mirror assigns a realtime mirror with bump map and water ripple effect to a water terrain.

fx_water_env performs environment mapping with ripple effect for water terrains (water.hmp). If the level map contains a sky cube, it is used for the reflection; otherwise a default sky cube is used. fx_water_env does not perform a realtime reflection; thus it's faster than fx_water_mirror, does not require the Pro Edition, and also works on old 3D cards that don't support clipping planes.

fx_uvspeed shifts a model texture in X and Y direction according to the speeds given in the entity Skill1 and Skill2 parameters.

By pressing F11 twice, the bounding boxes of non-passable entities are displayed with blue wireframes.

diag_frame can be used to log up to 10 variables every frame.

trace_hit is now also supported by c_trace in AABB mode.

New shader variables: vecColor, fAlpha, fAlbedo, fAmbient, fPower, vecSunPos.

The NOSHADER flag suppresses shaders in a view.

The VIEW object now supports a seventh clip plane additionally to the six frustrum clip planes. This plane can be used for mirror and water effects. It is activated by setting the view.portalclip flag (moved from experimental to production state).

sys_record / sys_replay records the user input by keyboard, mouse or joystick into a file, for debugging purposes or for recording a demo (moved from experimental to production state).

WED Project Window was restructured a little to make the WED user interface more straightforward.

The Albedo value in WED Entity Properties is now copied into the entity albedo and alpha parameters for controlling a transparent entities' opacity without needing a script.

Material events are now also run by static entities. Previously, an entity required an attached action for running its material event.

bmap_for_entity can now also return the textures from a map entity.

bmap_fill can be used to fill a bmap to a certain color.

window_pos gives the current position of the engine window.

video_window can now hide the engine window.

The DirectX mesh animation bug could be worked around by applying a command sequence that flushed the mesh cache whenever a mesh was changed. This method worked on all of our test machines. Therefore, the u/v or patch workarounds should not be required anymore.

bmap_blit was moved from experimental to production state and modified so that the bitmap can now be scaled.

Shaders can now share common functions and variable declarations through #include statements.

The transformed view positions of lights are now available for shaders. Lights are sorted at the beginning of the light array for activating more lights in 1.1 vertex shader models. The sorting can be prevented by setting compatibility (default = 4) at 3 or below.

Panels can now be rotated by panel.angle about panel.center.

d3d_texdepth can now be used to render PCX and BMP sprites and bmaps in 24 bit color depth, rather than 16 bit.

proc_status can be used to check the status of a function.

The level_free function partially releases the nexus.

pan_setbmap can be used to change the bitmaps of panel elements.

A new SED is contained, with the following improvements:

- Test Run (Ctrl-F5, black triangle button). The Test Run just executes acknex.exe and passes command line parameters, just like the old SED prior to 1.3, without any debugging. Fatal engine crashes won't terminate SED, and the SED cursor won't override the engine cursor.
- Debugging of lite-C variables (pure mode only).
- Fixed issues with loading toolbars, spaces in path to WED/MED, and line numbers that appeared clipped.
- Only save modified files before running the engine.
- Small menu text changes: 'Configuration' is renamed to 'Preferences' and the 'Low Color' Parameter is removed.
- Stored breakpoints (when opening a SED project) are now sent to the engine.
- File->Publish runs WED to publish.
- Manually entered command line parameters are no longer erased.
- Collapsed lines do not get removed when using backspace.

New WED and MED versions with the following improvements:

- Better 'snap' for moving selections in WED.
- MED supports the MouseWheel for Zoom.
- MED allows to temporarily interrupt a mouse edit mode (e.g. Move) by pressing [Alt] for activating the camera move funktion; after releasing [Alt] the original edit mode is retored.

A new manual chapter "The Culling Process" was added, with a brief culling introduction for newbies.

The new GXL2DX9.DLL and GXL2DX9A.DLL render libraries implement DX9 for WED and MED and contain several small improvements over the DX8 libraries, for instance easier clicking on very small vertices. GXL2DX9.DLL uses several DX9 devices for the windoes, GXL2DX9A.DLL used only one device.

A new GXL2Bas32.DLL render library contains a non-DirectX renderer WED and MED. It is fully compatible to the GXL2DX9A.DLL, but does not support textured or solid polygons. The source code for the library is available.

Acknex.dll was updated to the DirectX 9 version of April 2006. The new DirectX functions are contained in a d3dx9_30.dll. This DLL is contained in the Gamestudio folder.

Version 6.40 compatibility notes

Version 6.40 is NOT 100% code compatible to its predecessor. Below you'll find a list of all differences that could require manual adaption of a project to 6.40.

New features implemented in V6.40.5

max_nexus gives the allocated size of the nexus in KB.

Updated templates add climbing, swimming, traps, and other features.

bmap_remove removes a created bmap.

layer_sort places a layered element - a panel, text, view, or a view or sky entity - on a different layer.

file_seek returns the position of the file read/write pointer when mode is 4.

c_rotate got an USE_AXISR mode for rotating the angle parameter about the entity axis.

str_remove removes a string created by str_create.

New features implemented in V6.40.4

ent_mesh returns the entity mesh for using in higher languages.

path_name can be used to find the path of an entity, image, or sound file opened by a create function.

c_trace got a USE_POLYGON mode for deciding whether to use an oriented box or the mesh of the first frame for the target entities (see also collision).

c_move and c_trace are now able to detect water entities in OBB mode.

The previous exit function was renamed to sys_exit (not game_exit).

The LOD of dynamic shadows can be adjusted by shadow_lod.

Warning 1108 is now only issued when warn_level is at 2 or above.

MED can now save and load keyboard shortcuts (like WED).

The WMP / $$M file format is better documented, and an advanced section was added to the collision documentation.

New features implemented in V6.40.1

Terrain is automatically nonchunked if its file name ends with "_n" or if the second-last letter is a '_'. This is useful for water surfaces that must be nonchunked in order to apply water physics.

New features implemented in V6.40.0

Terrain resolution can now automatically be changed in MED.

ptr_first returns the first engine object of a certain type.

proc_kill can now be used to prematurely terminate all functions.

The ent_mtlset function can be used to manipulate skin materials and effects in real time.

The strings parameter of a text object is now calculated automatically when omitted.

A variable array can now be used as effect matrix through mat_effect and matEffect.

New functions: str_create, txt_create.

The user_name string can be used by engine extension developers to customize their product to a certain user.

The Local, Cast, and Polygon flags can now also be set in WED Entity Properties.

Entity-Entity Collisions now use an oriented bounding box (OBB) instead of an ellipsoid. This ensures better collision behavior when both entities are moving.

New function: client_drop

Undefined string pointers in texts are now automatically initialized to empty variable strings.

New function: bmap_createblack.

New view flag: NOFLAG1

New entity flag: clipped.

New command line option -nwnd.

bmap_to_format converts a render target bmap to a standard bmap in any color depth.

New render event: render_solid.

WED starter/publish/resource was replaced by a publish panel which allows to select the EXE. User-created EXE files can now use the engine library under an Open Source license to replace acknex.exe. Note that the angular brackets that determined which files are to be distributed are no more.

Objects can now be moved, rotated, and scaled in WED and MED by dragging arrows.

WED 'Add Script' was replaced by a Project Manager that comfortably allows to edit template projects.

New engine variable: patch.

New engine function: file_seek.

add_buffer now requires a size parameter.

Find Object can now also be used to find untextured blocks.

The CULL_CW view flag can be used for changing the global culling.

MED 6.65 can now interpolate bones and vertex animation between frames.

d3d_shadowdepth can be used to compress all shadow maps to 4 bit per pixel.

enable_polycollision can now be used to switch globally between the old (AABB) and new (ellipsoid) collision system. The USE_AABB collision mode is for individual selection the old or new system for collision functions. c_content must now always be called with a second parameter (c_content for the new collision system is not implemented yet). The old collision instructions ent_move, trace, and content are abandoned and will be removed from the documenation.

c_rotate can now rotate about arbitrary axes and can use the AABB collision system.

The FILTER flag was now implemented for texts also.

MED can now convert Bones animation to Vertex animation.

The DirectSound interface was switched back to DirectX 7. Reason: DirectX 8 mono sound buffers tend to crash when playing stereo sounds.

The enable_tree material event can be used to change entity parameters dependent on the current view.

Huge Terrain is now supported by automatically splitting terrain into a stream of separate chunks. The chunk size is controlled by the terrain_chunk variable (default: 32x32). Chunked terrain has to be saved with the new MED in HMP5 format, otherwise the normals will be wrong along the chunk seams.

Entities are now also hidden in the view if the view.genius is assigned to their parent pointer and the camera is inside the genius' bounds. This way, many attachments to the player can be automatically hidden.

c_scan was implemented to replace scan_entity.

The engine standard font can now be given by '*' in Digit elements.

The following A4 keywords are not recognized anymore by the engine: SYNONYM, SWITCH_VIDEO, CREATE, MORPH, ROTATE, REMOVE, PLAY_SOUND, PLAY_LOOP, STOP_SOUND, PLAY_ENTSOUND, TUNE_SOUND, SHOOT, TOUCH, SEND, NOP.

engine_open() / engine_close() can now be called multiple times by external applications.

add_buffer can now remove a named buffer by passing the NULL pointer.

The session_connect function now automatically waits until a connection is established. Therefore, it's now never necessary anymore to wait until connection is established, thus eliminating a frequent source of beginner's errors.

For temporarily playing large sound files when media_play can not be used (for instance because the sound files have to be stored in a resource file), a snd_remove function was implemented.

effect_cpy copies an effect from one material to another.

Models can now be previewed in MED's Engine Preview.

Model Skins can now get separate material colors and effects in order to define the reflection behavior, a shader, or a rendering technique for particular model parts. Skins can have only a color and no texture, thus saving video memory for monochrome models.

A6 Templates: WalkThru Project - simple project that adds the PlBiped action and a first person camera view.
plBipedWeap00.wdl - added Armor Pickup. Works like Health Pickup, but increases armor. Added "Pickup Sound" to Health, Armor, Weapon, & Ammo pickups. You can change the sound and the volume in the Customization panel. Fixed Health Pack Pickup when Player Health is Maxed. The player no longer picks up the health or armor packs if they are already maxed out.
AIFPS01.wdl
- Fixed Damage with armor. When an entity with armor takes more damage then the armor has, the remaining damage goes directly to health (armor no longer goes negative).
cutscene00.wdl
- added checks for cutscenes 2-5.
bipedAnim01.wdl
Added a new special case for once off animations. Once off animations can now override all other animations (e.g. they must finish a complete cycle before returning control to other animations). This is used for "attack" animations (since the actual attack mode has a much shorter duration then the animation). Only works for time-based animations.
AIFPS01_Fire - now fires at player not just along the AI's rotation. This makes the AI more accurate but you need to make sure the AI is facing the player before calling this function (otherwise it looks funny).
AIFPS01_Hover - a "hovering" AI that behaves similar to the normal AI but it floats at the height it is created at. When it dies, it spins to the ground and explodes.
WeapLaunch00_Anim_Explode - uses value in "temp" instead of "you._shell_radius__030" for the blast radius. So now you can call this function if you want anything to explode. Added Explosion Sound entry to WeaponFX00 Moved "Launch00_Anim_Explode" to "WeaponFX00_Anim_Explode" Added "Explode" flag to AIFPS01_Guard and AIFPS01_Hover. If set, entity will explode on death rather then show death animation.

Models now support multiple textures, which can be assigned to parts of the mesh through the Skin Manager. X models with multiple textures can be imported.

Multithreading was re-implemented in the Map Compiler.

Models and Terrains can now have skin textures in external files.

Mesh skin coordinates can now be directly changed by the vec_for_uv function.

A Drop Down Box was implemented in the Script Customize Panel.

WED Create Script: In addition to A6 Template Project and A5 Template Project you can select Shooter Project as one of your starting scripts. Shooter Project comes with all the scripts commonly used in a First Person Shooter (plBiped01, aiFPS01, camera1stPerson01, etc.). This will save you time since you no longer have to add all the scripts individually.

A6 Templates: Lift01.wdl - a new skill "Key" has been added in the Activate section of the Lift01_Basic entity. If a value is entered greater than zero, the trigger with the same value must be set before this lift can be activated.
aiFPS01.wdl
- added Armor "spark" effect. Like the "blood spray" effect that happens when an AI takes health damage, now when the AI takes armor damage sparks appear. Added "Gore" section for turning off sparks and blood effects.

A material and two text strings can be assigned to entities under WED Entity Properties.

A movie file name can be passed to the A6 engine at startup, letting the engine act as a movie player.

diag_var() writes a variable into the acklog.txt, controlled by a C-style format string.This instruction can be used for logging fast-changing variables.

panel.flags got a FILTER flag for blurring scaled panels. The background bitmap can now be colored. Panels can now be sized and drawn with a monochrome background rather than an image.

Some adaptions to the upcoming lite-C: Functions are now automatically started when their name ends with ..._startup, exit() was renamed to game_exit(), and flags in object definitions can now be separated by " + " or " | " characters.

master_vol can be used for setting the sound mixer volume

cycle(x,a,b) now also works for x > 2b.

entity.near and d3d_near are re-implemented in A6 for reducing the clipping distance of a model or sprite entity,

d3d_transform is now always activated, even with old 3D cards. The A5 renderer was abandoned.

MED Transform Vertices Tool and Background Image Tool are now documented.

WED now uses the same position and angle system as the engine: entity z positions now correspond to their origin and not to their lowest point, and pan angles are 0 in X direction and increase counterclockwise. Please note: When saving a WMP file in the new format the first time, positions and angles are automatically corrected. Make sure that the WMP sources for all WMB entities exist (the shapes of WMB entities must be visible). Otherwise their z positions are not automatically corrected and must be adjusted manually.

WED Add Texture : DDS images can now also be used for textures in WAD files and folders.

WED Entity Properties: Materials can now be directly assigned to entities:

exec() can now also execute batch files.

d3d_texdepth automatically compresses all 16 bit textures to 4 bit per pixel.

Dynamic light positions and colors can be passed to shaders.

WED Customize Script got flag boxes, text sections, and a spinner control.

panel.digits can now use format strings.

The screenshot function was improved.

MED Group Mode: Body parts of a model can now be automatically arranged in groups and individually manipulated:

For MED primitives, the number of faces, size, arrangement of multiple copies and other parameters can now be adjusted in the Primitives Toolbar.

MED Skin Painter now supports and displays true color skins.

MED Subdivide Triangle now uses a different, improved method.

MED Soft Selection / Dynamic Selection Mode: Vertex moving can now be done with a Soft Selection mode. Not only the selected vertex, but also surrounding vertices are moved, depending on their distance to the selected vertex. This way, meshes can be manipulated in a very 'organic' way.

MED Tool Properties Bar : When selecting a tool, the tool properties can be adjusted in the properties bar at the lower edge of the window. For the move tool, the following properties can be adjusted: Snap / Snap distance Soft Selection / Dynamic Selection / Selection Radius Move Distance Cursor Position

MED now also supports DDS skins.

MED Undo : Undo and Redo is now supported for all MED functions.

Bitmaps can now also use DDS, DIB, HDR, JPG, PFM, PNG, and PPM images

ent_createlayer - Remarks: This instruction must be executed before the first level is loaded and before a game score is saved.

Compatibility has now a default value of 3. When set at 2, the '#' character gets a special 'comment' meaning like in the A3 engine.

MED Magnet Tool: MinZ and MaxZ values can now be set in the Magnet Properties panel, thus allowing to create flat areas on the terrain.

MED Scale Tool: Can now be used for changing the size of a terrain.

The A6 engine now consists of 2 modules: acknex.exe and acknex.dll. Both are located in the Gamestudio folder. The bin folder does not exist anymore. The acknex.exe source code can be found in the sdk_engine folder of the beta version.

Version 6.31 compatibility notes

Version 6.31 supports DirectX 9.0c, and thus requires updating of DirectX 8 target systems to the newest DirectX version. A DirectX 9 redistributable can be downloaded from the Download Page.

Version 6.22 compatibility notes

Version 6.22 is 100% compatible to its predecessor.

New features implemented in V6.31.4

DirectX 9.0c Interface
   The DirectX interface was changed to DirectX 9.0c. This version won't
   run anymore on machines with a prior DirectX version. Please note that
   there are 3 DirectX9 versions - 9.0a, 9.0b, and 9.0c - that are
   mutually incompatible. DirectX 9.0c is the most common one because it
   comes with the Service Pack 2 for Windows XP. You can use the DxDiag
   tool for checking which DirectX version is installed on your PC.
   Please download a redistributable DirectX 9.0c setup for you and
   your customers from http://server.conitec.net/down/directx9_redist.zip.
DirectX9 color depth
   The color depth in window and fullscreen mode is now inherited from
   the desktop resolution.
DirectX9 mirrors
   Clipping planes under DX9 are extremely slow with nVidia drivers, and
   have a great impact on the frame rate. Therefore, camera portal
   clipping is now done by software again (like in A5).
DirectX9 effects
   Effects now use the DX9 samplers additionally to texture and render
   stage states. For details refer to the DirectX 9 documentation.
   Recommended books:
- Kris Gray, "DirectX 9 Programmable Graphics Pipeline".
   - Wolfgang Engels, "ShaderX 2".
   - Randima Fernando et al., "GPU Gems"
DirectX9 vertex format
   The vertex format was changed for DX9. All geometry and model vertices
   got a 3rd coordinate set for shader tangents, and have now the
   following format:
struct VERTEX_TLSHADED {
   D3DXVECTOR3 v;
   D3DXVECTOR3 n;
   float tu1,tv1; // coordinate set 1, for texture or shadow map
   float tu2,tv2; // coordinate set 2, for texture or detail map
   float tu3,tv3,tw3; // coordinate set 3, for tangent or other purposes
   };
DirectX9 shaders
   Shader code now supports the HLSL (aka Cg) language. It's a C based
   language just like C-Script, and should make shader programming much
   easier for C-Script programmers.
Example for an HLSL shader:
float4x4 matWorldViewProj : WORLDVIEWPROJ;
   float4 vecTime;
void vs_flicker_red(
   in float4 iPos : POSITION,
   in float2 iTex0 : TEXCOORD0,
   in float2 iTex1 : TEXCOORD1,
   out float4 oPos : POSITION,
   out float4 oDiffuse: COLOR0,
   out float2 oTex0 : TEXCOORD0,
   out float2 oTex1 : TEXCOORD1)
   {
   oPos = mul(iPos,matWorldViewProj);
   oTex0 = iTex0;
   oTex1 = iTex1;
   oDiffuse.r = fmod(vecTime.w * 0.1,1.0);
   oDiffuse.g = 0.0;
   oDiffuse.b = 0.0;
   oDiffuse.a = 1.0;
   }
technique flicker
   {
   pass p0
   {
   VertexShader = compile vs_1_1 vs_flicker_red();
   PixelShader = NULL;
   }
   }
Note that DX8 vertex shaders require a small modification for running
   under DirectX 9. The following declaration:
decl
   {
   stream 0;
   float v0[3]; //position
   float v3[3]; //normal
   float v7[3]; //uv 1
   float v8[3]; //uv 2
   }
has to be replaced by a DX9 declaration:
dcl_position v0
   dcl_normal v3
   dcl_texcoord0 v7
   dcl_texcoord1 v8
Due to the changed vertex format, further modifications might be
   necessary. Texture coordinates have now only two components, and
   tangent space uses the 3rd coordinate set. The DX9 shader compiler is
   a lot more sensitive than it's DX8 counterpart, and does not tolerate
   syntax errors anymore. All shader variables and keywords are now case
   sensitive. Reading from uninitialized registers will be detected and
   produce error messages. Errors in most shaders posted on the shader
   forum have to be fixed before they will run under DX9.
 
material.tanget
   now calculates the tangents for the 3rd texture coordinate set. This
   way tangents can now also be used for level geometry shaders.
material.effect
   Instead of an effect string, a .fx file name can be given. In that case
   the effect is read from the file. Example:
effect = <shadertest.fx>;
d3d_shaderversion
   gives the vertex and pixel shader version as a 4 digit number.
   Remarks:
   Usual 3D cards deliver 0, 1113, 1114, 2020, or 3030.
   Example:
   // set a material for vertex shader 1.1 and pixel shader 1.4
   if (d3d_shaderversion >= 1114) my.material = mtl_shader;
 
max_entities
   Remarks:
   Must be set before level loading. For every entity, around 1.5..2.5 KB
   memory is reserved from the nexus, dependent on its bones size.
time_level
   Time in ms/frame consumed by level rendering.
time_sky
   Time in ms/frame consumed by sky rendering.
time_entities
   Time in ms/frame consumed by entity rendering.
time_effects
   Time in ms/frame consumed by particle rendering.
time_portals
   Time in ms/frame consumed by portal/mirror rendering.
time_panels
   Time in ms/frame consumed by panel rendering.
time_update
   Time in ms/frame consumed by screen refresh.
time_actions
   Time in ms/frame consumed by script execution.
time_pfuncs
   Time in ms/frame consumed by particle functions.
time_client
   Time in ms/frame consumed by sound and movie rendering.
time_server
   Time in ms/frame consumed by entity updates and multiplayer
   communication.
time_idle
   Idle time in ms/frame for not exceeding fps_max.
Remarks:
   The time_ variables are valid for the topmost view. They are only
   available in the development version, not in the release version.
   See also:
   time_physics.
[F11] panel
   displays in the "ms" column the following variables:
   time_level+time_sky, time_entities, time_effects, time_panels,
   time_update, time_client+time_server+time_idle, time_actions+time_pfuncs,
   time_physics.
shadow_stencil
   Remarks:
   - Stencil shadows can only be cast by visible entities. When an
   entity is invisible, but casts a shadow, a 'ghost' image remains.
 
bmap_preload
   Returns:
   Pointer to the Direct3DTexture8 used by the bmap. This texture can be
   manipulated by DirectX functions.
 
ang_for_bone(ANGLE*,ENTITY*,STRING*)
   calculates the current euler angle of a bone. This can be used
   to attach weapons or other equipment to a certain bone of an actor.
   Parameters:
   ANGLE* - to be set to the hinge angle.
   ENTITY* - model entity pointer.
   STRING* - bone name.
   Modifies:
   ANGLE*
   Example:
   action attach_gun_to_actor
   {
   you = ent_create("gun.mdl",0,NULL); // create a gun for the actor
   var anim_percent = 0;
   while(1) {
   anim_percent += time;
   ent_animate(me,"walk",anim_percent,ANM_CYCLE); // animate the actor
   vec_for_bone(your.x,my,"RightHand"); // place gun at hand position
   ang_for_bone(your.pan,my,"RightHand"); // rotate gun by hand angle
   wait(1);
   }
   }
   See also:
   vec_for_bone
 
game_save()
   SV_PHYSICS - save all physics properties (not included in SV_ALL).
 
entity.dynamic
   Tells wether an entity is dynamic - i.e. it can change its position or
   properties during gameplay - or static.
   Remarks:
   Entities placed in a level are dynamic if an action is assigned.
   Entities created by ent_create are always dynamic. Static entities are
   faster than dynamic entities, so if an entities does not move anymore,
   this flag can be reset for improving the frame rate.
 
pan_remove(PANEL*)
   removes a panel. All bitmaps used exclusively by this panel will be
   removed also. Afterwards the panel pointer becomes invalid.
   Parameters:
   PANEL* - panel to be removed.
   Speed:
   Slow.
   Example:
   pan_remove(splashscreen);
 
long GetMessage(UINT message, WPARAM w_param, LPARAM l_param)
   Remarks:
   If a nonzero value is returned, the message is ignored by the engine's
   own message handler.
 
WED improvements
   - WAD files and textures are now stored with a path relative to the
   work folder.
   - On assigning a new action to an entity, previous skills and flags
   are only reset when they have default values in the new action.
   - The distributable editor WEDS can now also place entities that are
   not included in the game resource.
TGA WADs
   In previous WED beta versions TGA textures were stored with wrong
   colors. Remove your TGA textures and add them anew to the WAD.
 

New features implemented in V6.30.0

WED & MED =============================================================
WED command line options
   The publish and resource functions of WED can now also be called by a
   command line:
WED -p name.wdl
   Executes the Publish function. The script name.wdl must exist in the
   current folder.
WED -r name.wdl
   Executes the Resource function (Pro Edition only). The script name.wdl
   must exist in the current folder.
 
WED Sky textures (-> Map Design / Textures)
   A texture with a name beginning with "SKY" can be assigned to the sky
   box around the level. The texture proportions determine the kind of sky
   mapping. If it's width is six times it's height, the texture is used
   for a sky cube around the level. If it's width is twice it's height,
   it's first half is used for a sky dome and it's second half is used
   for a cloud dome.
   For displaying the sky cube in the 3D window, activate 'Sky Cube' in
   Preferences -> Advanced.
WED Automatic assignment of actions
   If an entity is placed into a level, it's automatically assigned an
   action of the same name (without extension) if it exists in the
   script. For instance, on placing 'guard.mdl' the action 'guard' is
   automatically assigned.
WED Customize dialog
   The following features were implemented:
   - Click on the [?] icon in the upper right corner of the dialog. Then
   click on the text of one of the 'tags' in the dialog. If that tag has
   a "help" text it will be displayed in a pop-up window.
   - The [Restore] button allows you to reload a script with the
   original values. Click on [Restore] and then select the original
   script in the template_6/code folder.
   - The [Update Script] button allows you to update your script to a
   new version without losing any changes you made to values. This will
   become more important as updates to the template scripts are
   released. Click on [Update] and then select the script in the
   template_6/code folder.
 
WED Behavior panel
   When right clicking an entity and selecting 'Behavior', a panel pops
   up that allows to customize the entities' behavior according to
   the action assigned.
As long as there is no action assigned, the Behavior panel offers an
   action list for choosing an action, just like
   Properties->Behavior->Choose Action.
If an action is assigned, you can customize the first 20 skills and 8
   flags of the entity according to comment tags in the action.
WED Preferences
   Sky Cube - display six sided sky cubes
WED Mirror Button
   The mirror button mirrors an object about the axes given by the
   movement restriction button.
WED Texture bookmarks
   The texture bookmarks are now saved along with the view in the views
   list. This way, several sets of texture bookmarks can be stored. The
   bookmarks are now available in the Textures list.
WED Preview
   Prefabs and entities can now be selected in a preview dialog.
WED 3D view
   The textures of Terrains and Sprites are visible in the 3D view.
   Models are rendered as solid monochrome objects. Selected objects
   are not full red, but reddish, so their textures are still visible.
   For displaying object textures, the GXL2DX8A must be selected for the
   3D view.
WED Light/Sound ranges
   When selecting a light or sound source, it's range is now indicated
   by a circle in the 2D views.
WED: New Texture properties
   Surface textures can now be automatically aligned with the following
   buttons in Properties->Surface:
[Reset] - resets the texture
   [L] - Texture left align
   [R] - Texture right align
   [F] - Fit Texture
   [T] - Texture top align
   [B] - Texture bottom align
   [C] - Center Texture
WED: Customize Script
   The following features/fixes have been added to the script
   customization dialog box:
Improved help feature. Click on the "?" icon in the upper right
   corner of the dialog. Then click on the text of one of the 'tags' in
   the dialog. If that tag has a "help" text it will be displayed in a
   pop-up window.
Improved float/int handling. The previous version of WDLV had a bug
   that converted whole numbered floats into integers.
Restore Button. The "Restore" button allows you to reload a script
   with the original values. Click on restore and then find the original
   script in the template_6/code folder.
Update Script Button. The "Update Script" button allows you to update
   your script to a new version without losing any changes you made to
   values. This will become more important as I release updates to the
   template script. It works the same way as the "Restore Button" does
   above.
WED 24 bit textures
   Textures in TGA format are saved with 24 bit color depth in the WMB
   file.
WED Camera Move
   The [Camera Move] Button rotates the camera with left mouse button
   pressed, and moves it with the right mouse button pressed. This is
   a movement similar to Worldcraft.
WED Select Box
   A select box is now also generated in Move, Scale, or Rotate mode when
   no object is at the clicked position.
WED Right click menu
   The [Add] functions in the right click menu are now collected in a
   separate menu.
WED Walk Speed
   ..is now configurable up to 256 unites/sec in Preferences.
WED Light ranges
   ..can now be controlled with the Scale mode.
WED Resources Panel
   ..displays the actions among the other level resources.
WED Find Object
   An object name can be entered alternatively to the object number.
WED Add Script
   Template scripts can be added multiple times to the same game. A
   multiple script ends with "_" (like "movie_.wdl"). On adding such a
   script, WED appends a number on copying it into the game folder (like
 "movie_1.wdl", "movie_2.wdl" etc). Within the script, "%_%" sections
   within variable or object names are replaced by the script copy number.
   This way, a script can be added several times, and every copy can have
   individual variable and object names.
WED Attaching Entities to paths
   Entities can now be attached to a path by WED. In the Entity Properties
   panel, click on the folder icon next to the path field, and select a
   path from the dropdown list. (You can also attach positions and other
   entities, but this has no effect yet in the script).
WED New path editor
   Only paths in the level can be used - map entities must not contain
   paths. The gxl2dx8a.dll is required for path editing.
After selecting a path, enter the Vertex Move Mode for editing nodes
   and edges. The direction of every edge is indicated by a little arrow.
Select a node by clicking on it. The node is highlighted in red. You
   can drag it around with the mouse. Clicking at another place in the
   window creates a new node and draws an edge from the last node to the
   new one.
[Del] removes the selected node and all its edges.
For connecting two nodes with an edge, either click on the first node,
   drag the 'rubber band' with pressed [Ctrl] and left mouse key to the
   second node, and drop it there. Or click with [Ctrl] pressed on a node
   to draw an edge from the previously selected node to this one. Each
   node can have an arbitrary number of edges to other nodes.
Touching an edge with the mouse highlights that edge. Left clicking
   anywhere on an edge splits the edge by inserting a new node.
[Undo] cancels the last operation.
Right clicking a node opens a node properties panel for setting the 6
   node skills. They can be used in C-Script for triggering path events.
Right clicking an edge opens an edge properties panel for setting the
   edge direction, bezier factor (not used yet), weight, and skill.
 
WED engine options window
   The checkboxes were removed. The whole engine command line is now
   displayed.
WED Lock Selection Button
   MED Lock Selection Button
   Locks the current selection unless menu functions like 'Select All',
   'Select None', 'Select Inverse' are performed.
WED Texture Lock
   .. now works not only when moving, but also when rotating blocks.
MED Converting Models to terrains
   A model can now be saved in terrain HMP format if it consists of a
   regular mesh.
MED Meshtester plug-in
   Checks whether a mesh is closed as required for stencil shadows. If not,
   the vertices adjoining holes in the mesh are selected.
MED Frames Toolbar/Auto Scene Range Button
   Toggles between frame and scene mode. In scene mode, an animation scene
   is composed from all frames beginning with the same name (i.e.
 "walk1"..."walk4"). The [<<] and [>>] buttons in the animate bar jump
   to the previous or next scene. The scroll bar only affects the current
   scene. The blue number field gives the number of frames belonging to the
   current scene. By editing this field and pressing [Return], frames can
   be deleted or appended from the end of the scene. Editing the frame
   name can possibly create a new scene.
MED 3D Window
   The camera can be moved by pressing the left and right mouse button
   simultaneously.
MED .X import
   The .X import dialogue now has a [Transform] button that allows
   swapping or mirroring arbitrary axes. By default the Y and Z axes
   are swapped on importing a .X model.
WED and MED preferences
   Some WED and MED options can be controlled by settings in
   data\options.scr. Comments in the file are preceded by ';'. The
   following entries are set by default:
--------------------------------------------------------
   ;output formats - don't change this
   WED2FORMAT = on
   TEXTUREVECS = on
   WRS2 = on
;export mipmaps with textures
   EXPORTMIPS = off
   ;generate texture name file when saving WAD
   WRITEWADTEXT = off
;project window buttons on top
   PV_TCS_TOP = on
   ;scrollbar width
   TV_SBSIZE = 7
   ;have a views list
   VIEWS_LIST = on
   ;sort textures in display
   SORT_TEXTURES = on
;save GXL state, view positions, toolbar positions
   SAVE_GXLCFG = on
   SAVE_FRAMESTATE = on
   SAVE_TBSTATE = on
;undo levels 1..16
   UNDO_LEVELS = 16
;mouse click on overlapping objects selects same type first
   SELMODE = 1
;prefabs & entity preview
   USEPREVIEW = on
;options for map compiler
   MCOPTIONS = "-solidsky -b -v -l -g"
   USEWEDBUILDDLG = off
;default template folder
   WDLTEMPLATEDIR = "template_6"
   TEMPLATE_DIR = "template_6\code"
;programs to open file types in the resource window
   DEFAULTEXEC "wdl" "sed.exe" "%1"
   DEFAULTEXEC "mdl" "med.exe" "%1"
;help menu links
   CONTENTS = "3dgs_manual.chm"
   UPDATES = "http://www.3dgamestudio.net/a4update.htm"
   COMMUNITY = "http://www.conitecserver.net/ubbthreads/ubbthreads.php?Cat="
;drag-duplication button
   CTRLDRAGFORDUP = off
   SHIFTDRAGFORDUP = on
;Camera Move Setup:
   ; CAMERAMOVE_LB = left mouse button [definition for 3d views] [definition for 2d views]
   ; CAMERAMOVE_L&RB = both mouse buttons [definition for 3d views] [definition for 2d views]
   ; CAMERAMOVE_RB = right mouse button [definition for 3d views] [definition for 2d views]
   ;definitions for CAMERAMOVE_LB, CAMERAMOVE_LRB und CAMERAMOVE_RB:
   ; RLPH - [R]otate [L]ookAt [P]oint, controlled by horizontal mouse movement
   ; RLPV - [R]otate [L]ookAt [P]oint, controlled by vertical mouse movement
   ; RCPH - [R]otate [C]amera [P]oint, controlled by horizontal mouse movement
   ; RCPV - [R]otate [C]amera [P]oint, controlled by vertical mouse movement
   ; MCXZH - [M]ove [C]amera [XZ]Plane, controlled by horizontal mouse movement
   ; MCXZV - [M]ove [C]amera [XZ]Plane, controlled by vertical mouse movement
   ; MCXYH - (3D View) [M]ove [C]amera [XY]Plane, controlled by horizontal mouse movement
   ; MCXYV - (3D View) [M]ove [C]amera [XY]Plane, controlled by vertical mouse movement
   ; ZVH - [Z]oom [V]iew, controlled by horizontal mouse movement
   ; ZVV - [Z]oom [V]iew, controlled by vertical mouse movement
   ; NULL - no function
   CAMERAMOVE_LB = [RLPH RLPV] [MCXZH MCXZV]
   CAMERAMOVE_LRB = [MCXYH MCXYV] [ZVH ZVV]
   CAMERAMOVE_RB = [MCXZH MCXZV] [MCXZH MCXZV]
;Path definition for Add Sprite, Terrain, Model, Map, or Prefab.
   ; Argument can be a full path name (relative path names are not supported):
   ; "c:\abc\def"
   ; or a macro
   ; "%TEMPLATES%" - the WDLTEMPLATEDIR given above
   ; "%WDLPATH%" - for the PATH given in the script
   ; "%WORK%" - for the current WORK folder (default)
   ; Several definitions may be made
   SPRITES_DIR = "%work%"
   SPRITES_DIR = "%wdlpath%"
   MDLS_DIR = "%wdlpath%"
   MDLS_DIR = "%work%"
   TERRAINS_DIR = "%wdlpath%"
   TERRAINS_DIR = "%work%"
   WMBS_DIR = "%wdlpath%"
   WMBS_DIR = "%work%"
   ;PREFABS_DIR = "%work%"
   --------------------------------------------------------
 
Map Compiler: Merge Across Leafs
   Re-merges polygons that were split by the BSP tree process. Reduces the
   number of polygons and vertices, and the WMB size; can increase the
   frame rate by up to 10%. Also removes the shadow seams that can be
   visible under some circumstances. NOTE: This option requires the
   floor_trace variable set at 2 for using the new collision detection,
   and using c_trace instead of trace for the SCAN_TEXTURE option.
Map Compiler: Tessellate options
   Controls the size of the polygon squares generated by the automatic
   tessellation process, in pixels. By default, shaded surfaces are
   Tessellated when they span more than 240 texture pixels, and flat and
   turbulent faces are not Tessellated at all. Reducing the tessellation
   size increases the number of polygons, but also increases the dynamic
   light resolution especially for spotlights.
Map Compiler: Phong jitter distance
   When compiling in light low quality mode, a light sample is taken every
   16 texture pixels. In high quality mode, 4 light samples are taken and
   then averaged into a single light texel. The jitter distance gives the
   offset of these 4 points from the final location. Larger values provide
   better averaging over a large area, while smaller values work better
   for small surfaces and edges. This parameter only influences Smooth
   shading. Flat shading has a fixed jitter setting of 8 and preview mode
   corresponds to a setting of 0.
Map Compiler: map size
   The maximum map size can be increased to up to 250000 units. Note that
   higher than default map sizes can produce more warning messages with
   thin blocks and geometry problems. The z buffers of most 3D cards can
   not deal with huge distances unless camera.clip_near is set to a
   relatively high value. Use this option with caution.
Map Compiler: Cancel
   The map compiler now asks for confirmation if [CANCEL] was clicked
   while compiling. This feature was implemented to honor a user who
   accidentally clicked [CANCEL] after two days of compiling a huge level.
 
SED Panel editor
   Panels can now be edited with a visual editor available through
   plug-ins->PanelEdit.
 
Engine ================================================================
Command line options
   If the engine is started without giving a script or level, it opens
   an empty window. The [TAB] key can then be used for manually entering
   commands.
If the file name of a level, terrain, model, or sprite is given, the
   engine starts as a viewer for that file. Six-sided sprites are
   displayed as sky cubes and two-sided sprites are displayed as sky
   domes.
   Example:
   acknex.exe gorge+6.tga
   runs the engine as a viewer for a sky cube.
If the script name contains a path, the engine changes its work
   directory to the script folder. This allows starting the engine by
   double clicking a script from an arbitrary work folder.
-ns command line option
   Prevents playing CDs and sounds, and does not initialize the
   DirectSound device. No sound files will be loaded.
-sim command line option (Pro edition, development engine only)
   Activates the NETWORKSIMULATOR_DP8SP_TCPIP service provider, and offers
   an interface to the DirectPlay simulator that comes with the DirectX9
   SDK. DirectX 9 must be installed. Run the program 'DP8Simul.exe' before
   starting a multiplayer session. A panel will open for setting values
   for latency and packet loss. This allows to simulate bad online
   connections, like from a 56K modem, and test a multiplayer
   application under real internet conditions.
   The simulator can also be used for testing clients and servers running
   on the same PC. Note that then the simulator generates bandwidth,
   latency and packet drop values that are much worse than the values
   indicated in the simulator panel, because every packet and every
   acknowledge message runs twice through the simulator. The real
   simulated latency is indicated in the first row of the Net column of
   the statistics panel.
[Ctrl-F11] (development engine only)
   Activates a map view that displays the player's surroundings for easier
   finding a certain place in the level.
 
C-Script instructions =================================================
port_in (var port);
   port_out (var port,var data);
   Writes or reads data from an internal I/O port.
   Parameters:
   port - address of the I/O port, 0..4096.
   data - byte to be written to the port, 0..255.
   Returns:
   Data to be written to or read from the port, or -1 if the instruction
   failed.
   Edition:
   C P
   Remarks:
   - The development of these instructions was sponsored by Hartford Hospital.
   - The instructions require the ackport.dll plug-in. Take care to copy it
   in the work folder of the release version.
   - Use port I/O with caution. Writing wrong data to the wrong port can
   erase your hard disk and destroy your PC. This is not a joke.
 
vec_for_angle(VECTOR*,ANGLE*)
   creates a unity vector pointing into the direction given by the angle.
   Returns:
   VECTOR*
   Algorithm:
   VECTOR.x = cos(ANGLE.pan)*cos(ANGLE.tilt);
   VECTOR.y = sin(ANGLE.pan)*cos(ANGLE.tilt);
   VECTOR.z = cos(ANGLE.tilt);
 
bmap_load(BMAP*,STRING name,var mode)
   loads a bitmap from a file during gameplay.
   Parameters:
   BMAP* - bitmap pointer
   name - file name with .jpg, .png, .bmp, .tga, .dds, or .dib extension.
   mode - 0 = clip to old bmap size, 1 = change bmap size.
   Remarks:
   The file must exist in the game folder. It can not be directly read
   from a resource or from the folder path.
   The original image can be restored by bmap_purge().
   If mode is set at 0, the bmap size is unchanged. If the image file
   has a different size, parts of the image are clipped away or filled
   with black.
   If mode is set at 1, the bmap must be a power of two in size.
   Example:
   bmap_load(bmap_for_entity(player,0),"newskin.jpg",0);
 
pan_create(STRING* content,var layer)
   creates an unnamed panel.
   Parameters:
   content - panel definition, or NULL.
   layer - the layer of the panel.
   Returns:
   Pointer to the panel.
   Remarks:
   The panel definition is the same as in C-Script after the leading
   bracket.
   Example:
   Splash = pan_create("bmap = splash.pcx;",1);
view_create(var layer)
   creates an unnamed view.
   Parameters:
   layer - the layer of the view.
   Returns:
   Pointer to the view.
mtl_create()
   creates a material.
   Returns:
   Pointer to the material.
bmap_create(STRING* filename)
   Defines a nameless bmap at runtime.
   Returns: Pointer to the bmap, or NULL if the file could not be opened.
snd_create(STRING* filename)
   Defines a nameless sound at runtime.
   Returns: Pointer to the sound, or NULL if the file could not be opened.
ent_createlayer(STRING* filename,var flags,var layer)
   creates a layered view or sky entity at runtime.
   Returns:
   Pointer to the entity.
   Parameters:
   filename: the texture or model of the entity.
   flags: a combination of the following flags:
   SKY - creates a sky entity. Otherwise it's a view entity.
   DOME - 360 degrees half dome texture
   CUBE - six sided cube texture
   CYLINDER - 360 degrees cylinder texture
   SCENE - don't use the z buffer (sky models only)
   layer - determines the rendering order
   Remarks:
   The sky flags are available for the SDK and the future Lite-C compiler
   only. With C-Script, no sky entities can be created this way.
   See also:
   Sky, entity
 
file_save(char* name,void* buffer,long size)
   Opens the file with the given name, writes the buffer content into it,
   and closes the file.
   Returns:
   pointer to the buffer, or NULL if the instruction failed.
   Parameters:
   name - file name
   buffer - pointer to a buffer that contains the file content.
   size - the file size in bytes.
   Remarks:
   - This instruction is intended for external languages and thus uses
   char* and long instead of STRING* and var.
file_load(char* name,void* buffer,long* size)
   Opens the file with the given name, reads it into the buffer, and closes
   the file.
   Returns:
   pointer to the buffer, or NULL if the instruction failed.
   Parameters:
   name - file name
   buffer - pointer to a preallocated buffer, or NULL. If NULL is given,
   a buffer is allocated by the engine through malloc(), and must be freed
   by the application.
   size - pointer to a long variable, set to the file length, or NULL.
   Modifies:
   buffer, size
   Remarks:
   - This instruction is intended for external languages and thus uses
   char* and long* instead of STRING* and var*.
   - The file is looked for first in the named buffers (see add_buffer),
   then in the path and then in the WRS resource path, if any.
   - If the file was found in the named buffers, size is set to 0.
   - If a buffer is preallocated, its size must be given by the size
   pointer. If the size of the file exceeds the size of the buffer,
   nothing is read and NULL is returned.
   See also:
   add_buffer
add_folder(STRING* name);
   add_resource(STRING* name);
   adds a folder path or a resource file, like the PATH and RESOURCE
   statement.
   Remarks:
   Files for the media player, or DLL files can not be loaded from the
   folder or resource path.
add_buffer(char* name,void* buffer)
   Adds a named buffer to the engine file system. If the engine afterwards
   attempts to open a file with the given name, it reads out of the buffer
   rather than loading the file from the hard disk. This allows to add a
   user defined file resource system in an external language.
   Remarks:
   - Files for the media player, or DLL files can not be loaded from a
   named buffer.
   - This instruction is intended for external languages and thus uses
   char* rather than STRING*.
   Example:
   void* pTerrain = file_load("terrain.hmp",NULL,NULL);
   add_buffer("terrain.hmp",pTerrain);
add_struct(void* data,long size)
   Adds a pointer to a memory area to be saved by game_save if SV_STRUCT
   is set.
   Parameters:
   data - pointer to the memory area to be saved.
   size - length of the memory area to be saved, in bytes.
   Remarks:
   - This instruction is intended for external languages and thus uses
   long instead of var. It can be used to mark memory areas or variables
   that should be saved with the game score.
   - The instruction must be called before the first game_save instruction.
   - Up to 1000 memory areas can be marked.
   See also:
   game_save, game_load
game_save()
   SV_STRUCT - save all memory areas marked by add_struct.
   SV_PATH - save all paths changed by path_setnode or path_setedge
   See also:
   add_struct
level_load()
   Not only WMB files, but also HMP and MDL files can now be given for
   loading a level. This way a level can consist of a single terrain or
   model.
 
draw_begin()
   Opens a scene for rendering on the screen by user-defined DirectX
   functions. Calls the DirectX BeginScene function if the scene is not
   already open.
   Returns:
   Pointer to the Direct3D device.
   Remarks:
   Not necessary when rendering by user-defined render or material events.
   Closing the scene is automatically handled by the engine.
draw_line(VECTOR*, COLOR*, var alpha)
   Draw a line to the given XY position with the given color and
   transparency.
   Parameters:
   VECTOR* - the end position of the line. The start position is the
   position of the last draw_line instruction. The Z value must be 0.
   COLOR* - the end color of the line. The start color
   is the color of the last draw_line instruction. If NULL is given, no
   line is drawn, but the position is set for the start of the next line.
   alpha - the end transparency of the line, 0..100.
Example:
   function draw_red_rect(x1,y1,x2,y2) {
   while(1) {
   draw_line(vector(x1,y1,0),NULL,100); // move to first corner
   draw_line(vector(x2,y1,0),vector(0,0,255),100);
   draw_line(vector(x2,y2,0),vector(0,0,255),100);
   draw_line(vector(x1,y2,0),vector(0,0,255),100);
   draw_line(vector(x1,y1,0),vector(0,0,255),100);
   wait(1);
   }
   }
See also:
   draw_text
 
error(STRING*)
   outputs a message box with the given error message.
timer()
   Measures the time between two timer calls in microseconds. Used for
   performance testing of functions and instructions.
   Returns:
   Time since the last timer() call in microseconds (1/100000 sec).
   Remarks:
   This instruction uses the Pentium high-precision performance counter.
   The returned value has a precision of a few nanoseconds, depending
   on the processor clock rate.
   Example:
   ...
   timer();
   c_trace(vec_from,vec_to,mode);
   time_elapsed = timer(); // processor time used for the c_trace call
   ...
 
ent_animate
   ent_bonename
   MED: Entity animation and bones
   Remarks:
   Entity scene and bone names must consist of at least 3 characters.
 
str_for_key
   str_for_entname
   str_for_entfile
   Returns:
   String pointer.
   Remarks:
   If NULL is given for the string pointer, the function returns a
   temporary string that can be passed to an instruction.
str_lwr(STRING*)
   str_upr(STRING*)
   Converts the given string to lower case resp. upper case.
   Returns:
   String pointer.
pan_setpos(panel,var type,var num,vector pos)
   Changes the pos_x and pos_y position of a panel element.
   Parameters:
   panel - panel name or pointer.
   type - the element type:
   1 = digits
   3 = buttons
   4 = sliders
   6 = windows
   num - the number of the element
   pos - a vector containing the element's new pos_x and pos_y values.
   Example:
   // change the position of the fps display in the [F11] debug panel
   pan_setpos(_dbg_pan,1,1,vector(20,30,0));
sys_metrics(var mode)
   returns system information for determining various parameters of the
   current PC configuration.
   Returns:
   System information value.
   Parameters:
   mode - number that determines the system information to be returned.
   The following mode numbers are available:
SM_CXSCREEN 0
   SM_CYSCREEN 1
   SM_CXVSCROLL 2
   SM_CYHSCROLL 3
   SM_CYCAPTION 4
   SM_CXBORDER 5
   SM_CYBORDER 6
   SM_CXDLGFRAME 7
   SM_CYDLGFRAME 8
   SM_CYVTHUMB 9
   SM_CXHTHUMB 10
   SM_CXICON 11
   SM_CYICON 12
   SM_CXCURSOR 13
   SM_CYCURSOR 14
   SM_CYMENU 15
   SM_CXFULLSCREEN 16
   SM_CYFULLSCREEN 17
   SM_CYKANJIWINDOW 18
   SM_MOUSEPRESENT 19
   SM_CYVSCROLL 20
   SM_CXHSCROLL 21
   SM_DEBUG 22
   SM_SWAPBUTTON 23
   SM_CXMIN 28
   SM_CYMIN 29
   SM_CXSIZE 30
   SM_CYSIZE 31
   SM_CXFRAME 32
   SM_CYFRAME 33
   SM_CXMINTRACK 34
   SM_CYMINTRACK 35
   SM_CXDOUBLECLK 36
   SM_CYDOUBLECLK 37
   SM_CXICONSPACING 38
   SM_CYICONSPACING 39
   SM_MENUDROPALIGNMENT 40
   SM_PENWINDOWS 41
   SM_DBCSENABLED 42
   SM_CMOUSEBUTTONS 43
   SM_SECURE 44
   SM_CXEDGE 45
   SM_CYEDGE 46
   SM_CXMINSPACING 47
   SM_CYMINSPACING 48
   SM_CXSMICON 49
   SM_CYSMICON 50
   SM_CYSMCAPTION 51
   SM_CXSMSIZE 52
   SM_CYSMSIZE 53
   SM_CXMENUSIZE 54
   SM_CYMENUSIZE 55
   SM_ARRANGE 56
   SM_CXMINIMIZED 57
   SM_CYMINIMIZED 58
   SM_CXMAXTRACK 59
   SM_CYMAXTRACK 60
   SM_CXMAXIMIZED 61
   SM_CYMAXIMIZED 62
   SM_NETWORK 63
   SM_CLEANBOOT 67
   SM_CXDRAG 68
   SM_CYDRAG 69
   SM_SHOWSOUNDS 70
   SM_CXMENUCHECK 71
   SM_CYMENUCHECK 72
   SM_SLOWMACHINE 73
   SM_MIDEASTENABLED 74
   SM_MOUSEWHEELPRESENT 75
   SM_XVIRTUALSCREEN 76
   SM_YVIRTUALSCREEN 77
   SM_CXVIRTUALSCREEN 78
   SM_CYVIRTUALSCREEN 79
   SM_CMONITORS 80
   SM_SAMEDISPLAYFORMAT 81
   SM_IMMENABLED 82
   SM_CXFOCUSBORDER 83
   SM_CYFOCUSBORDER 84
   SM_TABLETPC 86
   SM_MEDIACENTER 87
(Note for documentation: Insert here the GetSystemMetrics parameter
   table from the VC++ help file)
   Remarks:
   This function calls the Windows GetSystemMetrics function.
   Example:
   // retrieve the width and height of the current desktop resolution
   var desktop_size[2];
   ..
   desktop_size.x = sys_metrics(0); // SM_CXSCREEN
   desktop_size.y = sys_metrics(1); // SM_CYSCREEN
 
vec_for_bone(VECTOR*,ENTITY*,STRING*)
   calculates the current position of a bone hinge in world coordinates.
   Parameters:
   VECTOR* - to be set to the hinge position
   ENTITY* - model entity pointer
   STRING* - bone name
   See also:
   vec_for_vertex
ent_bonename(ENTITY*,STRING*,var num)
   gets the name of a bone that controls the vertex with the given
   number.
   Returns:
   STRING* if bone found, otherwise 0.
   Parameters:
   entity - model entity pointer
   string - string to be set to the bone name
   num - number of the vertex that is attached to the bone.
 
C-Script Variables and parameters =====================================
shadow_stencil
   Determines the type of dynamic shadows cast by models.
   Type:
   var, redefinable.
   Range:
   off - Z buffer shadows (default).
   on - Stencil buffer shadows.
   Remarks:
   Stencil buffer shadows look better than z buffer shadows: they 'bend'
   around corners, and objects cast shadows on themselves. Due to the hard
   shadow edges, especially with self shadows, they work best with high
   polygon models and rather dark levels with hard light contrasts. Please
   note the following restrictions:
   - Stencil buffer shadows are slower than z buffer shadows, and only run
   on 3D cards with 8 bit stencil buffer support.
   - Stencil buffer shadows can only be cast by nontransparent models
   consisting of closed meshes with no holes or intersections. Otherwise
   rendering errors (dark lines projecting from the model to the shadow)
   can be visible. In a closed mesh, every edge is shared by exactly two
   triangles. If the model's mesh is not closed, create a closed mesh LOD
   model for shadow casting. The MED meshtester can be used for
   determining whether a mesh is closed or not.
   - Dynamic shadows are not clipped by walls. A shadow can be cast on
   a wall and behind the wall at the same time. Take care that level and
   models are very dark in unlit parts to cover unwanted shadows.
   - Stencil shadows also cover model polygons that point away from the
   light source, which can lead to undesired flickering shadow polygons.
   To avoid this, use a material with low ambient and a high diffuse part.
   - For speed reasons, a z-pass stencil shadow algorithm is used that
   does not allow to move the camera into a shadow volume. Therefore the
   player should only cast a stencil shadow when using a 3rd person
   camera. In first person mode the player's shadow is automatically
   switched off when stencil shadows are activated.
floor_trace
   Determines the method for the internal entity static light and shadow
   calculation.
   Range:
   0 - don't calculate brightness by static lights
   1 - use the old collision detection (trace, default)
   2 - use the new collision detection (c_trace)
   Remarks:
   Setting this variable to 2 allows activating the map builder function
   'Merge Across Leafs' for reducing the number of polygons in a level.
   See also:
   entity.unlit, Merge Across Leafs
entity.floor_dist
   Distance to the nearest block or terrain surface below the entity.
   Type:
   var, r/o
   Range:
 > 0 - distance to the floor
 < 0 - no floor found
   Remarks:
   This value is internally set by the static light and shadow calculation
   and can be used for the movement script. It is only valid if the entity
   is not unlit, and the nearest level or block surface below is within
   the floor_range.
   See also:
   entity.unlit, floor_range
entity.fat
   entity.narrow
   Remarks:
   If both flags are set, the entities' bounding box (min_x, max_x) is set
   to the real size of its first frame by default.
 
video_depth
   Range: 16,32; default: 32
screen_color
   ..is also drawn when all views are switched off.
sky_color
   replaces bg_color and has now a default of 64,0,0 (dark blue).
sky_blend
   If this flag is set, sky domes are not clipped abruptly at the sky_clip
   angle, but get a transparency range for fading at the horizon.
   Range: on/off, default: on.
   See also:
   Sky_clip,DOME
sky.scene
   Abandoned for sprites. Now for preventing z buffering of sky models only.
sky.cylinder
   Replaces sky.scene for sprites. Unlike sky.scene, with sky.cylinder the
   overlay flag is not automatically set.
sky_cube_level
   sky_dome_level
   Entity pointers for the default sky cube or sky dome used by the level
   sky box.
   Remarks:
   These pointers can be used for changing the default sky properties,
   like cloud speed or brightness. They are set when loading a level that
   has a cube or dome texture for its sky box. Otherwise they are NULL.
   They are automatically set to NULL when a sky is defined by script.
sky.dome
   Remarks:
   If the sky entity contains several frames, the are displayed one over
   each other as cloud layers.
mouse_sync
   Synchronizes the mouse pointer with the windows mouse position, using
   hardware cursor support if available on the 3D card. This results in
   smoother mouse movement because the mouse position is updated
   several times per frame cycle.
   Type:
   flag (default = off)
   Remarks:
   - The mouse sprite is written into the front buffer instead of the
   back buffer, which can result in a frame rate dependent offset
   between the real mouse position and mouse_pos.x/y.
   - Due to a DirectX8 bug, the mouse bitmap size is critical for some 3D
   cards. In window mode the mouse_map must be 32x32 pixels in size,
   otherwise it is automatically rescaled to that size. In fullscreen mode
   the mouse_map must be 16x32 pixels in size, otherwise it is not visible
   at all. Therefore two different mouse cursor images must be used for
   window and fullscreen modes.
mouse_valid
   Indicates whether the mouse pointer is within the engine window. This
   flag can be used to suspend mouse reactions when the mouse is outside
   the window.
   Type:
   Flag, r/o.
   Range:
   1 - mouse pointer within the engine window.
   0 - mouse pointer outside the engine window.
   Example:
   if (mouse_valid) {
   force.x = key_force.x + mouse_force.x;
   } else {
   force.x = key_force.x;
   }
window_focus
   Determines whether the engine window is the foreground window or not.
   Type:
   var, r/o
   Range:
   1 - engine window is in the foreground.
   0 - other window is in the foreground.
   Remarks:
   The mouse_force vector is set to 0 if the engine window is not the
   foreground window. In fullscreen mode, the engine is always in the
   foreground.
 
save_dir
   The current folder for saving files, game scores, and screenshots.
   Type: STRING*
   See also: -DIR
work_dir
   The game folder.
   Type: STRING*, R/O
exe_dir
   The folder of the application's EXE file.
   Type: STRING*, R/O
 
joy_hat
   joy2_hat
   Coolie hat position of the first or second joystick.
   Type: var, r/o
   Range: Hat angle in degrees, or -1 at center position.
joy_11, joy_12, joy2_11, joy2_12
   The number of joystick buttons was increased to 12.
 
render_view
   The currently rendering view in a material event.
   Type:
   view pointer
   Example:
   // use different material effects depending on the view
   if (render_view == camera) { mtl..... }
video_screen
   has now a default value of 2, making window mode the default mode.
event_frame
   entity.enable_frame
   This event is triggered every frame. Not useful for C-Script that
   has the wait() instruction, but very useful for entity functions
   in other languages.
entity.cast
   If this flag is set, no stencil shadows or self shadows are cast on
   this entity. If it is set for a light emitting entity, the light will
   cast stencil shadows for all entities in its range.
   Remarks:
   Take care that shadow casting lights don't cast a shadow
   towards the camera. This limitation is normally kept by the sun, but
   can be violated by low-flying lights.
 
material.enable_render
   Remarks:
   If the event function returns the value of 1, the entity is not rendered
   by the engine. A user rendering function can be implemented this way.
   For rendering the entity, 0 must be returned.
   Example:
   // generate a matrix that transforms camera space back to world space
   function mtl_env_view()
   {
   mat_set(mtl.matrix,matViewInv);
   // reset the translation part of the matrix
   mtl.matrix41 = 0; // 0 == float(0)
   mtl.matrix42 = 0;
   mtl.matrix43 = 0;
   return(0); // render the entity
   }
 
delimit_str
   Gives the character that marks the string end for the file_str_read
   and txt_load functions. Can be changed to a different character than
   ','.
   Type:
   STRING*
   Default:
 ",".
   See also:
   file_str_read, txt_load
 
panel
   Remarks:
   Rather than using previously defined bmaps, panel definitions can
   also contain directly defined bmaps by giving the image file name
   instead of a bmap name. A bmap with the same name, but the '.'
   character replaced by '_' is then automatically created. If the same
   image file is used several times for different panels, only one
   bmap is created.
   Example:
   PANEL* splashscreen = { bmap = "splash.pcx"; } // creates a bmap splash_pcx
panel.scale_x
   panel.scale_y
   scale factors for resizing a panel and its elements.
   Range:
   0.1 .. unlimited (default 1)
   Remarks:
   Scale factors don't affect truetype fonts.
text.scale_x
   text.scale_y
   scale factors for resizing a text.
   Range:
   0.1 .. unlimited (default 1)
   Remarks:
   Scale factors don't affect TrueType fonts.
text.center_x
   Causes the text to be horizontally centered around text.pos_x. Works
   with truetype and bitmap fonts.
panel.button
   Button functions can compare the event_type variable to examine by
   which mouse event they were triggered. At the beginning of a button
   function, event_type can have the following values:
event_touch - the mouse was moved over the button
   event_release - the mouse was moved away from the button
   event_click - left mouse button was clicked over the button
   event_buttonup - left mouse button was released over the button
   Remarks:
   event_release and event_buttonup can be used to distinguish whether
   functionOff was triggered by leaving the button or releasing the mouse
   button.
panel.digits
   Parameters:
   len - format parameter, gives the maximum number of digits. The
   fractional part gives the number of decimals. If len is negative,
   leading zeros will be displayed.
   factor - the variable value is multiplied by the given factor. The
   result is not limited to the normal variable range of
   -999999..+999999, thus allowing for the display of huge numbers.
panel.blue
   panel.green
   panel.red
   Colors for True Type fonts in digit elements.
Comment tags
   The following comment tags are used for the WED behavior panel:
// uses: (List of Skill and Flag definitions)
   Like Properties->Behavior, but only the defined Flags and Skills are
   displayed and can be edited.
/* desc: text */
   // desc: text
   The text appears at the beginning of the panel.
// title: text
   The text replaces the action name in the title of the panel(like 'Customize Script').
// image: name.pcx
   The given .pcx image is displayed at the head of the panel (like 'Customize Script').
// flag1: name default
   Similar to // uses: the entities' flag1 can be set under the given
   name and gets the given default value (0 or 1). The same goes for
   flag2...flag8.
Example:
   // flag7: Remote 1
   Defines a 'Remote' flag that is flag7 and set by default.
// skill1: name default
   Similar to // uses: the entities' skill1 can be set under the given
   name and gets the given default value. The same goes for skill2..skill20.
Example:
   // Skill20: Health 123.45
   Defines a 'Health' variable that uses skill20 and is initialized at 123.45.
/* help: text */
   // help: text
   This text appears when [?] is clicked and the mouse cursor is over the
   skill or Flag following this help tag.
view.nocull
   Disables BSP tree culling for the given view.
   Type:
   flag
   Remarks:
   If this flag is set, objects are rendered even when hidden behind walls.
   The BSP tree is still used for rendering, but it's precaclulated
   visibility information is discarded.
   See also:
   d3d_nobsp
Warning W1510 - Inkey already active
   An attempt was made to run inkey() twice at the same time.
d3d_automaterial
   Activates automatic material assignments by material names.
   Type:
   var, redefinable.
   Range:
   0 - no automatic material assignment (default).
   1 - assign a material to all level textures with the same name.
   2 - assign a material to all level textures and entity files with
   the same name ('.' replaced by an underscore '_').
   Remarks:
   - through this variable, default materials can be assigned to individual
   level textures and entity files, and material effects like bumpmapping
   and shaders can be assigned to level texures.
   - For assigning a material
   to a certain texture, define it with the same name as the texture.
   - For assigning a material to a
   certain file, define a material that has the same name as the file with
   the extension preceded by an underscore (like "warlock_mdl" or
 "brickwall_tga").
   - Levels load faster if this variable is at 0.
 
material.skill9..material.skill20
   vecSkill9, vecSkill13, vecSkill17
   Materials have now 3 more skill vectors for passing values to shaders.
material.tangent
   Remarks:
   This flag can only be used for models and terrain, but not for
   sprites or level geometry.
matWorldInv
   The inverse world transformation matrix, to be used by shaders.
ent_skin1
   is set to the sprite texture on rendering sprite material effects,
   to the surface texture on rendering flat level geometry, and to the
   lightmap texture on rendering shaded level geometry.
ent_skin2
   is set to the surface texture on rendering shaded level geometry.
 
Physics & Collision ===================================================
The c_move, c_trace, c_rotate instructions use an ellipsoid-based
   collision detection. The shape of the ellipsoid can be set by the
   entities' min_x and max_x vectors, or by the c_setminmax instruction.
c_setminmax(entity)
   sets the collision ellipsiod of the entity to it's real proportions.
   Parameters:
   entity - entity pointer.
   Modifies:
   entity.min_x,entity.max_x
   Remarks:
   By default, the min_x and max_x vectors of a model entity are set to
   a vertical symmectric ellipsoid suited for actors. If the entity is
   not an actor, set both it's fat and narrow flags (or redefine
   enable_polycollision to 2) and use this instruction right after loading
   or creating the entity, or after changing it's scale values to set it
   to it's real proportions.
phent_setelasticity(ENTITY*,var bounciness,var minSpeed);
   Remarks:
   EVENT_FRICTION is only triggered at speeds above the minimum speed.
phent_addvelcentral(ENTITY*,VECTOR* speed);
   A linear velocity is added to the entity’s center of mass. When there
   is no gravity and no damping, the entity will just continue to float
   with the direction and speed given by the speed vector, which is
   independent of the body's current orientation.
   See also:
   phent_addcentralforce;
   Remarks:
   For giving an entity a defined push, use this instruction rather than
   phent_addcentralforce. The effect by phent_addvelcentral is independent
   of the entity's mass and of the time a force is applied.
phent_addvellocal(ENTITY*,VECTOR* speed,VECTOR* pos);
   phent_addvelglobal(ENTITY*,VECTOR* speed,VECTOR* pos);
   Linear and angular velocity are added to the specified entity, at the
   local or global position given by the pos vector. The speed vector is
   independent of the objects current orientation. It is not checked
   whether the position is actually inside the entity, so by choosing a
   pos far away from the entity, you can give it a strong spin. If on the
   other hand pos is exactly at the object’s center of mass, no spinning
   will occur (consider using phent_addvelcentral in this case).
   See also:
   phent_addcentralspeed, phent_addforcelocal, phent_addforceglobal;
c_updatehull(entity,framenum)
   Recalculates collision hulls for the given entity to match the vertex
   positions of framenum (starting at 1 for first frame).
   Remarks:
   - c_updatehull includes a call to c_setminmax() and thus will override
   previous ellipsoid dimensions.
   - c_updatehull does not check for intersections, thus you should make
   sure that there is enough space when selecting a larger frame. Choosing
   a smaller frame does not pose any problems.
   Speed: slow
phent_addlocalforce(entity, vecforce, vecpoint)
   Remarks:
   This function now also works with PH_WAVE entities. When used with such,
   vecpoint is a local coordinate of the terrain object. vecforce.z gives
   the amount of initial water displacement in Z direction. The valid
   range for vecforce.z is -1 to +1, where this value is relative to the
   general terrain size. E.g. a value of 1 corresponds to the distance
   from one vertex to its neighbor in x direction; a value of 0.5 then
   would be have this distance. It's a good idea to use small values here.
   Speed: fast
phent_addglobalforce(entity, vecforce, vecpoint)
   Remarks:
   This function now also works with PH_WAVE entities. When used with such
   vecpoint is a global (=world) coordinate. vecforce.z gives the amount
   of initial water displacement in Z direction. The valid range for
   vecforce.z is -1 to +1, where this value is relative to the general
   terrain size. E.g. a value of 1 corresponds to the distance from one
   vertex to its neighbor in x direction; a value of 0.5 then would be
   have this distance. It's a good idea to use small values here.
   Speed: fast
phent_clearvelocity(entity);
   Sets the instantaneous linear and angular velocity of the registered
   entity to 0, effectively stopping its movement at the current
   position.
   Speed:
   Fast
   Remarks:
   It is not recommended to do this for entities that are part of a
   constraint.
PH_WHEELS
   Wheels used to bend at high rotational speed. This has been improved
   and wheels will stay in place even at higher velocities.
ph_autodisable()
   Adjusts time-out values for automatically disabling physics entities.
   Remarks:
   When a physics entity has been inactive, i.e. moving only a very small
   amount for a number of frames, it will be disabled automatically. When
   changes are made to this physics entity by calling one of the phent_xxx
   functions, or if an active physics entity collides with the disabled
   one it will be enabled automatically. Please note that non-physics
   entities will need to use c_move to corectly enable auto-disabled
   entities. Just placing an entity using my.x will not cause the entity
   to be re-enabled.
ph_iterations
   If set to a value larger than 0 (default), uses an alternative
   experimental physics solver which can use less memory and be faster in
   certain configurations with lots of constraints. The higher the value
   set to PH_ITERATIONS, the more accurate the solution will be (= less
   jittering) but calculations will also take longer. Try values in the
   range of 5 to 50.
PH_WAVE
   Edition: |P|
   Constant for phent_settype(); converts a terrain entity to a dynamic
   water surface. The resolution and smoothness depends on the underlying
   terrain's vertex grid. The more vertices the smoother and slower the
   simulation will be. Currently the following two functions are available
   for water surfaces:
phent_setdamping(entity, damping, area)
   Damping determines how the water surface reacts to distortions. A low
   value causes a goo-like slow motion whereas a high value makes the
   surface vibrate a lot. Area sets the size of the area affected by
   distortions a low value results in local distortions, higher values
   make the whole surface react to distortions.
   Edition: |P|
   Parameters:
   damping and area in the range of 0..100.
phent_addforcelocal(entity, vecpoint, vecforce)
   Remarks:
   On a water entity, this instructions creates a distortion at the local
   position vecpoint of the water entity with intensity vecforce.z. Only
   the z component is used (not x,y) and the value must be between -1 and
   +1.
phent_addobstruction(entity, amount, vecpoint)
   Obstructions limit or prevent waves from propagating past them. This
   function only works with PH_WAVE entities.
   Edition: |P|
   Parameters:
   Vecpoint - a global (=world) coordinate where an (invisible)
   obstruction should be placed.
   amount - strength of obstruction with a range of 0..1 where 1 means
   block waves and 0 does not limit waves at all.
   Remarks:
   Ideally obstructions should be anti-aliased, meaning that there is a
   center point with amount set to 1 and then a border zone of 3 vertices
   where the amount value is set to less than 1. If amount is set to a
   negative number all previous obstructions of this entity will be
   deleted.
   Speed: fast
enable_polycollision
   Range:
   2 - Ellipsoid collision and physics engine enabled. All entities' fat
   and narrow flags will both be set by default, and their bounding boxes
   are set to the real size of their first frame.
 
Paths =================================================================
path_set(ENTITY*,STRING* name)
   Attaches the given entity to the path with the given name.
path_next(ENTITY*);
   replaces ent_nextpath.
path_nextnode(ENTITY*,var node,var edge)
   Finds the next node along a given edge.
   Parameters:
   entity - pointer of an entity attached to a path.
   node - number of the current node (1 == first node of the path).
   edge - number of the edge (1 == first edge of the node).
   Returns:
   Number of the node to which the given edge leads from the current
   node (direction sensitive), or 0 if no such edge exists.
path_scan(ENTITY*,VECTOR* pos,VECTOR* angle,VECTOR* sector)
   Finds all nodes of any path within the scan cone, and returns the
   closest one.
   Parameters:
   ENTITY* - entity pointer.
   pos - scan origin.
   angle - scan direction.
   sector - horizontal and vertical scan cone in degrees, and range.
   Returns:
   The number of the closest node found, or 0 if none is found.
   Modifies:
   entity - is attached to the path belonging to the closest node.
   Speed:
   Slow.
   Remarks:
   For the pos and angle vectors, entity.x and entity.pan can be used,
   which uses the entity position and pan/tilt angles for origin and
   direction of the scan cone.
   The path_scan instruction internally creates a sorted list of nodes
   according to their distance to the scan origin. For finding further
   nodes within the same scan cone, the path_scannode instruction can be
   used.
   Example:
   // move along a path loop
   // uses _FORCE, _MOVEMODE
   action patrol_path
   {
   // attach entity to nearest path
   result = path_scan(me,my.x,my.pan,vector(360,180,1000);
   if (result == 0) { return; } // no path found
// find first waypoint
   var node = 1; // start at first node
   path_nodepos(my,node,my._TARGET_X);
 while (my._MOVEMODE)
   {
   // find direction
   result = vec_to_angle(angle,vec_diff(temp,my._TARGET_X,my.x));
// near target? Find next waypoint of the path
   if (result < 25) {
   node = path_nextnode(my,node,1);
   path_getnode(my,node,my._TARGET_X,NULL);
   }
// turn and walk towards target
   actor_turnto(angle.PAN);
   actor_moveahead(MY._FORCE);
   wait(1);
   }
   }
path_scannode(ENTITY*,var index)
   Finds further path nodes within the cone of the last path_scan
   instruction.
   Parameters:
   ENTITY* - entity pointer.
   index - distance index, 0 == closest, 1 == second closest and so on.
   Returns:
   The number of the node found, or 0 if no more nodes were in the scan
   cone.
   Modifies:
   entity - is attached to the path belonging to the found node.
   Speed:
   Fast.
path_setnode(ENTITY*,var node,VECTOR* pos,var* skills)
   path_getnode(ENTITY*,var node,VECTOR* pos,var* skills)
   Retrieves or sets position or skills from a path node.
   Parameters:
   ENTITY* - pointer of an entity attached to a path.
   node - number of the node (1 == first node of the path).
   pos - vector to receive or set the nodes xyz position, or NULL.
   skills - var[6] array to receive or set the 6 node skills, or NULL.
   Returns:
   0 if the node does not exist, otherwise nonzero.
   Modifies (path_getnode):
   pos - set to the nodes xyz position.
   skills - set to the 6 node skills.
   Modifies (path_setnode):
   nodes xyz position - set from the pos vector.
   node skills - set from the skills array.
   Remarks:
   Changing a node position does not update the edge lengths. If necessary,
   the lengths have to be manually updated by path_setedge.
path_setedge(ENTITY*,var node,var edge,var* skills)
   path_getedge(ENTITY*,var node,var edge,var* skills)
   Retrieves or sets length, weight, and skill values from a path edge.
   Parameters:
   ENTITY* - pointer of an entity attached to a path.
   node - number of the node (1 == first node of the path).
   edge - number of the edge (1 == first edge of the node).
   skills - var[3] to receive or set the length, weight, and skill values.
   Returns:
   0 if the edge does not exist, otherwise nonzero.
   Modifies (path_getedge):
   skills[0] - set to the edge length.
   skills[1] - set to the edge weight.
   skills[2] - set to the edge skill.
   Modifies (path_setedge):
   edge length - set from skills[0] if nonzero.
   edge weight - set from skills[1].
   edge skill - set from skills[2].
 
Multiplayer ===========================================================
Bandwidth issues
   When developing a network game, the most important thing is keeping the
   traffic below the limit of the available bandwidth. As long as the
   bandwidth is not exceeded, the network will run smoothly. The problems
   arise when the bandwidth is exceeded on a slow internet connection,
   which can happen easily if no care is taken about limiting the traffic.
In engine versions prior to 6.3, clients were synchronized to the
   server. This ensured that all messages were sent at the right time, but
   had the disadvantage that the frame rate of server and clients was
   reduced when the available network bandwidth was exceeded. From version
   6.3 on, the frame rate of clients and servers doesn't depend on the
   bandwidth anymore. All messages are sent in asynchronous mode with
   exception of client messages when dplay_timeout is disabled. If the
   traffic of a client or server exceeds the available bandwidth, the
   oldest unreliable messages expire and are removed from the message
   queue. This has the disadvantage of packet loss, but ensures a high
   frame rate.
The application can check the number of dropped packets and can adjust
   the send rate or entity update rate until the bandwidth limitation is
   met. Note that the message expiration mechanism only works for
   unreliable messages. The application must take care that reliable
   messages NEVER exceed the lowest possible bandwidth, otherwise clients
   and servers will fall out of sync.
For testing and controlling internet play, the Pro Edition can use the
   Microsoft DirectPlay network simulator (see command line option -sim |P|).
Network protocol
   svc_info: the frame_time and 0x11191218 sync values are removed
   svc_update: If an update packet contains file name, skin, flags, or
   lightrange, it is sent in reliable mode. Otherwise it's sent in
   unreliable mode.
dplay_dropped
   Number of packets per second that did not reach the target machine
   because they were lost on the internet or timed out due to low
   bandwidth. Indicated in the 5th row of the statistics panel Net column.
   Can be used to determine whether a game is playable on a certain
   connection, or to automatically reduce the dplay_entrate when a lot of
   packets are dropped.
send_skill(entity.skill,var mode)
   Sends the given entity parameter - for instance, a skill or skill
   vector - to the other PCs in a network. If executed on a server, it
   sends the skill to the creator of the entity, or to all clients. If
   executed on a client, it sends the skill to the server. The skill or
   skill vector is updated on the same entity instance on the other PCs.
   Returns:
   0 if the parameter was not sent due to SEND_RATE or for other reasons,
   otherwise nonzero.
   Parameters (new):
   entity.skill - the entity parameter to be sent.
   mode - either 0 or a combination of the following flags:
   SEND_VEC - send 3 consecutive skills used as a vector.
   SEND_ALL - send to all clients, rather than to the creator of the entity (only when executed on the server).
   SEND_UNRELIABLE - send in unreliable mode. Otherwise it's sent in reliable mode.
   SEND_RATE - send only every n'th frame, while n = dplay_entrate/time.
   Speed:
   Medium.
   Remarks:
   - Triggers event_receive on the target entity.
   - The entity must exist on the target machine. So don't perform this
   instruction immediately after creating the entity. Use sleep(0.5)
   to wait until all target machines have received the newly created
   entity.
   - Send most entity parameters, like user input, in unreliable mode.
   Only important entity status changes like shooting or opening a door
   should be send in reliable mode. Reliable messages won't expire, which
   could result in a buffer overflow and falling out of sync on slow
   connections when many reliable messages are sent.
Example:
   var skill1_old; // local variable to backup skill1
   if (my.skill1 != skill1_old) { // send only if changed
   skill1_old = my.skill1; // store change
   if (my.skill1 == 0) { // send important values in reliable mode
   send_skill(my.skill1,SEND_ALL);
   } else {
   send_skill(my.skill1,SEND_ALL+SEND_UNRELIABLE);
   }
   }
   See also:
   event_receive,dplay_timeout
dplay_timeout
   Time in ticks for unreliable network messages to expire if they could
   not be sent during that period due to low bandwidth.
   Range:
   0..16, default 3 (~180 ms). 0 disables the expiration mechanism (client only).
   Remarks:
   Network messages must expire after some time to prevent a buffer
   overflow and falling out of sync when the available bandwidth is
   exceeded. The lower dplay_timeout, the lower the traffic, but the higher
   the packet loss due to dropping of expired messages.
   On the client, this value can be set to 0, which means that even
   unreliable messages never expire. In that case the client waits
   at the end of every frame until all pending messages are sent. This was
   the behavior of engine versions prior to 6.3, and can result in a
   reduced frame rate on slow connections.
   See also:
   send_skill,send_var,send_string
dplay_packetsize
   Maximum size of an UDP network message packet, in bytes. The engine
   collects messages in a buffer until they sum up to the given size,
   then they are sent together in a single packet.
   Type:
   var
   Range:
   0..1024, default 128.
   Remarks:
   The message buffer is sent at least once per frame, even if the packet
   size is not reached. At a packet size of 0, messages are not buffered
   but sent straight away. The bigger the packet size, the less packets
   are sent, but the slower they travel over the net. The packet size
   should be less than 1000 bytes, because routers or other equipment on
   the internet often delay or drop larger UDP packets.
dplay_bpsreliable
   dplay_bpsunreliable
   Bytes per second received in reliable and unreliable mode.
   Type:
   var, r/o
   Remarks:
   On the client, these values are for the connection ot the server. On
   the server, the values are for the connection to the last connected
   client.
   The values are indicated in the 4th and 5th row of the net column in
   the statistics panel.
dplay_maxclients
   gives the maximum number of clients that can connect to a server.
   Range:
   1..4, default 4 (Commercial Edition)
   1..unlimited, default 25 (Pro Edition)
   Remarks:
   If more clients try to connect to a session, they are refused. In
   the development version error 1403 "Too many clients" is displayed.
dplay_localfunction
   Start entity actions in a loaded level even on a client. Can be used
   for local entity functions without the need to send the function by
   proc_local or proc_client.
   Type:
   Flag (default: off)
   Remarks:
   Affects the level_load, but not the ent_create instruction. The
   entity action could use the connection variable to decide whether
   it's running on the client or on the server, and behave accordingly.
   Example:
   dplay_localfunction = on;
   level_load(mylevel.wmb); // starts entity actions even on a client
   dplay_localfunction = off;
   See also:
   connection, proc_local, proc_client
dplay_pingrate
   Minimum rate of time synchronisation messages from server to client.
SDK variables and parameters ==========================================
render_mesh
   void *pointer to the current D3DXMESH, to be used in render events for
   implementing user rendering functions.
render_map[4]
   BMAP pointer to the current entity skin and the 3 consecutive skins,
   to be used in render events for implementing user rendering function.
pdsbs
   void* pointer to the last created secondary SoundBuffer, valid
   immediately after snd_play, snd_loop, ent_playsound, and ent_playloop
   instructions. The pointer remains valid as long as the sound plays.
pd3dcaps
   void* pointer to the D3DCAPS struct of the current D3D device.
GetMessage(UINT message, WPARAM w_param, LPARAM l_param)
   can be set to a user provided message handler that links into the
   engine's main message loop. If is called every time a message event is
   sent to the engine window.