(Deutsche Beschreibung weiter unten) This is a description of the 3D GameStudio/A5 update to version 5.51. All new features and changes are described below. For installing the update, you must follow the update instructions below to the point. NOTE: The update will MODIFY not only the engine, but also the template scripts and the office and terrain test levels. If you have changed something within, and want to keep your changes, copy them to a safe place before updating. NOTE: Unlike all updates before, this one is NOT 100% COMPATIBLE anymore with prior versions. Normally your game will still run without problems, but the new multimedia player required changes in the MIDI/AVI playing instructions. Please find details in the 'compatibility' section below. DO NOT INSTALL THIS UPDATE if you are not able to edit scripts or understand script error messages, or if your PC is very old, or not equipped with DirectX 8 compatible 3D hardware. Outdated video cards, like the Voodoo series or video cards with 4 MB memory or less, and Windows 95 are not supported by this DirectX 8 version. Updates do not include the new manual. You can download the new manual separately from the download page as soon as it's available. ====================================================================== 2-step update instructions: Step 1: Copy your A5 key file (KEY.EXE) from your key disk into your GameStudio folder (normally "C:\Program Files\GStudio"). Take care that it's indeed your personal key file that you've received from Conitec (not from a demo or a beta version). If you have purchased GameStudio in a computer shop, you don't have a key file - copy the SETUP.EXE file from the CD-ROM instead. Step 2: Make sure that WED, MED or the engine are not running. Stop all virus scanners or other programs that run in the background. Start the update program that you've downloaded. You'll be asked for a target folder. Enter your GameStudio folder. Some files located there will be updated. If you are getting an error message instead, you've used a wrong file, or the wrong folder. After successful update, the engine version "GameStudio 5.51.00" must be indicated in WED through Help/About. ====================================================================== Possible problems you may encounter: 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 used a wrong key file. It must be an original key file, from your original key disk and for the right edition. 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 "Access to an unnamed file denied". A. WED or MED or anything else from 3D gamestudio was not accessible during the update process - still running or still open, or set to system or read/only, or set to restricted access on a Win2000 or ME system. 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. Update again and make sure that all files are closed and accessible. You can repeat the update process as often as you want. Q. I'm getting script error messages when starting my level. A. You have modified scripts in the template folder or copied them into your game folder, or you have defined 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. In the former case delete the scripts that you've copied or modified, and install anew. You should never copy or modify content of the template folder without having some script experiences. Another possibility is that your scripts contain long-abandoned A3 or A4 instructions. These instructions now issue error messages. See the "compatibility" section below for details. Q. My flare and alphachannel effects look worse than before. A. Your Standard Edition does not support flare effects. Due to a bug, prior versions (5.10 and below) contained a part of the flare code - but incomplete, so this could lead to crashes when using flare effect. The current version does not contain flare code anymore. Q. My sprites appear mirrored. A. They were mirrored in prior versions (5.12 and below), this was fixed now. By entering var compatibility = 0; at the beginning of your script you'll get the old behaviour. Q. My sky entities have a different brightness than before. A. The color values were changed to make them consistent with level entities. By entering var compatibility = 1; at the beginning of your script you'll get the old behaviour. Q. The keyboard shortcuts of WED don't work anymore. A. Open WED->Preferences and set Key->Default->Apply. ====================================================================== Compatibility: Several long-abandoned A3 and A4 WDL instructions will now issue error messages and must be replaced by their C-Script counterparts. The DirectX 8.1 conversion also required the replacement of certain multimedia, D3D and DirectPlay instructions. In summary, this affects the following features and keywords: MUSIC name = will be ignored. PLAY_SONG(name,volume) will be ignored. Replace it with media_loop("filename.mid",NULL,volume). PLAY_SONG_ONCE(name,volume) will be ignored. Replace it with media_play("filename.mid",NULL,volume). MIDI_PLAYING - will be always at 0. Replace it with media_playing(media_handle). MOVIE_PLAYFILE("filename.avi") will be ignored. Replace it with media_play("filename.avi",NULL,100). MOVIE_STOP will be ignored. Replace it with media_stop(media_handle). MOVIE_FRAME will be always at 0. Replace it with media_playing(media_handle). D3D_TEXRESERVED, D3D_VSYNC will be ignored. DPLAY_SERVERMODE, DPLAY_OPTIMIZE, CLIENT will be ignored. ENTITY.HIDDEN will be ignored. VIDEO_DEPTH can only take the values 16 and 32. 8 bit mode is not available anymore. -n3d, -card will be ignored. The best card is selected automatically. -modem, -serial, -ipx will be ignored. Multiplayer mode must use TCP/IP or UDP. 3D cards with 4 MB video memory or less will give a "not enough video memory" error message and exit. Mouse picking on sprites will also detect the transparent parts, unlike before. Colors for screen and sky entities and particles have now their medium and default value at 128. Values of 129..255 will brighten the entity or particle, while values of 0..127 darkens them. The following abandoned WDL keywords will now issue error messages: SET a,b Replace with a = b. SKILL name { val x; } Replace with var name = x. SKILL name {... x; ... y; ... z;} Replace with var name[3] = x,y,z. CALL function Replace with function(), and have the function or a prototype defined before. WAIT x, WAITT x will issue an error message. Insert the missing parentheses. ACCEL will issue an error message. Use the following C-Script function for acceleration: function vec_accel(&speed,&force,friction) { friction = max((1-time*friction),0); speed[0] = friction*speed[0] + time*force[0]; speed[1] = friction*speed[1] + time*force[1]; speed[2] = friction*speed[2] + time*force[2]; } Note that this acceleration function is frame rate independent, while the abandoned A3 ACCEL instruction wasn't. TO_ANGLE a,b Replace with result = vec_to_angle(a,v). VECROTATE v,a Replace with vec_rotate(v,a). NORMALIZE v,l Replace with vec_normalize(v,l). TO_SKILL n,s Replace with n = str_to_num(s). TO_STRING s,n Replace with str_for_num(s,n). SET_STRING s1,s2 Replace with str_cpy(s1,s2). ADD_STRING s1,s2 Replace with str_cat(s1,s2). STRICMP s1,s2 Replace with result = str_cmpi(s1,s2). END Replace with return. PLEASE NOTE: The version 5.240 which supports DX7, 8 bit mode and the old syntax will remain available. Use that version for your old projects if replacing outdated instructions would be too much effort. Use the new version only for new projects. ====================================================================== DEUTSCHE BESCHREIBUNG ================================================ ====================================================================== Der folgende Text beschreibt die Installation des 5.51 Updates von 3D GameStudio. Der englischen Beschreibung weiter unten koennen Sie eine Liste der neuen Features entnehmen. Um das Update zu installieren, folgen Sie genau den Update-Anweisungen. BITTE BEACHTEN: Ein Update bringt nicht nur die Engine auf den neuesten Stand, sondern auch die Template Skripte und den Office-Level. Falls Sie darin etwas modifiziert haben, sollten Sie die betreffenden Dateien vorher an einen sichern Ort kopieren. BITTE BEACHTEN: Im Gegensatz zu allen frueheren Updates ist dieses NICHT 100% KOMPATIBEL zu alten Versionen. Normalerweise wird Ihr Game problemlos laufen, doch der neue Multimedia-Player erfordete Aenderungen in MIDI/AVI Anweisungen. Sie finden Details im 'Kompatibilitaet' Abschnitt unten. INSTALLIEREN SIE DIESES UPDATE NICHT, wenn Sie nicht in der Lage sind, Skripte zu editieren oder Skript-Fehlermeldungen zu verstehen, oder wenn Ihr PC sehr alt ist oder ueber keine DirectX 8 kompatible 3D Hardware verfuegt. Veraltete Video-Karten, wie die Voodoo Serie oder Karten mit 4 MB Videospeicher, oder Windows 95 werden von dieser DirectX 8 Version nicht mehr unterstuetzt. Updates enthalten nicht das Skript-Handbuch. Bitte laden Sie sich das neue Skript-Handbuch, sobald es verfuegbar ist, von unserer Download-Seite. ====================================================================== 2-Schritt Update Anweisung: Schritt 1: Sie muessen zuerst eine Datei in Ihren Gamestudio-Ordner (normalerweise C:\Programme\Gstudio) kopieren. Haben Sie die A5 Sybex-Version im Laden gekauft, kopieren Sie die Datei SETUP.EXE von Ihrer CD-ROM. Diese Datei ist 11 MB gross, aber Sie duerfen sie nach dem Update wieder loeschen. Haben Sie dagegen 3D GameStudio direkt von Conitec bestellt, kopieren Sie Ihr A5 Key File (KEY.EXE), dass Sie erhalten haben. Beachten Sie, dass es ein 'offizielles' Key File sein muss - nicht von einer Demo- oder Beta-Version. Schritt 2: Vergewissern Sie sich, dass WED, MED oder die Engine nicht laufen. Beenden Sie alle Virenscanner oder sonstigen Programme, die im Hintergrund laufen. Starten Sie das Update-Programm, das Sie heruntergeladen haben. Sie werden nach einem Target Folder gefragt. Geben Sie hier den Pfad Ihres GameStudio Ordners ein - normalerweise "C:\Programme\GStudio". Es werden nun Dateien in diesem Ordner upgedated. Falls Sie stattdessen eine Fehlermeldung erhalten, war es der falsche Ordner oder das falsche Key File. Nach erfolgreichem Update muss die Engine-Version "GameStudio 5.51.00" in WED unter Help / About angezeigt werden. ====================================================================== Moegliche Probleme beim Updaten: Q. Warum bekomme ich eine Fehlermeldung ("Can't update" oder "Error 36") nach meinem Versuch upzudaten? A. Sie haben entweder einen falschen Ordner angegeben, oder benutzen ein falsches Key file. Nur die Sybex-CD-ROM und originale Key Files fuer die richtige Edition lassen sich updaten. Moeglicherweise haben Sie auch versucht, das Update-Programm aus einer Command Shell zu starten - doppelklicken Sie stattdessen einfach das Icon. Q. Warum bekomme ich "Error 37" oder "Error 39"? A. Der Download wurde unterbrochen, oder die Datei ist beschaedigt. Laden Sie sie nochmal. Am besten mit einem Download-Manager, wie GetRight, der hoehere Zuverlaessigkeit bietet. Eventuell wurde die Datei auch durch einen Virus auf Ihrem System veraendert. Q. Ich bekomme "Access to an unnamed file denied". A. WED oder MED oder irgendeine andere Datei 3D von GameStudio konnte nicht upgedated werden - das Programm lief noch oder die Datei war noch geoeffnet, oder ihre Attribute waren auf System, Read/Only, oder Restricted gesetzt. Unter Windows 2000, ME oder XP brauchen Sie Administrator-Rechte, um updaten zu koennen. Updaten Sie noch einmal, und stellen Sie sicher, dass jede Datei geschlossen und zugreifbar ist. Sie koennen den Update-Prozess beliebig oft wiederholen. Q. Ich bekomme WDL-Fehlermeldungen, wenn ich einen Level starte. A. Sie haben Skripte im Template Ordner veraendert oder in Ihren Game-Ordner kopiert, oder Sie haben ein WDL-Objekt definiert, das zufaellig den gleichen Namen wie eine der neu hinzugekommenen Variablen oder Funktionen hat, oder Sie haben einen Fehler in Ihrem Skript, der von den vorigen Versionen nicht erkannt wurde. Im ersteren Fall loeschen Sie die kopierten oder veraenderten Skripte, und installieren Sie noch einmal. Ohne Skript-Erfahrung sollten Sie niemals Inhalte des Template-Ordners kopieren oder veraendern. Eine weitere Moeglichkeit ist, dass Sie noch einige veraltete A3- oder A4-Anweisungen verwenden, die in dieser Version mit Fehlermeldung angezeigt werden. Sie finden Details im 'Kompatibilitaet' Abschnitt unten. Q. Meine Flare- und Alphakanal-Effekte sehen ploetzlich viel schlechter aus als vorher. A. Sie haben die Standard-Edition, die keine Flare-Effekte unterstuetzt. Aufgrund eines Bugs war in frueheren Versionen (5.10 oder darunter) trotzdem ein Teil des Flare-Codes enthalten - jedoch unvollstaendig, so dass dies zu Abstuerzen fuehren konnte. Die aktuelle Version enthaelt keinen Flare-Code mehr. Q. Meine Sprites erscheinen gespiegelt. A. Sie waren in frueheren Versionen (5.12 und darunter) gespiegelt, jetzt erscheinen sie richtig. Durch Eingabe von var compatibility = 0; am Beginn Ihrer Skript-Datei bekommen Sie das fruehere Verhalten. Q. Die Tastaturzuweisungen von WED funktionieren nicht mehr. A. Oeffnen Sie WED->Preferences und klicken Sie Key->Default->Apply. ====================================================================== Kompatibilitaet: Mehrere sehr veraltete A3- und A4-WDL-Anweisungen geben nun Fehlermeldungen aus und muessen durch C-Script Anweisungen ersetzt werden. Die DirectX 8.1 Implementierung erforderte zudem die Aenderung einiger Multimedia, D3D und DirectPlay Anweisungen und den Verzicht auf den 8-Bit Modus. Die folgenden Features und Objekte sind davon betroffen: MUSIC name = wird ignoriert. PLAY_SONG(name,volume) wird ignoriert. Ersetzen durch media_loop("filename.mid",NULL,volume). PLAY_SONG_ONCE(name,volume) wird ignoriert. Ersetzen durch media_play("filename.mid",NULL,volume). MIDI_PLAYING - ist immer 0. Ersetzen durch media_playing(media_handle). MOVIE_PLAYFILE("filename.avi") wird ignoriert. Ersetzen durch media_play("filename.avi",NULL,100). MOVIE_STOP wird ignoriert. Ersetzen durch media_stop(media_handle). MOVIE_FRAME ist immer 0. Ersetzen durch media_playing(media_handle). D3D_TEXRESERVED, D3D_VSYNC wird ignoriert. DPLAY_SERVERMODE, DPLAY_OPTIMIZE, CLIENT wird ignoriert. ENTITY.HIDDEN wird ignoriert. VIDEO_DEPTH kann nur die Werte 16 und 32 annehmen. Der 8-Bit Modus ist nicht mehr verfuegbar. -n3d, -card wird ignoriert. Die beste Karte wird automatisch gewaehlt. -modem, -serial, -ipx wird ignoriert. Der Multiplayer-Modus benutzt TCP/IP oder UDP. 3D Karten mit 4 MB Videospeicher oder weniger beenden das Programm mit einer "not enough video memory" Meldung. Mausberuehrung von Sprites reagiert nun auch auf die transparenten Teile des Sprites. Farben fuer Screen und Sky-Entities und Partikel haben nun die mittlere Helligkeit beim Farbwert 128. Werte zwischen 129..255 erhellen das Objekt, Werte zwischen 0..127 dunkeln es ab. Die folgenden veralteten WDL Anweisungen geben nun Fehlermeldungen aus: SET a,b Ersetzen durch a = b. SKILL name { val x; } Ersetzen durch var name = x. SKILL name {... x; ... y; ... z;} Ersetzen durch var name[3] = x,y,z. CALL function Ersetzen durch function(), und die Funktion oder einen Prototyp vorher definieren. WAIT x, WAITT x Fehlende Klammern ergaenzen. ACCEL Benutzen Sie die folgende C-Script Funktion zum Beschleunigen: function vec_accel(&speed,&force,friction) { friction = max((1-time*friction),0); speed[0] = friction*speed[0] + time*force[0]; speed[1] = friction*speed[1] + time*force[1]; speed[2] = friction*speed[2] + time*force[2]; } Diese Funktion ist, im Gegensatz zu der veralteten A3-ACCEL-Anweisung, unabhaengig von der Frame Rate. TO_ANGLE a,b Ersetzen durch result = vec_to_angle(a,v). VECROTATE v,a Ersetzen durch vec_rotate(v,a). NORMALIZE v,l Ersetzen durch vec_normalize(v,l). TO_SKILL n,s Ersetzen durch n = str_to_num(s). TO_STRING s,n Ersetzen durch str_for_num(s,n). SET_STRING s1,s2 Ersetzen durch str_cpy(s1,s2). ADD_STRING s1,s2 Ersetzen durch str_cat(s1,s2). STRICMP s1,s2 Ersetzen durch result = str_cmpi(s1,s2). END Ersetzen durch return. BITTE BEACHTEN: Die Version 5.240, welche DX7, den 8-Bit-Modus und die alte Syntax unterstuetzt, wird weiterhin angeboten. Benutzen Sie diese Version fuer alte Projekte, falls das Ersetzen veralteter Anweisungen zu viel Aufwand bedeuten wuerde. Benutzen Sie die neue Version fuer neue Projekte. ======================================================================= New features implemented in A5 5.51: ================================== ======================================================================= New DirectX 8.1 Renderer ============================================== A5 now uses the DirectX 8.1 interface, instead of DirectX 7. Please note the following differences to the previous version: - An arbitrary number of A5 applications can now run in window mode at the same time on the same PC. Switching to the desktop and back ([Alt-Tab]) is now supported even in fullscreen mode. - Changing the video resolution in window mode now also changes the window size. The window size won't be changed with the mouse. - 8-bit mode won't be supported anymore by the DX8 version. For games that must use 8-bit mode, an alternative DX7 release (A5.240) that supports 8-bit mode will still be available. - In most cases the frame rate will be around 10%..20% higher under DX8, especially when rendering high-polygon models or terrain. However, in some cases the frame rate can be unchanged or can be even lower. - 3D graphics can look a little different. Transparent parts of a sprite must now really have the color 0,0,0 (under DX7, everything below 8,8,8 was considered transparent). From the commercial edition on, sprite and model textures can be rendered in 24 or 32 bit color depth, instead of 16 bit. - DirectX 8 does not provide a reliable method for displaying error or warning message boxes in fullscreen mode. For this reason, A5 now switches temporarily to window mode when an error message is displayed. - DLL plugins that use DirectX 7 functions won't work anymore, and must be converted to DirectX 8. - There wont't be problems anymore with faulty DX7 drivers of some 3D cards. Instead, there'll probably be new problems with faulty DX8 drivers of some other 3D cards. New Multiplayer Mode ================================================== The DirectPlay 7 network system used previously for multiplayer mode was converted to DirectPlay 8, and now works much more reliably through routers or firewalls. There are many differences between the DP8 and the DP7 implementation: - There won't be a requester anymore asking for a host address. The host address can be entered by the -ip command line option or the predefined server_name string. Sessions on local area nets are automatically found, even if the host address is not entered. Modem, serial, and IPX connections are not supported anymore. - The protocol is faster because client ID's are retrieved from the packet header rather than sent with the packet. - Bandwidth can be greatly reduced by setting the server->client update rate independent of the frame rate, and by updating entity parameters locally instead of globally. - Multiplayer applications can now easily be tested without even having a network. Several clients can be started in window mode (-wnd) simultaneously on the same PC, and connect to a server running on the same or another PC. A new Client/Server system was implemented to allow improvements like local entities, or accessing global entities from a client. Until now, all level entities in a multiplayer game only existed on the server, and were not accessible from the clients. This required some awkward solutions for special effects like a radar screen or local entities. From Version 5.51 on, entities now exists on the server as well as on all clients. Position and angle of non-local entities are automatically synchronized with the server. All client entities can be either accessed by ent_next(), or by their own functions when they are transmitted to the client by proc_global()/proc_client(). Local effects can use the entity positions and angles. The office level contains some simple examples for multiplayer capable functions. ent_createlocal(string,vector position,function) ent_create(string,vector position,function) Creates an entity at the given position with the given action. Ent_createlocal creates the entity locally on the client. A local entity is not transmitted to the server, and thus not visible on other clients. Ent_create creates the entity on the server and on all clients, and starts its action on the server. Speed: Medium. Returns: A pointer to the created entity, or zero when the entity could not be created (for instance, when the file was not found or no level was loaded). Remarks: - In a single player system, both instructions are identical. - A local entity's action runs only on the client who has created it. Local entities can be used for advanced particle effects, player weapons or similar purposes. - Local entities perform collision detection, but are passable for non-local entities. - On a single player system, the entity function is started immediately when the entity is created. On multiplayer systems, entity functions are triggered by a server transmission, which can occur up to 500 ms later. - On a single player system, the entity handle (see handle() function) is valid immediately after entity creation. On multiplayer systems, entity handles are assigned by a server transmission, which can occur up to 500 ms later. So it is recommended not to use entity handles immediately upon creation. - ent_createlocal replaces the hidden flag, which is not useful anymore and will be removed from the documentation. ent_next(entity) Remarks: Ent_next now also works on the client in a multiplayer system. It returns the local as well as the global entities, however in the latter case only the positions and angles are valid. The rest of the parameters and skills stays at their values they had after loading the level. effect_local Like effect(), but starts the effect on the local client in a multiplayer game, rather than sending it to all clients. proc_local(entity,function) proc_client(entity,function) These instructions start a client-side function for the given entity. Proc_local starts the given function on all clients. Proc_client starts the given function only on the client which has created the given entity or it's creator entity. Local or client functions can be used for detecting local mouse events, for starting local sound or particle effects, or for local entity animation. Example: // the following function sets the MY entity invisible only on the client who has created it. function hide_me() { my.invisible = on; } ... proc_client(me,hide_me); ... Remarks: - These instructions can only be executed on the server in a multiplayer game. The function does not run on the server, only on the clients. The entity must also exist on the clients, and will become the MY entity for the local functions. - The last proc_local instruction of each entity is stored. If a new client connects, it is started again on this client. Therefore local functions will even run on clients that connect after the proc_local execution on the server. For using this mechanism, do not start more than one proc_local instruction per entity. - By using the 'connection' variable, a function can do different things dependent on whether it's running on the server, on a client, or on both. send_skill(entity.skill,var mode) Sends the given entity skill or skill vector to the other PCs in a multiplayer network. If executed on a server, it sends the skill either to the client that created that 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: Zero if it's not a valid entity skill or the entity has no creator, non-zero otherwise. Parameters: mode - either 0, SEND_VEC, SEND_ALL, or SEND_VEC+SEND_ALL. SEND_VEC - sends the given skill plus the two following skills. SEND_ALL - sends to all clients, rather than to the creator of the entity (only when executed on the server). Remarks: Triggers event_receive on the target entity. This instruction replaces send() and send_vec(). entity.enable_receive event_receive This event is triggered when the entity receives a skill sent by send_skill. Send modes Normally the server sends all changed entity parameters over to the clients for keeping them up to date. For speeding up the network communication, some entity parameters can be omitted from the updates. For instance, when an entity is locally animated on the clients, its frame and next_frame parameters must not be sent from the server. Each entity now has new flags that prevent sending of certain parameters when set: entity.nosend_origin prevents sending of x,y,z. entity.nosend_angles prevents sending of pan,tilt,roll. entity.nosend_scale prevents sending of scale_x,scale_y,scale_z. entity.nosend_frame prevents sending of frame and next_frame. entity.nosend_skin prevents sending of the skin number. entity.nosend_flags prevents sending of all entity flags. entity.nosend_ambient prevents sending of ambient and albedo. entity.nosend_alpha prevents sending of alpha. entity.nosend_light prevents sending of lightrange. entity.nosend_color prevents sending of red,green,blue. entity.nosend_uv prevents sending of u,v. entity.nosend_sound prevents sending entity sounds. entity.nosend prevents sending of any entity parameter. The flags can be switched on and off during gameplay. By fine-tuning the parameters to be sent, and doing entity effects and animation on the client side through proc_local instructions, the network traffic can be remarkably reduced and two or three times as much clients can be served. entity.local This flag indicates that the entity was created by create_local. entity.native This flag indicates that the entity was created on this machine. entity.client This flag indicates that the entity itself or it's creator entity was created by a remote client. dplay_latency (read only) Gives the round trip latency on the client. That's the approximate time, in milliseconds (ms), it takes a message to reach the server and be returned to the client. Latency time on a local network is normally in the range of 10..100 ms, while latency on the internet can be over 300 ms. This number can change throughout the session as connection conditions change. dplay_bps (read only) Gives on the client the approximate throughput, in bytes per second (Bps), for the connection to the server. This number will change throughout the session as connection conditions change. dplay_bpspeak (read only) Gives on the client the peak throughput, in bytes per second (Bps) for the connection to the server. This number will change throughout the session as connection conditions change. Dplay_latency, dplay_bps, and dplay_bpspeak are updated every 8 ticks and are indicated in the "net" column of the [D] panel on the client. dplay_smooth If set to 0, entity updates from the server are directly displayed on the clients, without prediction or smoothing. If set at 2 (default) or above, the position and angles of entities are predicted based on their last values received from the server. This produces smooth movements and rotations, but can lead to visible 'overshooting' when the server update frequency is low. If dplay_smooth is set to 3 or above, MDL animation is also interpolated on the client by predicting the frame and the inbetweening factor. If the model contains more than one animation cycle, frame prediction can sometimes fail, which leads to undesired 'jerks' if the server updates come in slow and irregular intervals. Therefore only use animation prediction when the server update rate is set to 1 tick per update or better. dplay_unreliable Determines whether the unreliable, but fast UDP protocol or the reliable, but slow TCP/IP protocoll is used for sending messages. 0 (default): UDP or TCP/IP depending on the message importance. 1 : Always use the UDP protocol. -1 : Always use the TCP/IP protocol. dplay_entrate Number of ticks on the server per entity update sent to the clients (default 1 = 16 entity updates per second). The higher this value, the less bandwidth is used, but the higher is the response time on player input. When setting this value to 0, entities are updated once per server frame, as it was the case before. When setting it to a negative value, entity updates aren't sent at all; only the server time is sent to the clients with a rate corresponding to the absolute of this value. dplay_pingrate Number of ticks on the client per keepalive message sent to the server (default 16 = one message per second). The keepalive message is used for detecting client disconnection on the server. Sending and receiving user-defined messages via the SDK The SDK now allows to use A5's send and receive functions for sending user-defined messages in a multiplayer environment. For this, the following function pointers were added: typedef struct { byte *save_block;// pointer to block of variables for save/load (not used) int save_size; // size of block of variables for saving (not used) long (*Exec)(long n,long p1,long p2,long p3); // DLLLIB internal use only // only available in A5.30 or above - first packet byte must be 17 (0x11) for user defined packets void (*SendPacket)(long to,void *data,long size,long guaranteed); // the send function of the engine void (*ReceivePacket)(long from,void *data,long size); // user provided function } ENGINE_INTERFACE; void (*SendPacket)(long to,void *data,long size,long guaranteed); sends a user defined packed from the client to the server, or vice versa. Parameters: to - Identifier number for the client to receive the message. Set to 0 for sending to all clients. data - Data packet to be sent. First byte must be 17 (0x11) for identifying this as a user-defined packet. size - Size of the packet in bytes. guaranteed - set to 1 for TCP/IP mode, 0 for UDP mode. void (*ReceivePacket)(long from,void *data,long size); Set this variable to a user provided void(long,void*,long) function that receives and interprets messages sent with SendPacket. Parameters: from - Identifier number of the client who has sent the message. If at 0, the message was received from the server. data - Data packet to be sent. First byte is always 17 (0x11) and identifies this as a user-defined packet. size - Size of the packet in bytes. Note that the receive function should be very short and mainly just store the message, for not interfering the receive process. It must not send, open a file, render, or do anything time consuming. New multimedia player ================================================= The old MIDI and AVI player was replaced by a new streaming player that uses DirectShow 8.1 for playing all sorts of multimedia files in fullscreen or window mode, on panels, or even on textures of sprite or model entities. media_play(string,bmap,volume) (partially Commercial Edition) media_loop(string,bmap,volume) Plays a movie or audio stream on the screen or on a texture or panel. Media_play plays the stream once, media_loop repeats it until it is explicitly stopped. As many movie, sound or music files as supported by the hardware can be played simultaneously - for instance, to play two midi files at the same time you'd normally need two sound cards. All files playable with the windows media player can be used with this instruction - .avi, .mpg, .wmv, .wma, .wav, .mid, .mp3, .ogg and so on, even some still image formats like .bmp or .jpg. Parameters: string - The name of the multimedia file. The file must exist in the game folder, it can not be contained in a resource. bmap - The bmap that serves as target texture for the video stream. It must be a texture without alpha channel, like from a .pcx or .bmp image. If at NULL, the video is played on the whole window or screen. volume - The individual audio volume of the stream, 0..100. The master volume for all streams is controlled by the midi_vol variable. Changes: media_handle - this variable is automatically set to the handle of the last played movie or audio file. Returns: 0 if the file was not found or could not be played, otherwise a handle to the playing stream. Speed: Slow. Examples: media_play("news.avi",bmap_for_entity(tv_model,0),100); handle = media_loop("ribanna.mid",NULL,50); Remarks: - Full multimedia support is only available in the commercial edition and above; the lower editions only support playing .wav and .mid files. - License restrictions apply to some file formats, like .mp3 or DivX. Check required license fees before including such files in your game. - Keep movies as small and low-res as possible. The media_play instructions use the Microsoft CBaseVideoRenderer filter. If a movie has a higher resolution or frame rate than the PC can decode in real time, frames will be dropped, possibly resulting in low frame rates, flickering, and loss of synchronisation between video and sound. If the movie has no audio, or the volume is set at 0, loss of synchronisation is preferred over dropping frames. - For playing .ogg files, an installer for Ogg Vorbis DirectShow filters (oggds0994.exe) is included. Install them by starting the exe. The Ogg Vorbis filter was created by Tobias Waldvogel (http://tobias.everwicked.com) and can be freely used and distributed for private and commercial purposes. - The target bitmap for video streams can have any size, and can also be displayed with transparency or overlay flags. Alpha channel bitmaps that are created through setting the flare flag or using a TGA image can't receive video streams. - Some media types, like still images, stream endlessly and must explicitely be stopped by media_stop(). - Two movies can not be played simultaneously onto the same bitmap. The 'older' movie is automatically stopped in that case. See also: media_pause, media_playing, media_start, media_stop, media_tune, media_layer, media_handle, num_mediastreams. media_layer This variable determines the layer (default 900) on which fullscreen multimedia is played. When set to a low value, panels or text can be placed on top of the playing movie. Example: media_layer = 0.5; // layer between the camera and any panels num_mediastreams This variable gives the number of currently playing movie and audio streams for testing purposes. Because some types of media streams play endlessly and others don't, carefully observe this variable during development for avoiding frame rate drops due to too much open streams. media_handle This variable is set to the handle of the last played movie or audio file, in order to modify or stop it without explicitely having stored a handle. media_pause(var handle) Pauses the multimedia stream with the given handle. media_start(var handle) Resumes the paused multimedia stream with the given handle. media_stop(var handle) Stops and closes the multimedia stream with the given handle. If rendering to a bmap, the last image stays on the texture. If 0 is given as handle, it stops all playing streams. media_playing(var handle) Returns the frame number if a movie stream or audio stream with the given handle is currently playing, otherwise 0. media_tune(var handle,var volume,var rate,var balance) Changes the audio volume, playback rate, and audio balance of a movie or audio stream. Parameters: handle - The handle of the stream, which was returned by media_play or media_loop. volume - The new audio volume (0..100) for the stream. If at 0, the previous volume remains unchanged. The master volume for all streams can be set through the midi_vol variable. rate - The new playback rate as percentage of the original rate. Thus, 100 is normal playback speed, 50 is slow motion at half speed, and 200 is quick motion at twice speed. For audio streams, changing the rate also changes the pitch. If at 0, the previous playback rate remains unchanged. balance - The new audio balance (-100..+100). Negative values move the sound source to the left speaker, positive values to the right speaker. If at 0, the previous balance remains unchanged. Returns: The handle if the instruction was successful, otherwise 0. Speed: Medium. Example: // play a silent fullscreen movie at half speed media_tune(media_play("silent.mpg",NULL,0),0,50,0); PLEASE NOTE: The media stream instructions replace the old play_moviefile, play_song, play_song_once, snd_playfile, and snd_loopfile instructions. Because the DirectX8-based streaming player can not coexist with the previous .mid and .avi players, but can also not fully emulate the old instructions, play_song, play_song_once, play_moviefile, and the related variables won't be supported anymore in the new A5 version. They won't issue a script error message, but they won't play anything either. Replace them by media_play and media_loop. The snd_playfile and snd_loopfile instructions will still work, but we also recommend to replace them by the new instructions. cdaudio_vol (Commercial Edition) This variable sets the playback volume of the CD player (0..100, default 50). Rendering onto a texture ================================ (Pro Edition) By setting a view's bmap parameter to a bmap, the view is rendered onto this bmap when it's visible flag is set. This way, remote cameras can be created that render onto monitors somewhere in the level. Example: remote_camera.bmap = bmap_for_entity(monitorsprite,0); remote_camera.visible = on; Remarks: Several views can be rendered onto the same texture, and are sorted according to their layer parameter. The view's pos_x/pos_y and size_x/size_y parameters affect the position on the target bmap, instead of the position on the screen. The original content of the texture is lost. A bmap once used as render target must be purged before it can be locked or used as a target for video streams. The bmap must not be larger than the current screen resolution. If the bmap size is not a power of 2, than the next power of 2 must not be larger than the current screen resolution. New Save/Load system ================================================== The previous save, save_info, load, and load_info instructions are replaced by a more flexible save/load system that allows selection of the objects to save and load. game_save(string name,var number,var mode) Saves the current state of a game or application. Parameters: name - the file name for the saved state. number - a number appended to the file name (3 digits maximum). The extension ".sav" is appended after the number. mode - gives one or more of the following modes which can be combined by adding or subtracting: SV_VARS - saves all user-defined variables except for var_info and var_nsave. SV_INFO - saves all variables defined by var_info. SV_SYS - saves all predefined variables. SV_STRINGS - saves all changed strings. SV_POINTERS - saves all pointers. SV_BMAPS - saves all changed bmaps. SV_KEYS - saves all function assignments to keys or mouse/joystick buttons. SV_FUNCTIONS - saves the current state of all running functions. SV_PANELS - saves all panels and texts. SV_VIEWS - saves all views. SV_SKY - saves all sky entities. SV_LEVEL - saves the current level and all level entities. SV_ALL - saves everything above. Returns: A positive number if the instruction was successful, and zero or a negative number if the game could not be saved for some reason. Speed: Slow. Examples: // saves everything except var_info variables to "test7.sav" // does the same as the previous save() instruction result = game_save("test",7,SV_ALL-SV_INFO); if (result <= 0) { print("Save Error!"); } // saves var_info, strings, and bitmaps to "info0.sav" // does the same as the previous save_info() instruction game_save("info",0,SV_INFO+SV_STRINGS+SV_BMAPS); game_load(string name,var number) Loads a previously saved game. Parameters: name - the file name to load. number - a number appended to the file name (3 digits maximum). The extension ".sav" is appended after the number. Returns: A positive number if the instruction was successful, and zero or a negative number if the file could not be found or contained invalid content. Speed: Slow. Example: // resumes the game saved under "test7.sav" if (game_load("test",7) <= 0) { print("Load Error!"); } Miscellaneous C-Script Instructions =================================== Ogg Vorbis player (Commercial edition) Additionally to .wav files, .ogg files can now also be defined as sound files and played with all snd_... instructions. Ogg Vorbis is a new audio compression format. It is roughly comparable to other formats used to store and play digital music, such as MP3, VQF, AAC, and other digital audio formats. However, .ogg sounds are played in better quality than .mp3 sounds. Unlike MP3, Ogg Vorbis is license free. Tools for creating .ogg files can be found at www.vorbis.com. file_cpy(string destname,string srcname) Copies or unpacks the file "srcname" to the file "destname". The source file is first looked for in the SAVEDIR, then in the game directory. If it is found in neither and its name has the extension ".pak", it is also looked for in the WRS resources. This way files can be unpacked from a resource and renamed to their original file extension. If a file with the name "destname" already exists in the SAVEDIR, it will be overwritten; otherwise it is created. Parameters: destname - name of the destination file, without path. srcname - name of the source file, without path. Returns: A pointer to the string destname if the operation was successful, otherwise 0. Speed: Slow. Examples: // copies office1.sav to office2.sav file_cpy("office2.sav","office1.sav"); // unpacks a packed text database file from the game resource string db_name = ; // compile the database to the resource ... file_cpy("database.txt",db_name); // unpack and rename it See also: file_rename, file_delete. file_rename(string oldname,string newname) Renames the file "oldname" in the SAVEDIR folder to "newname". If a file with the name "newname" already exists, the operation will fail. Parameters: oldname - original name of the file. newname - new name of the file. Returns: A pointer to the string newname if the operation was successful, otherwise 0. Speed: Slow. Example: // renames office2.sav to office3.sav file_rename("office2.sav","office3.sav"); file_delete(string name) Deletes the file "name" from the SAVEDIR folder. Parameters: name - name of the file to delete. Returns: A pointer to the string name if the operation was successfull, otherwise 0. Speed: Slow. Example: // deletes office3.sav file_delete("office3.sav"); String functions return values The string functions str_set, str_cat, str_for_asc, and str_for_num now return a pointer to the changed string if the operation was successful, otherwise 0. This allows to concatenate strings in a single line, like this: string name_str[80]; string num_str[10]; ... // create the string "123" str_cat(str_cat(str_cpy(test_str,"1"),"2"),"3"); // copies office1.sav to office2.sav file_cpy(str_cat(str_cat(str_cpy(test_str,"office"),str_for_num(num_str,2)),".sav"),"office_1.sav"); Screenshots are saved in BMP rather than PCX format. ent_frames(entity) ent_skins(entity) Returns the number of frames or skins of the given entity. Example: // animate an entity by changing its frames action animate { while(1) { my.frame += time; if (my.frame > ent_frames(my)) { my.frame -= ent_frames(my); } wait(1); } } bmap_for_entity(entity ent,var frame) Returns a bmap pointer for the texture of a given entity. Parameters: ent - a sprite, model, or terrain entity. frame - number of the frame or skin whose texture is to be converted to a bmap pointer. If at 0, the entity's current frame or skin is used. Returns: A pointer to a bmap if the operation was successful, otherwise 0. The bmap contains the entity's first mipmap texture. Bmap operations, like bmap_for_screen, can be applied to that pointer, but if assigned to other objects (like panels) it is not saved by the game_save instruction. Speed: Fast. Example: // captures a screenshot into a sprite bmap_for_screen(bmap_for_entity(my,0),1,0); scan_entity(...) Sets the you pointer to the nearest entity with enable_scan set. If none is found, the you pointer is set to NULL. The you pointer won't change when compatibility is set at below 2. ang_add(vector angle1,vector angle2) Adds two angles quaternion-style for rotating an arbitrary oriented object or view. Parameters: angle1: The pan/tilt/roll euler angle which is rotated by angle2. angle2: The pan/tilt/roll euler angle by which angle1 is rotated. Speed: Medium. Example: // Let a camera chase a target entity and rotate with it. // The target is always kept in the center of the view. var cam_dist[3] = -500,100,100; // xyz position of camera to target function chase_camera(target) { my = target; // the target entity // calculate the camera view direction angles to the target var cam_ang[3]; // direction angles of camera to target vec_diff(temp,nullvector,cam_dist); vec_to_angle(cam_ang,temp); cam_ang.roll = 0; // roll is unchanged by vec_to_angle // permanently update the camera position and angles while (1) { // place the camera at the right position to the target vec_set(camera.x,cam_dist); vec_rotate(camera.x,my.pan); vec_add(camera.x,my.x); // set the camera angles at the camera view direction vec_set(camera.pan,cam_ang); // and rotate it by the target angles ang_add(camera.pan,my.pan); wait(1); } } Remarks: This function replaces ang_rotate(), which erroneously rotated the second angle by the first one, instead of vice versa as you would expect. On adding angles the order does matter. For compatibility reasons, ang_rotate was not fixed, but replaced by ang_add. Miscellaneous Object Parameters ======================================= entity.u entity.v Texture u/v offsets are now also implemented for model, terrain, and sprite entities. Note that the skin or texture must be a power of 2 in vertical and horizontal size for applying an offset. Example: action moving_terrain { while (1) { my.v += time; wait(1); } } entity.uvspeed If this entity flag is set, a texture offset speed can be given for the entity through the speed_u and speed_v parameters. Note that this is mutually exclusive to giving a texture u/v offset. The skin or texture must be a power of 2 in vertical and horizontal size. Moving textures this way is faster than by changing the offset, especially in a multiplayer game where offset changes had to be communicated to the clients. Example: action moving_terrain { my.uvspeed = on; // necessary for setting speed_u and speed_v my.speed_v = 1; } view.arc The lower limit for a view arc is now 1 degree (was 10 degrees before). This allows for a 10 times higher zoom factor. terrain.frame Terrain can now be animated through it's frame parameter. The collision detection uses the current frame instead of the first one. Use collision detection functions for preventing objects from falling through the terrain when it's triangles animate upwards. Particle colors now behave the same way as screen and sky entity colors: They have their medium and default value at 128. Values of 129..255 will make the particle brighter, values of 0..127 will make it darker. Until now, particles could only be darkened and 255 was the medium value. The old behaviour can be temporarily restored by setting the compatibility variable at below 2. skill_a,skill_b,skill_c,skill_d Four more particle skills, if skill_x..skill_z aren't enough. Entity lighting (Commercial Edition) Entities now also reflect the color, and not only the brightness, of the static lights on floor below them. If the unlit flag of an entity is set, it does not calculate anymore the environment color when its position changes. So when moving a lot of entities, set their unlit flags for maintaining a high frame rate. Miscellaneous C-Script Variables and Pointers ========================= Watched For debugging purposes, an entity can be permanently watched by setting the predefined WATCHED entity pointer to this entity. Example: watched = my; // observe this entity Important parameters of the watched entity are permanently visible in several lines on the screen: -Typ, handle number, name -Position, angles, scale -Ambient, albedo, alpha, rgb, frame, next_frame, skin -Flags -Actions performed by this entity, and event function -Ground below the entity, and ground surface number and texture While single stepping through a function, the entity parameters are displayed below the debugger display. For switching off the parameter display, set the WATCHED pointer to NULL. function* same as action*. max_loops This variable sets the sensitivity of the endless loop detector in the development version. The less the value (default = 5000), the earlier the detector warns about a possible endless loop. Set it at 999999 if you are using huge loops in your application. d3d_alphadepth (Commercial edition) determines the color depth (16 or 32) of TGA bitmaps and sprites. The new 32 bit mode produces a smooth look without banding, but twice the video memory is consumed. This variable must be redefined at the beginning of the script; it can't be set during gameplay. Example: var d3d_alphadepth = 16; // sets TGA files to 16 bit mode d3d_shadowdepth (Commercial edition) determines the color depth of the shadow maps - 16 or 24 (default) - of the WMB6 format. In 24 bit mode the shadows are smoother, but consume 50% more video memory than in 16 bit mode. This variable must be set before level loading. Example: d3d_shadowdepth = 16; // sets shadows to 16 bit mode d3d_nobsp If this variable is set to 1, BSP tree culling is partially switched off in D3D mode. This reduces the frame rate in most cases because the only remaining culling is performed by the portal algorithm. For testing purposes only. d3d_vbuffersize determines the default size of the vertex buffers. Theoretically the performace is the better, the higher the size; however we measured the best performance at the default value of 128. d3d_lockable If this variable (default 0) is redefined at 1, the frame buffer will be lockable. This can reduce the frame rate on some 3D cards. mip_flat, mip_shaded now work in all mipmapping modes for adjusting the mipmap distance in the range 0..2 (default 1.0) for flat and shaded surfaces. Example: mip_shaded = 1.5; // increase mipmap switching distance by 50% mip_flat = 1.5; tex_color.red,tex_color.green,tex_color.blue (Commercial Edition) After a trace instruction with scan_texture set, this color vector returns the color of the static light shed on the target texture. doppler_factor This variable gives a factor for the doppler shift, which modulates the frequency of moving sound sources. This way the sound speed can be adjusted to the level scale, or to the medium the game plays in. For instance, under water the doppler factor is lower than in air. A setting of 1 (default) gives a doppler factor for air at a scale of 2.5 cm per quant. At 0 the doppler shift is switched off. max_entities The maximum number of entities in sight range is now also controlled by max_entities. num_entities This variable display the current number of level entities. It is shown in the "num" column of the [D] panel at the last-but-one place. mouse_pointer This variable determines the look of the windows mouse pointer when over the application window. 0: The mouse pointer is always switched off over the window. 1: The mouse pointer is switched off when mouse_mode is activated and a mouse_map is set, otherwise it's a hand (default). 2: Like 1, but the mouse pointer is the standard arrow. 3: Like 1, but the mouse pointer is a crosshair. 4: Like 1, but the mouse pointer is a hourglass. sky_map, cloud_map These bmap pointers are set to the level's original sky and cloud texture at level loading. They can be reset after loading a level to prevent that the level's sky textures are rendered behind sky entities, and thus reduce the frame rate. Example: sky_map = NULL; cloud_map = NULL; time_factor Until now, the slow motion effect was limited to a time value of 0.05. Now it can be set as low as 0.001. compatibility This variable is now at 2 by default. Setting it to a value lower than 2 will switch back A5 to the following behaviour of the previous version: - scan_entity won't change the you pointer. - writing the 13 character into a file will produce an additional 10 character, and file_copy won't work. - sky models appear twice as bright as other sky objects. - screen entities and particles can't be made brighter by their color, only darker. The default color value will be 255 instead of 128. WED/MED improvements ================================================== Milkshape import/export filters for MED (Commercial Edition) MED can now use Milkshape's import and export filters for importing and exporting models made in virtually every 3D format. For this, there's a new subfolder 'ms' that contains two DLL files: cpi01.dll and msModelLib.dll. For installing a Milkshape filter, simply copy the DLL into the ms subfolder. Once you have installed a filter, you can open models made in the corresponding format, and save them as GameStudio MDLs. Please note: - Do not copy Milkshape's original msModelLib.dll - instead use GameStudio's msModelLib.dll that's already in the ms folder. - Do not copy msPSKExporter.dll - it will crash. - Some filters, like msASCIIExporter.dll and msASCIIImporter.dll, test whether Milkshape is running. So you have to start Milkshape before importing or exporting a model. - If a filter supports multiple materials, MED will try to merge them into a single skin. This works in some cases and fails in others. - Bones animation import is not implemented yet. We'll make this work in a future version. Bones animation export won't be supported. You can download the Milkshape import/export filters from the links on the Milkshape download page, and from the Milkshape program folder when installing the Milkshape demo (see link page). Despite the filters on the download page are free, when you use them please support this great model editing software by registering Milkshape. New MED toolbars Med has now gotten new toolbars, so the user interface is a little different now (see MED manual). MED frames toolbar The frame name can now be entered directly into the name field. MED hide/unhide buttons These buttons allow better working on certain parts of the model by setting the rest of the model invisible. [Hide Selected] hides the selected part of the model [Hide Unselected] hides the unselected part of the model [Flip] Hides the previously unhidden part of the model [Show all] Shows the whole model Unlimited terrain The terrain size limit in MED of 100x100 vertices was removed. On importing a height image for terrain, the triangle size can now be controlled independently on the vertex count. Model skins and frames MED now stores TGA skins in 32 bit color depth, rather than 16 bit. Models with up to 10000 frames can now be imported (the previous MED limit was 3000 frames). High resolution static lights (Pro edition) When setting the hires flag of a light in WED, the shadows cast by this light are rendered in double resolution. The advantage is that shadows look better this way, and small shadow faults (see WED tutorial) are less visible. The disadvantage is that the WMB file becomes larger, lightmap calculation needs 4x longer for those lights, and the high resolution lightmaps consume 4 times the video memory as with low resolution. Duplicate offset ... can now be adjusted in WED/File/Preferences. Less than 4 LOD levels If a lod level is omitted, the next higher LOD level is used. This way, for instance, when an entity has only LOD levels 0 and 3, level 3 is now also used for the LOD distances of levels 1 and 2. Until now the entity was invisible in this distance range. -gamma x This map compiler option sets a gamma factor for the shadow maps (default = 1.5). The higher the gamma factor, the brighter the lights. -zoomlevel x This map compiler option scales the level up by the factor x before BSP tree calculations, and scales it back down afterwards. This helps preventing missing geometry if blocks are too small. It's more of a workaround and should not be used for production because it can introduce additional portals and reduces the maximum size of the map. -autozoom makes the map compiler search for an optimal scale factor (see -zoomlevel below). The map compiler tries integer scale factors 1,2,3,... up to the factor X specified by "-zoomlevel X" (if -zoomlevel was not specified X will default to 10). The first factor that allows the blocks to be read properly will be used. Note that errors during surface tesselation might still occur- as this parameter only checks individual blocks, not their intersection. Example: Create a new level, and add the prefab plants/bonsai01.wmp. When compiling this level some (harmless) warnings will appear. Now bring up the Build dialog and enter the option: "-autozoom". The compiler now tries zoomlevels 1..10 and stops at the earliest acceptable scale which is 4 (with HiPrec). If you want to speed up future builds you can just enter -zoomlevel 4 to get the same result. -nod3dlmap This command line option tells the map compiler to compile 16 bit lightmaps instead of 24 bit, which is now the default (-d3dlmap must not be given anymore). The wmb file becomes a little smaller, but the shadows look not as good, and high resolution lights won't work with 16 bit lightmaps. ======================================================================= New features implemented in A5 5.240: ======================================================================= WED nugde function The selected object or group can now be moved, rotated, or scaled with the cursor keys. WED - block and surface flags Block and surface flags, like detail or smooth, can now be applied to all blocks of the selected group through the group properties panel. New WED rendering module A new rendering module GXL_DX81 was included, which can be selected for the 2D as well as the 3D windows through WED->Preferences. When right clicking onto the 3D view and selecting 'GXL Properties' you can adjust the effect of the sun light and the light sources in the 3D window. You need DirectX 8.1 for using this renderer. Terrain and model mipmapping Terrain and model polygons are now displayed with mipmapping. To create mipmaps for a model or terrain, open the skin editor in MED and select Convert Skin->Add Mipmaps. Then save the model. The model or terrain surface texture must not be bigger than the 3D card's limit - normally 1024x1024 - otherwise mipmaps won't work. MED - New Terrain (Extra edition or above) Terrain can now be created by MED without having to import a height image. MED - Magnet Tool (Extra edition or above) For editing terrain, MED has a new 'magnet' tool for shaping hills and valleys. Move the magnet over the terrain. Pressing the left mouse key moves the selected vertices under the magnet upwards; the right mouse key moves them downwards. You can control the range, strength and form of the effect in the "Magnet Tool" window that pops up when you select the tool. Terragen support, static terrain shadows MED can now also import the Terragen RAW 8-bit format for terrain. Terragen can also be used to create a terrain skin with static shadows. Set the camera position in terrain units at 128,128,1024, the target at 128,128,0, and the zoom at 8. Now an image with shadows is rendered which can be directly used as the skin for the terrain. Detail maps for terrain If the camera is allowed to get too close to terrain, the surface texture becomes a blurry mess due to the high magnification. For adding little details, like bumps and cracks visible at close distance, a detail bitmap can be added to a terrain entity. For adding a detail bitmap, perform the following steps: - Open the MED skin editor - Create a second skin - Select the second skin - Import the bitmap that should become the detail map - Uncheck "adapt skin points" when the requester pops up - Select "Convert Skin -> Add Mipmaps" - Save the terrain The detail bitmap should be small (like 64x64), tiled, true colour and medium bright. It must have a different size than the normal skin for being recognized as detail map. An example (detail.pcx) is included in the template folder. The predefined detail_size variable gives the number of detail pixels per terrain surface pixel (default 4). Example: detail_size = 10; This way the terrain looks much better even when a lower resolution surface image is used. Note that some old video cards (like Voodoo3 or ATI Rage) don't support detail maps. When detail_size is set at 0, detail maps are switched off. -jitter x Command line option for the map compiler. When compiling in preview mode, a light sample is taken every 16 texels. When preview is disabled, 4 lightsamples are taken and then averaged into a single lighttexel. The -jitter x command line parameter (with X being an integer [0..8], default: 8) 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. No self check (Pro edition only) The -nc command line option prevents the engine from checking itself for possible virus or hacker tampering at game start. This way, the EXE can be 'wrapped' into another program for using the registration/ unlock feature of some distribution channels. -black This command line option sets the startup window to a red text on black background. Otherwise it's a black text on white background. If an acknex.wdf file is found in the game folder, the window definition in this file overrides the -black option (professional edition only). Abort During compilation, the engine aborts immediatley when [Esc] is pressed (development version only). Local variables Var definitions can now also be placed inside functions. This creates a local variable. Local variables are only valid within the scope of the function - they are unknown outside the function. If a global variable with the same name as a local variable exists, the local variable has priority. Example: function beep_seven_times() { var i = 0; // define and initialize a local variable while (i < 7) { i += 1; beep; wait(1); // local variables keep their value during wait } } This feature does not sound very exciting, but it's a major improvement for better and more elegant C-Scripts. If many copies of the same function are running, which is normally the case with entity actions, each copy uses its own independent set of local variables. Local variables can completely replace the entity skills, except for setting entity properties in WED, or for communication between entities. Note: Variables are always initialized (by default to 0). So if you define a local variable inside a loop, be aware that it is initialized at each loop repetition, which is probably not what you intended. So define local variables always at the beginning of the function, like in C. Restrictions: Arrays can be used for local variables, but only with the dimension 3. Local arrays can not be initialized (they are always initialized to 0), and can not be passed as vector parameters to other script functions. Local variables cause a small performance penalty on calling their function, and on saving or loading. They can not be used for particle functions. Unlimited length strings Strings can now be defined without a default length and content. In this case the string gets a default length of 32 chars, but the str_cpy and str_add instructions can change or increase the length of the string without limit. Disadvantage: str_cpy, str_cat, and save/load instructions are a little slower with those kinds of strings. Example: string tstring1; // define an unlimited length string function stringtest { var i = 10; str_cpy(tstring1,"12345"); while (i > 0) { str_cat(tstring1,"abcd"); // increase the length of the string i -= 1; } } str_cmp(string1,string2) Like str_cmpi, but compares the strings with case sensitivity. sleep(var seconds) Suspends execution of the function, and resumes after the given number of seconds is elapsed. Like waitt(), but with seconds instead of ticks. If the given time is less than half a frame time, the function won't be suspended at all. Sleep() will replace waitt(), which was often confused with wait() and thus wrongly used. diag(string) Prints the string into the acklog.txt file when the -diag command line option is given. effect() When executed on a client, creates a local particle effect which is only visible on the client. Until now particle effects were global and could only be created on the server. var dplay_clienttimeout Sets the number of ticks after which a client is automatically disconnected when he does not respond. Default: 80 (5 seconds). Multiple servers ...can now be started on the same machine in standalone TCP/IP mode (Pro Edition only). Different session names and different port addresses must be used when starting multiple server instances. Server console When starting in server mode (-sv), the -diag output is now printed into a server console window. This way it's possible to observe on the server which clients connect or leave, and what's happening in the game. dplay_entupdate This variable controls the automatic update of entities from the server to the clients in multiplayer games. 0 - no entity updates are sent (for user-made entity update functions). 1 - entity parameters are sent once at client connection. 3 - entity parameters are sent at client connection, and when they change during gameplay (default). send_var_to(entity,var); send_string_to(entity,string); Like send_var and send_string, but when executed on the server it sends the variable or the string not to all clients but only to the client who has created the given entity. When executed on the client it sends the variable or string to the server, regardeless of which entity is given. The var or string is sent in reliable mode unless dplay_unreliable is set. Scripts in additional resources Until now, only the main resource file could contain script files. Now script files can also be packed into additional resources included with the "resource" statement. This way, scripts can be distributed to GameStudio users who can use, but not edit or read them. ent_blend(string, var anim_percent, var blend_percent) Interpolates the MY model entity's frame between a source and target frame. Parameters: string - animation name of the target cycle. anim_percent - percentage of the target cycle. blend_percent - blending percentage between source and target. Changes: my.frame - set to source frame plus interpolation factor. my.next_frame - set to target frame. The source frame is the current frame which can be set by another instruction before. Note that the source and target frames themselves are not interpolated - the instruction 'snaps' to the next full frame. Example: Sets the entity to a frame within 50% of the walk cycle, and then blends over to the first frame of the stand cycle. ent_cycle("walk",50); ent_blend("stand",0,25); The result of this code is an interpolated frame that is mixed from 75% of the middle of the walk cycle and 25% of first frame of the stand cycle. D3d_fogcolor1..d3d_fogcolor4 These 4 predefined color vectors determine the 4 fog colors in D3D mode. They are set at loading a level to the level's 4 fog colors, but can be adjusted afterwards to change the fog color in real time. Example: d3d_fogcolor1.red = 255; d3d_fogcolor1.green = 0; d3d_fogcolor1.blue = 255; // sets purple fog fog_color = 1; // activates the purple fog nofog This flag now also works with fog ranges, and switches fog completely off instead of reducing it. Render_sky, render_world, render_entities DLL functions can be assigned to these function synonyms, for drawing onto the screen at certain places of the rendering pipeline. Render_sky will draw before anything else is drawn. Render_world will draw after the engine has finished drawing the level. Render_entities will draw after the engine has finished drawing the entities, and before panels and view entities are drawn. Example: dllfunction extra_entities(); render_entities = extra_entities; define Tokens redefined to a certain value, like in "define resolution,1024;" now react on ifdef. Previously an "ifdef resolution;" in the above example would skip the following lines, now it will parse them. Note that this can lead to different behaviour of scripts when ifdef's were used in a wrong way. proc_kill(var mode) Replaces EXCLUSIVE_ENTITY and EXCLUSIVE_GLOBAL. Parameters: mode = 1 terminates all functions created by the MY entity. mode = 2 terminates all functions created by the YOU entity. mode = 4 terminates all other instances of the current function. Modes can be combined by adding. ent_playloop(entity,sound,var volume) Like ent_playsound, but the sound is looped endlessly until either the entity is removed, or the sound is stopped by snd_stop(). Paramters: entity - pointer of the entity that plays the sound sound - sound to be played volume - sound volume in percent (0..100) The sound is played with doppler effect due to the entity's position and speed. Its volume and frequency can be tuned with snd_tune() - the balance of a 3D sound can not be tuned. The same restrictions as with dynamic lights apply: not more than 32 entity sound loops can be played at a time. If more are started, the sound loop farthest away from the camera is removed. Example: Plays a sound and then modulates its volume with a sawtooth function. var whosh_handle; whosh_handle = ent_playloop(my,whosh,100); // modulate the entity sound volume while (1) { ifndef SERVER; // don't snd_tune on server, sounds play on client snd_tune(whosh_handle,(10*total_ticks)%100,0,0); endif; wait(1); } sound instructions Until now, sounds were only played when their volume was non-zero. This restriction was removed now - only inaudible sounds can now be played, in order to tune their volume up afterwards. starter functions Starters are a special sort of functions that are automatically executed at game start, like the main() function. This way, scripts can have starter functions which for instance initialize script variables. The old A4 WDL instruction for renaming the main script was removed. Example: starter debug_main // automatically started if this script is included { debug_panel.visible = on; while (1) { // run forever debug_panel.pos_y = screen_size.y - 15; fps = 0.9*fps + 0.1/time; wait(1); } } Arrays in panel elements In digits, vbar, hbar, vslider, hslider, and window elements now also arrays can be used, instead of plain variables. Example: window = 200,0,40,20,compass_map,compass_pos[0],compass_pos[1]; Note that the indices must be numbers - further variables or expressions can't be given here! Vglide This vector gives the amount of gliding along walls after an ent_move instruction. If the entity didn't glide along a surface, the vector contains zero. video_switch(var res,var depth,var window) replaces switch_video() and can be called from a DLL. It returns either the new video mode number or 0 if this mode was not available. transparent sky layers TGA images can now also be used for dome and scene skies. When the TRANSPARENT flag is set, sky layers appear translucent according to their alpha value, and thus can be smootly faded in and out. inkey_active This variable is at 1 when the inkey() function is active and expects keyboard input, otherwise 0. Inkey() can be terminated prematurely by setting this variable to 0 through another function. ent_nextpath() sets the MY entity onto the next path in the level if the entity already has a path assigned. Otherwise the MY entity is set to the first path in the level. Returns the number of points of the new path. Anisotropic texture filtering The d3d_anisotropy variable gives the maximum level of anisotropy (default = 0 = no anisotropic filtering). Anisotropic texture filtering is supported by some newer 3D cards and eliminates the distortion visible in the texture whose surface is oriented at an angle with respect to the plane of the screen. Set the variable to a value greater than 1.0 for activating anisotropic texture filtering. Example: d3d_anisotropy = 2; // activate Panel pointer The panel pointer is passed as a second parameter to the button function when a button is clicked. DLL SDK The level palette can now be accessed in the following struct: typedef struct { byte *bytes; // pointer to frame buffer (only valid after Lock) int pitch; // size of a horizontal line in bytes (!= width!) int width,height; // width, height of the screen int bpp; // bytes per pixel of the frame buffer BOOL (*Lock)(void); // lock frame buffer before accessing it void (*Unlock)(void); // unlock frame buffer after accessing it void *pd3ddev; // pointer to the IDirect3DDevice7 used by A5 // only available in A5.12 or above HWND hwnd; // handle of the engine window // only available in A5.21 or above byte *palette; // level palette in byte[768] format } FRAME_INTERFACE; Blended animation The template scripts now blend between different player animations. The warlock in the office has the new animation assigned. New actor AI The new actor_ai_one function is a new improved AI actor that can be attached to entities in your level. Designed to be faster, smarter, and easier to modify, the new AI actor uses the 'blended' animation techniques and has improved obstacle avoidance and weapon code. As the suffix 'one' implies, this is the first of a series of improved AIs. The following values can be set to modify this AI to fit your needs. Default values, which are given in '()'s, are the values that will be used if the value is set to 0 in WED. _WALKSWIM_DIST, SKILL1; // Walk Distance . Swim Distance _RUNCRAWL_DIST, SKILL2; // Run Distance . Crawl Distance _STANDJUMP_TIME, SKILL3; // Stand Time . Jump Time _ATTACKDUCK_TIME, SKILL4; // Attack Time . Duck Time _RUNTHRESHOLD, SKILL14; // Run Threshold _FORCE, SKILL5; // Force (1.5) _HITMODE, SKILL6; // Hitmode (actor only) _FIREMODE, SKILL8; // Firemode (DAMAGE_SHOOT+FIRE_PARTICLE+HIT_FLASH+0.10) _HEALTH, SKILL9; // Health (75) _ARMOR, SKILL10; // Armor (0) _ALERTNESS, SKILL11; // Alertness.AlertCone (1000.180) _ACCURACY, SKILL12; // Accuracy (5) _COWARDICE, SKILL13; // Cowardice (30) _MUZZLEATTACH, SKILL15; // Muzzle vertex . Attach vertex _WEAPONRANGE, SKILL16 // range of the weapon (500) NOTE: You can use the flag "-d showaiboxes" described above to display AI bounding boxes around these entities. The new actor AI has a series of helper functions including the following: _actor_ai_explode: called if the actor explodes during death _actor_ai_death_one: handles death of the new AI (explosions, gibs, removal) _actor_ai_player_trace: traces to the player to see if we see them. _actor_ai_move_gravity: move the actor. Uses 'force' vector set in one of the functions below _actor_move_hunt_one: set the force in a way to encourage hunting _actor_ai_move_escape_one: set force to run away from player _actor_ai_move_attack_one: set force to attack player _actor_ai_avoid_obs: try to avoid obstacles by side stepping _actor_ai_shoot_one: use firing_mode and firing_range to shoot a weapon _actor_ai_handler_one: handle events (i.e damage done by explosions, gun shots) _actor_ai_loop_one: main AI loop. Switches between states and calls functions do_explosion(my_blast_range,my_blast_damage,my_graphic_type) This script function in weapons.wdl handles an explosion which does 'blast damage' by using scan_entity my_blast_range: range in quants of the blast my_blast_damage: max damage (damage goes from 100% at center to 0% at the edge) my_graphic_type: type of 'blast animation' to use (0 - sprite, 1 - model) An example of its use can be seen in the new action "demolition_pack". Jumping Uses new skill "_JUMPTARGET" (skill29) which is automatically set at the beginning of each player jump to the "jump_height" value (which can be changed at any time) minus the player's current height above the ground (a player can by up to 5 units above the ground and still be able to jump). The player's vertical velocity will be sqrt(2*gravity*jump_height) at the beginning of the jump gradually reduce to zero at the top of the jump (jump_height = player_height). A5 logo On common request, we've added two new A5 logos to the template folder: logodark.pcx and logolite.pcx. The new logos have "Made with 3D Gamestudio" replaced by "Powered by the A5 engine", which is said to sound more serious. ======================================================================= New features implemented in A5 5.20: New sky system Skies can now be composed from an unlimited number of sky entities, which can be either models or sprites. Models are used for sky spheres or sky boxes: sky space { type = ; flags = scene,visible; layer = 0; } This creates a sky sphere or box named 'space'. It is drawn into the background of the level. Sky spheres are automatically centered around the camera. An unlimited number of sky spheres can be combined. The drawing order is determined by their layer parameter. The same properties as for global entities, like colour, overlay, flare and so on, can also be used for sky spheres. They are not affected by level light and fog. In a similar way, sprites can be used for vertically projected sky and cloud domes: sky sky_purple { type = ; speed_u = 1; speed_v = 1.5; scale_x = 0.5; flags = dome,visible; layer = 1; } sky cloud_purple { type = ; speed_u = 3; speed_v = 4.5; flags = dome,overlay,visible; layer = 2; } The following parameters are valid for sky entities: Red, green, blue - light colour (default 255,255,255 = white) speed_u, speed_v - the movement speed of dome textures (default = 1) scale_x - the scale of dome textures, and the part of a full circle for scene textures. E.g. with a scale_x of 0.25, a scene texture is repeated 4 times around the horizon. pan, tilt - the rotation of scene textures. overlay flag - black parts are transparent scene flag - cylinder projection for sprites, infinite distance for models dome flag - vertical projection for sprites When neither the dome nor the scene flag of a sky sprite is set, the sprite is rendered into the background at its xyz position given. This way, sun or moon can be drawn onto the sky (D3D mode only). Sky sprites and spheres are also supported by the software renderer in 8-bit mode. However only one sky dome layer, one cloud dome layer, and one scene layer is visible in this mode, and the order is fixed. They can not be combined with sky spheres or boxes. Debug panel D3d_textotal was replaced by a more accurate display for the texture memory in the [D] debug panel. For optimizing frame rates, the time for rendering certain parts of the image is now indicated also. The new debug panel now displays in Column 1 - frames per second Column 2 - camera position (xyz) Column 3 - camera angle (pan tilt roll) Column 4 - mouse pointer (XY) Column 5 - video memory in KB used for script defined objects, wmb surfaces, wmb shadow maps, level models and sprites, and free memory available. Column 6 - number of visible level polygons, visible entity polygons, living particles, and running functions. Column 7 - time in ms per frame for level rendering, entity rendering, particle effects rendering, portals rendering, 2D elements rendering, vsync, and script execution. D3d_texfree Indicates the amount of texture memory still available on the 3D card. D3d_texmin When redefined, gives a minimum amount of texture memory that must be available on the 3D card for the game to start in D3D mode at all. Below this amount the game falls back to 8 bit mode. This way the end user is not forced to start the game manually in 8 bit mode when he sees a 'out of video memory' error message. Example: var d3d_texmin = 3000; // at least 3000 KB must be available on the 3D card D3d_texskins, d3d_texsurfs, d3d_texsmaps, d3d_texbmaps These variables contain the amount of video memory currently used for level models and sprites, wmb surfaces, wmb shadow maps, and script defined objects. Time_factor This variable (default 1) influences the internal timebase. When set below 1, a Max Payne style slow motion effect is achieved - above 1 it's a quick motion effect. Note that the script must be perfectly time corrected for this to work properly. shadow_offset gives the distance of the model shadow to the floor surface (default 2.5). clip_particles gives the clip distance for particles in clip_range units (default 0.5). Edition This variable gives the engine edition: 1 = Standard, 2 = Extra, 3 = Commercial, 4 = Professional. View.skyvisible, view.portalvisible These flags are automatically set in a view when the sky, or when a portal is potentially visible (it may be obscured by another objects though). Mouse wheel support The Z element of the predefined mickey vector contains the relative movement of the mouse Z axis - normally the wheel - during the last frame. The absolute wheel position can be determined by wheel += mickey.z; View entities If view entities share the same layer, they now also share the Z buffer. This way weapons can be composed from several view entities. LEVEL WED automatically includes entities from further levels into the published game folder or the resource when their WMP files are given by the LEVEL keyword in the script. Example: LEVEL "level2.wmp"; // include all entities from level 2 LEVEL "level3.wmp"; // include all entities from level 3 -diag now also is supported by EXE modules of published games. Better error messages When a script crashes due to a script bug, not only the function, but also the source line is now indicated. WED smooth shading (commercial & pro edition only) WED's SMOOTH texture flag softens static shadow edges by Gouraud shading, thus giving the impression of a round object - useful for columns. WED improvements The selected waypoint of a path is now indicated in the status line. In 'Preferences' a mode for automatically reloading modified scripts can be activated (still experimental). Objects can be locked against editing by 'Render Style / Disable'. Animated sprites are displayed with the frame width instead of the image width. WED multiple selection WED now allows to select multiple objects by drawing a frame around them, or by clicking with [Ctrl] pressed. Multiple selection with [Ctrl] also works in the objects window. With Group/Finish all selected objects are grouped. WED Resource (professional edition only) The new WRS format supports long file names of up to 22 characters. The 8.3 limitation for file names no longer applies. WED skill/flag display Instead of skill1, skill2 and so on, entity skills and flags now got meaningful names, depending on the action assigned to the entity. The script is scanned for define statements for that purpose. The corresponding action must be preceded by a //uses... comment. This is done with the door and elevator actions in the template script. WED texture preview The texture names are now visible in the preview. The texture thumbnail size can be selected between original size, 32x32, and 64x64. Both features can be switched on by right click and "show texture". WED Scaling When holding [Ctrl] pressed while scaling, the object is equally scaled in both directions. WED Intelligent selection When clicking onto an object in WED's 2D windows, WED now makes an intelligent guess which object could be meant when several are stacked over each other. This normally reduces the number of clicks for selecting a certain object. ======================================================================= New features implemented in A5 engine 5.15: New WED See Help/Tutorial about the new features. Extra Edition screen resolution The maximum screen resolution of the Extra Edition is now 1024x768. Second joystick Trough the vectors joy2_raw, joy2_rot, the button variables joy2_1..joy2_10, and the actions on_joy2_1..on_joy2_10, a second joystick ist supported. The variable num_joysticks gives the number of joysticks connected (0,1,2). bmap_preload(bmap) preallocates video memory for the given bmap even if it is not visible on the screen. bmap_for_screen(bmap,fac,offset) replaces the old freeze_map instruction. It can be called from a DLL, and can also copy 32 bit screens into a bmap. screenshot() now also saves 32 bit screens. DirectDraw Interface The dx struct of the SDK now contains a pointer to A5's DirectDraw interface: typedef struct { void *pdi; // pointer to the DirectInputDevice used by A5 void *pdimouse; // pointer to the mouse DirectInputDevice void *pdikbd; // always zero (keyboard doesn't use DirectInput) void *pdijoy; // always zero (joystick doesn't use DirectInput) void *pdplay; // pointer to the DirectPlay4 interface void *pdplobby; // pointer to the DirectPlayLobby2A interface DWORD pdplayer; // player ID void *pdpguid; // multiplayer session GUID void *pds; // pointer to the DirectSound interface void *pdsb; // pointer to the DirectSoundBuffer interface // only available in A5.14 or above void *pdd; // pointer to the DirectDraw7 interface } DX_INTERFACE; vec_for_min(vector,entity) vec_for_max(vector,entity) set the vector to the upper and lower boundaries of the current frame of the given model entity. This can be used to calculate an entities' bounding box more precisely than through its min_x...max_x parameters. Fps_lock If this flag is set, the time variable is locked to fps_max, independent of the real frame rate. randomize() Initiates the random() sequence with a random number. Otherwise the random() function always starts with the same sequence of numbers. Improved Mipmapping Through the new D3D_MIPMAPPING variable, two new hardware based mipmap filters can be activated in D3D mode: d3d_mipmapping = 0 -> Mipmapping deactivated d3d_mipmapping = 1 -> polygon mipmapping (old method) d3d_mipmapping = 2 -> scanline mipmapping d3d_mipmapping = 3 -> trilinear mipmap filtering (new default) Scanline mipmapping looks better than polygon mipmapping, but is not supported by some very old 3D cards, like Voodoo. Trilinear filtering looks even better, but is only supported by newer 3D cards. The D3D_MIPMAPPING variable must be set before level loading. It's default value is 3 when the 3D card supports scanline or trilinear mipmapping, otherwise 1. Fog range Through the view parameters fog_start and fog_end, a start and end range for fog in D3D mode can be given. There won't be any fog closer than fog_start; the world will be all foggy beyond fog_end. This way fog can be used to completely hide everything outside the clip_range. Example: camera.fog_start = 0.8 * clip_range; camera.fog_end = 0.9 * clip_range; Note that some old cards like Voodoo, or some Radeon versions, do not support Fog ranges, but only the old style fog strength. So take care that your fog is adjusted for both methods. When setting fog_end at 0, fog strength is used instead. Multiple distributable resources The new RESOURCE statement is similar to the PATH statement, but gives the name of a WRS resource file. Resource files are scanned in the order of their appeareance in RESOURCE statements. This way, files belonging to a game can be split into several resources. Another possibility is distributing a pack of WDL scripts or artwork to other GameStudio users without the possibility to extract and edit it. Such resources can be opened by all GameStudio editions, but created only be the Professional Edition. Example: resource "models.wrs"; resource "bmaps.wrs"; resource "warlock.wrs"; A separate resource file can be created through a WDL script consisting of BIND or other statements that give file names in <> brackets, like this: // warlock distributable resource bind ; bind ; action warlock { MY.FAT = OFF; MY.NARROW = ON; // set narrow hull MY._WALKFRAMES = 1; // enable frame name animation MY._FORCE = 0.5; // He should be not too fast MY._MOVEMODE = _MODE_WALKING; MY.__JUMP = ON; MY.__DUCK = ON; MY.__STRAFE = ON; MY.__TRIGGER = ON; player_move(); ent_morph(me,"warlock.mdl"); ent_create("staff.mdl",nullvector,staff_prog); } For creating such a resource, open a new project in WED, assign that BIND script in Map Properties, and perform a Resource function. The WRS file is created in a .CD subdirectory. In the original script, the files to be contained in separate resources should be given in "" instead of <> for preventing their inclusion into the main resource. If files with the same name are contained in several resources, the priority of the files depends on the order of their RESOURCE statement, beginning with the main resource. Note that files contained in resources still must have DOS-compatible names (max. 8+3 characters). print The print statement in a WDL file outputs the following text in the engine start window during script compilation (development engine only). This way the compilation progress can be traced for development purposes. Example: print version_1; outputs ....version_1.... between the points in the start window. DEVELOP The keyword DEVELOP is predefined in the development version of the A5 engine, and not defined in the published version. This way, debug panels can be conditionally displayed, like this: ifdef DEVELOP; set_debug(); endif; On_close This function is executed when the engine window close button is clicked at. Until now, the F10 key action was executed instead. Example: function quit() { exit; } on_close = quit; ent_preload(entity) preallocates video memory for the given sprite or model entity. If video memory is preallocated, there won't be a delay when the entity is visible the first time. Video memory is automatically preallocated for entities placed in the current level, but not for entities that are created during gameplay through ent_create or ent_morph, and not for global entities. ent_create Can now also create map entities, and replaces the old create instruction. Note that video memory for ent_created entities is only allocated when the entity is seen the first time. ent_purge, ent_preload, ent_frame, ent_cycle ...now also works with terrain. Detail blocks When setting the DETAIL flag of a block, this block does not increase the portal count of the level, as normal blocks do. Detail Blocks can be used for small details in the level, like pillars, rounded arcs or other elements which would otherwise increase the portal count and building time. Because Detail Blocks do not suppress the rendering of the scene behind them, they should not be used for objects that hide much of the level - otherwise they will reduce the frame rate. Do not try using Detail Blocks as level boundaries. Note that they are only visible in D3D mode, and not rendered at all in 8-bit mode. Detail Blocks might slow down lighting calculations. Standard level building rules still apply (e.g. don´t create a block much smaller than 2x2x2 quants). session_connect(sessionname,hostname) This instruction can be used for switching to a different session on another server (Pro Edition only). The first string parameter contains the name of the new session, the second parameter gives the name or IP address of the new server. This way, level changing in a multiplayer environment can be performed: session_connect("level2","169.254.73.29"); level_load("level2.wmb"); If an empty string is given for the server IP, a dialogue box will pop up for entering the IP manually. If the server or session is not found, an error message will appear. -SN name Through the -SN command line option the session name can be given when starting a server or a client in multiplayer mode. The default session name is the name of the main WDL file witout extension. The given name or address is available during gameplay in the predefined session_name string. -PORT number Through the -PORT command line option, a port address for TCP/IP client/server communication can be given. Valid ports are in the range 2300..2400. If no port is given, a default port address is assigned. A port address can only be given for the server - the client will connect to the right port automatically. -IP name Through the -IP command line option the server name or IP address can be given when starting a client in multiplayer mode. In this case the dialogue asking for entering a server address won't appear. Example: acknex office -cl -ip 169.254.73.28 connects to the server with the given IP address on the internet. The given name or address is available during gameplay in the predefined server_name string. dplay_smooth This variable (default = 0.3) sets the prediction factor for the dead reckoning system for multiplayer entity movement extrapolations. The 0.3 is the influence of the predicted entity movement over the received values from the server. If set t0 0, no prediction is performed at all. This is for diagnostic purposes only. dplay_unreliable If this variable (default 0) is set to 1, all messages are sent in unguaranteed mode. This is for diagnostic purposes only. recbuf_size, recbuf_cycles These variables give the number of bytes in the receive buffer of multiplayer systems, and the ratio of server to client frame cycles. They are used for diagnostic purposes and indicated in the 4th column of the debug panel below the D3D memory size. move_friction This variable (range 0..1, default 0.25) determines the friction for gliding along surfaces during an ent_move instruction. At 0 there is no friction at all, at 1 the entity sticks to the surface and does not glide at all. particle.lifespan If the lifespan of a particle is set to a value smaller than a frame cycle, like 0.01, the particle will now live for just one frame cycle. particle streaks are now also drawn when start and end points are outside the screen. snd_play (sound, volume, balance); snd_loop (sound, volume, balance); snd_playfile (string, volume, balance); snd_loopfile (string, volume, balance); snd_stop (handle); snd_tune (handle, volume, frequency, balance); ent_playsound (entity, sound, volume); Replace the old sound instructions. The sound handle is returned by the functions. The new balance parameter gives the screen position of the sound in percent (-100 .. +100). The new sound instructions can be called by a DLL file. ======================================================================= New features implemented in A5 engine 5.12: Compatibility If this variable is set at 1 (default), oriented sprites are not mirrored anymore. Relative sprites Sprites with relative flag set can now be rotated about their roll angle. decal This flag makes a sprite one-sided for attaching it at a wall. It can provisionally be set through the metal flag in WED 5. 4-player mode (Commercial Edition only) 4-player client/server mode was implemented in the commercial edition. Creating a multiplayer game works the same way as with the Pro edition. The only difference is that any more clients than 4 are automatically rejected by the server, and server only mode is not available. Camera portals and realtime mirrors (Pro Edition only) A second camera view named 'camera portal' can be mapped onto any surface of a level. This way windows into different areas of the map, as well as realtime mirrors can be created. The second view can be assigned to the new PORTAL parameter of any view. If the new MIRROR flag (only availabe in WED 5) is set for a surface, the translucent portal view is blended onto that surface. Only one portal can be visible. If several portals are in the view, only the first one will be displayed properly. The blending percentage is given by the ALBEDO parameter of the surface (0..100 %). If the surface is part of a map entity, then its albedo value modulates the surface value, allowing for soft blending in/out of mirrors. As an example for a camera portal, a mirror with 30% reflectivity was applied to the checkerboard plate in the office level: // Code to simulate a horizontal mirror by generating // a vertically flipped camera view from below through the floor view mirror { } function init_mirror_z() { camera.portal = mirror; mirror.noshadow = on; // suppress shadows in the mirror while (1) { proc_late(); // place it at the end of the function list - the camera must be moved before mirror.genius = camera.genius; mirror.aspect = -camera.aspect; // flip the image upside down mirror.arc = camera.arc; mirror.fog = camera.fog; mirror.x = camera.x; mirror.y = camera.y; mirror.z = 2*camera.portal_z-camera.z; // move the camera downwards by twice the portal distance mirror.pan = camera.pan; mirror.tilt = -camera.tilt; // flip the vertical camera angle mirror.roll = camera.roll; wait(1); } } New particle system - effect(function,number,position,velocity); This new instruction replaces the old EMIT instruction, and can be called from a DLL. The parameters are the same, but the particle action is different: Particle parameters are now accessed with the MY prefix, like entity parameters. The old MY_POS etc. variables are not used anymore. Velocity is a vector which is copied to the initial speed vector of the particle, but can also be used for other purposes, like transmitting a target position, a colour, a bmap handle, or any other information to the particle function. The following particle parameters can be changed: my.lifespan Life expectancy of the particle in ticks (default 80). Is automatically counted down; when reaching 0 or manually set to 0, the particle is removed. my.x, my.y, my.z Position of the particle. Is set to the given position at the beginning of the action. my.vel_x, my.vel_y, my.vel_z Speed vector of the particle, or line for a beam or ray effect. Is set to the given velocity at the beginning of the action. my.gravity Gravity acceleration of the particle in quants per square tick (default 0). Is used for accelerating vel_z when the move flag is set. my.size Size of the particle in quants (default 4). my.alpha Opacity of transparent particles (default 50). my.red, my.green, my.blue Particle colour (default white). In d3d mode it colorizes or darkens also the particle bitmap. Each pixel colour of the bitmap is multiplied with this colour value. my.bmap Bitmap of the particle (if any). my.flare, my.bright, my.transparent Particle flags, behave like entity flags. Ignored in 8 bit mode. my.move If this flag is set, the particle moves with its speed vector, and accelerates with its gravity acceleration. my.beam (professional edition only) By setting the beam flag of a particle, the particle is "smeared" along a line given by its speed vector and starting at its position (D3D mode only). Normally used for single particle effects. In combination with the flare and bright flag, rays of light can be created this way for laser, tracer bullet or light trail effects. my.streak (professional edition only) Like beam, but stretches the particle along its velocity vector, instead of smearing it. If the amount of velocity is the same as the size, the particle appears like without streak; if it is smaller, the particle is compressed; if it is larger, the particle is stretched. The streak effect is faster than beam, but looks less dramatic. Setting streak for multiparticle effects, like explosions, gives the effect a motion blur like appearance. my.function Particle function. When set to NULL, the particle continues to live until its lifespan reaches zero. my.flag1..my.flag8 General purpose particle flags for use in the particle action. my.skill_x, my.skill_y, my.skill_z General purpose particle vector for use in the particle action. Example: // helper function: sets the vector to random direction and length function vec_randomize(&vec,range) { vec[0] = random(1) - 0.5; vec[1] = random(1) - 0.5; vec[2] = random(1) - 0.5; vec_normalize(vec,random(range)); } // helper function: fades out a particle function part_alphafade() { my.alpha -= time+time; if (my.alpha <= 0) { my.lifespan = 0; } } // particle function: generates a fading explosion into vel direction function effect_explo() { vec_randomize(temp,10); vec_add(my.vel_x,temp); my.alpha = 25 + random(25); my.bmap = scatter_map; my.flare = on; my.bright = on; my.beam = on; my.move = on; my.function = part_alphafade; } ... vec_scale(normal,10); // produce an explosion into the normal direction effect(effect_explo,1000,my.x,normal); ... No other entity properties, except the above, and no entity instructions can be used for particles (otherwise -> crash). The new particle system is twice as fast as the old one, and thus can use twice as much particles without frame rate reduction. Particles are now clipped away at half the clip_range. Files outside resource (Pro edition only) All files except WDL files can now also be read from outside a resource file. Good-bye to Synonyms They still exist, but are now renamed to "Pointer" in the manual, for using a more conventional name better known to programmers. Also they are now defined in a different and shorter way: synonym guard { type entity; } // old style entity* guard; // new style The "*" suffix indicates a pointer to that object. You can define pointers to entities, actions, strings, panels, and bitmaps through entity*, action*, string*, panel*, and bmap*. It is recommended to use new-style pointer definitions from now on. Multidimensional arrays No, this is not a new beta feature, but just an addendum to the documentation. Users repeatedly requested multidimensional arrays and local variables without being aware that they are quite easily already available through the normal array feature. This is the "offical" way to define multidimensional arrays in WDL: Suppose you need an array in two dimensions, like a 10*20 grid of height values. Just define it this way: var heightmap[200]; // 100 = 10*20 and access it this way: temp = heightmap[j*10 + i]; // j = 0..9, i = 0..19 C++ programmers often prefer this way for creating multidimensional arrays, instead of defining something like heightmap[10][20]. Using a single index gives better control over the internal structure of the array. Local variables and additional entity skills You can use multidimensional arrays to add local variables to functions - variables that are only used within a certain function and nowhere else. Local variables can be used for unlimited entity skills. Suppose the 48 entity skills are not enough for a certain type of entity - you need 100 skills. Just defining an array[52] to get a total of 100 skills won't work when you have more than one entity of that type. If WDL functions would support local variables, you could just define a local array[52] within the entity action. Well, you can do this already, through defining a 'pool' of local variables in an array outside the function: var ent100_skill[5200]; // enough for 100 entities, 52 skills each var ent100_offs = 0; // index offset into the array define _local my.skill48; // use my.skill48 to store the index offset action ent100 // directly attached to the entity { _local = ent100_offs; // store the current array offset ent100_offs += 52; // and reserve 52 array elements for this action if (ent100_offs >= 5200) // check whether we have enough skills left { beep; beep; return; } // indicate an error (too much entities) ... while (1) // entity main loop { ... temp = ent100_skill[_local+0]; // access first additional skill ... temp = ent100_skill[_local+51]; // access last additional skill ... wait(1); } } Do not forget to set ent100_offs back to 0 when loading a new level! The idea to use arrays for additional entity skills is taken from Ronny Funk's Array Tutorial. Recursive functions A WDL function can call itself - this is named a 'recursive function'. Recursive functions are useful for solving certain mathematical or AI problems. This is an example: function factorial(x) { if (x <= 1) { return(1); } if (x >= 10) { return(0); } // number becomes too big... return (x*factorial(x-1)); } As an exercise for the reader, find out what this function does! Note: Recursive functions were already possible with prior versions, but undocumented. They must be used with care, and are for advanced users only. If you make a mistake, like a function that infinitely calls itself, you can easily produce a 'stack overflow' which crashes the computer. The stack size allows a recursion depth of around 10,000 nested function calls. Multiple parameters Functions can now accept multiple parameters (up to 4). Example: function sum(a,b,c,d) { return(a + b + c + d); } Note that functions with parameters must be defined before they can be used or assigned (see 'function prototypes' below). When redefining functions, the number and type of parameters must not change. Function pointers can only be used for functions that do not accept parameters. Array parameters Functions can now be given a numeric array or vector as a parameter. To indicate that a parameter is handled as an array, instead of a single number, the parameter name in the function definition is prefixed by a "&". Example: function vector_add (&sum,&v1,&v2) { // calculate the sum of two vectors sum[0] = v1[0] + v2[0]; sum[1] = v1[1] + v2[1]; sum[2] = v1[2] + v2[2]; } var vector1[3] = 1,2,3; var vector2[3] = 4,5,6; var vector3[3]; ... vector_add(vector3,vector1,vector2); // vector3 now contains 5,7,9 Inside the function, .x, .pan etc. abbreviations are not allowed for array or vector parameters. You must always use indexes. However on calling the function, you can also pass .x entity positions or angles instead of numeric arrays. Example: function vector_direction(&result,&from,&to) { // calculate the direction angles between two positions result[0] = to[0] - from[0]; result[1] = to[1] - from[1]; result[2] = to[2] - from[2]; vec_to_angle(result,result); } ... vector_direction(temp,my.x,you.x); // sets temp to the angle pointing from my to you vector_direction(temp,camera.x,nullvector); // sets temp to the angle from the camera to the level origin Because each variable is also an array at least of length 1, you can pass a variable either as a number or as an array parameter. However there are some subtle differences between the two types of parameters. If you pass a variable to a function that expects a number, it's content is handed over. If you pass the same variable to a function that expects an array parameter, a 'pointer' to the variable is handed over instead. If the function modifies the parameter, modifying a number is 'locally', i.e. happens only internally within the scope of the function. The passed variable itself is not changed. This is not the case for array parameters: Elements of a passed array are modified 'globally'. It is important to understand this difference. Some examples: function double_num(num) { num *= 2; // num is doubled locally, i.e. only within this function } function double_vec(&num) { num[0] *= 2; // num[0] is doubled globally } ... temp = 1; double_num(temp); // temp is still left at 1 here; double_num(1); // this is ok, 1 is a number double_num(temp+1); // this is ok, temp+1 is a number double_vec(temp); // now temp is globally changed to 2; double_vec(temp); // now temp is 4; //double_vec(1); // this is not allowed, 1 is not a vector //double_vec(temp+1); // this is not allowed, temp+1 is not a vector The length of an array is not tested within an array function. If such a function uses a wrong index (like num[3] in the above example), it won't be indicated - it can just lead to an engine crash. The local content of numeric parameters, as well as the local states of the YOU and MY pointers within all functions are saved together with the game. Array parameters or pointer parameters are not saved. So they can become invalid within functions when loading a game. As save/load instructions can only occur during wait() time, use array or pointer parameters only in functions that do not contain a wait() loop. Otherwise use them only before any wait/waitt instruction in the function, and be aware that they can be invalid after the first wait/waitt. Function prototypes Like all other WDL elements, functions must be defined BEFORE they are used (old WDL code will still work, however). Sometimes this is inconvenient, for instance if two functions call each other. In that case, a function can be predefined through a PROTOTYPE (already known to C programmers). The prototype consists of the function head with the parameters, followed by a semicolon, but without the instruction list in { }. Example: function beep_sum(beep1,beep2); // prototype of function beep_sum function use_beep_sum() { beep_sum(3,4); // beep_sum is used here } function beep_sum(beep1,beep2) // this is the real function { beep1 += beep2; while (beep1 > 0) { beep; beep1 -= 1; wait(1); } } ent_create(string,vector,action) ent_morph(entity,string) level_load(string) replace the old CREATE, MORPH and LOAD_LEVEL instructions, and can be called from a DLL. Ent_create returns a pointer to the created entity. Unlike the old instructions, a string and not a filename is given for the entity or level file. The filename must be given additonally in angular brackets with a BIND or STRING statement for including the file into the resource or publish folder. Example: STRING flash_pcx = ; // strings can be defined in "" or <> ... you = ent_create(flash_pcx,temp,flash_prog); is the same as the old-style CREATE ,temp,flash_prog; ent_next(entity) All entities of a level are sorted into an internal list. This instruction returns a pointer to the first entity in the list when the entity parameter is NULL, and a pointer to the next entity otherwise. When the last entity is given as parameter, the instruction returns NULL. With this instruction something can be done to all entities in a level - or a certain entity can be found. Example: function hide_all_ents() { you = ent_next(NULL); // retrieve first entity while (you != NULL) { // repeat until there are no more entities you.invisible = on; // set entity invisible you = ent_next(you); // get next entity } } The parameters of all entities can be read, but changing the parameters only has an effect on active entities (with an action attached). vec_for_mesh(vector,entity,number); vec_to_mesh(vector,entity,number); Performs realtime mesh deformation of a model or terrain entity. vec_for_mesh() sets the given vector to the mesh coordinates of the given vertex number. Vec_to_mesh() sets the mesh coordinates of the given vertex number to the given vector. The mesh is deformed not only on this entity, but on all models or terrains of the same type. Mesh deformations are lost on exiting the game. They can not increase the model size: mesh vertices deformed 'outwards' stop when reaching the model boundaries. For smooth mesh deformation the model should have the high prec flag set. Example: function dent(ent,num) // make a "dent" into a mesh { vec_for_mesh(temp,ent,num); vec_scale(temp,0.9); // move the vertex inwards by 10% vec_to_mesh(temp,ent,num); } vec_for_vertex(vector,entity,number); Sets the given vector to the current world position of the vertex with given number of the given model or terrain entity. This instruction is useful for composing entities from several parts. Weapons can be attached and changed without having to change the whole model, flares can be attached to headlights or jet engines, or certain parts of models can emit particle effects. The vertex number is indicated by MED on selecting a vertex. Example: // let the MY entities' vertex no. 248 periodically emit particles vec_for_vertex(temp,my,248); // get XYZ position of vertex 248 emit(1,temp,particle_flare); This instruction replaces the old ent_vertex instruction which required clumsy pointer assignments when using another entity than my. vec_for_normal(vector,entity,number) Like vec_for_vertex, but returns the vertex normal of the given model vertex. The vertex normal is the average of the normals of the surrounding triangles. ent_vertices(entity) returns the number of mesh vertices of the given entity. var = handle(object) returns a handle of an object. A handle is a unique number that internally identifies that object. The object can be an entity, an action, a string, a bmap, a panel, or any pointer to them. A handle is similar to a pointer, but is just a number and therefore can be assigned to any variable or skill. After saving and loading a game, a handle is guaranteed to reference always the same object - this is not guaranteed for pointer parameters. For using a handle to get the referenced object, it can be converted to a pointer, through the following instruction. ptr = ptr_for_handle(var) assigns the object referenced by the given handle to a pointer. Example: my.skill40 = handle(you); // store a handle to the YOU entity ... you = ptr_for_handle(my.skill40) // get the YOU entity back; This way arbitrary objects can be stored in entity skills or var arrays. WARNING W1514: Invalid handle in... An invalid parameter was passed to a handle or ptr_for_handle instruction. Multiplayer modes Trough the following variables the multiplayer communication can be optimized for the type of the game or the network. The variables are for advanced users only who have experience with DirectPlay - normally they should be kept at their default values. They can't be set directly during gameplay, but can be defined at a certain value. Dplay_protocol If this variable (default 0) is redefined to 1, the engine uses the DirectPlay UDP protocol for reliable messages, instead of the TCP protocol. The DirectPlay protocol has the advantage that it supports reliable messages also for IPX and modem connections. Dplay_servermode If this variable is at 1 (default), the server runs in DPSESSION_MIGRATEHOST mode. If is redefined to 2, the server runs in DPSESSION_CLIENTSERVER mode. If it is redefined to 0, neither of both modes is active. Dplay_optimize If this variable is at 1 (default), the server runs in DPSESSION_OPTIMIZELATENCY mode. It it is refedined to 2, the server runs in DPSESSION_OPTIMIZELATENCY and DPSESSION_NOPRESERVEORDER mode. It it is redefined to 0, neither of both modes is active - this reduces the bandwidth in multiplayer games, but increases the latency time. proc_late() Places the current function at the very end of the scheduler list. Necessary when this function needs results or entity or camera positions that are calculated by other functions. The other functions must be guaranteed to run earlier during each frame cycle. Shift operators The >> and << operators perform a bitwise shift of the left number by the right number. This is equivalent to a division, or a multiplication by a corresponding power of 2 - but is a little faster. Examples: temp = x >> 2; // sets temp to x / 4 temp = x << 3; // sets temp to x * 8 x = frc(x) << 10; // copies the fractional part of x (10 bits) into the integer part fsin(a,f) returns f*sin(a). fcos(a,f) and ftan(a,f) work equivalent. The precision is higher than calculating f*sin(a) externally. fasin(a,f) returns asin(a/f). facos(a,f) and fatan(a,f) work equivalently. vec_inverse(vector) Flips the vector by multiplying its components by -1. vec_diff(vector,vector1,vector2) Sets the vector to the difference of vector1 and vector2. After the instruction, the vector gives the direction from vector2 to vector1. ang_rotate(vector1,vector2) Rotates the pan,tilt,roll angles of vector1 by the pan,tilt,roll angles of vector2. Internally a quaternion rotation is used. This instruction can be used to rotate an arbitrarily oriented object about an arbitrary axis given by the first vector. Example: // Let a camera chase a space ship and rotate with the ship. // The ship is always kept in the center of the view. var cam_dist[3] = -500,100,100; // xyz position of camera to ship var cam_ang[3]; // direction angles of camera to ship function chase_camera() { // calculate the camera view direction angles to the ship vec_diff(temp,nullvector,cam_dist); vec_to_angle(cam_ang,temp); cam_ang.roll = 0; // roll is unchanged by vec_to_angle // permanently update the camera position and angles while (1) { // place the camera at the right position to the ship vec_set(camera.x,cam_dist); vec_rotate(camera.x,ship.pan); vec_add(camera.x,ship.x); // set the camera angles to the ship angles, vec_set(camera.pan,ship.pan); // and quaternion rotate them by the camera view direction angles ang_rotate(camera.pan,cam_ang); wait(1); } } Redefining of keys... ... is much easier now through the following new WDL functions and variables: On_key, on_joy, on_mouse All key and button actions now get a parameter passed that contains the number of the key pressed. For the keyboard, the number is the key scan code. For the joystick the number is 256..265 dependent on which of the 10 joystick buttons are pressed. For the left, middle, and right mouse buttons the number is 280, 282, and 281. key_pressed(number) This function returns 1 when the key or button with the given number is pressed, otherwise 0. key_for_str(string) This function returns the key number for the given string on an US keyboard. The letters "A".."Z" and the numbers "0".."9" can be given. str_for_key(string,number) This function copies the letter or number for the given key number on an US keyboard to the given string. key_set(number,action) Sets the given action to the key with the given number. This way keyboard remapping can be done easier than before, without comparing all key_.. variables. Example: key_set(key_for_string("P"),my_function); does the same as on_p = my_function; key_lastpressed This variable contains the number of the last key or button pressed. Example for remapping a key: print("Please press key to assign function to"); while (key_any == 0) { wait(1); } // wait until a key is hit str_cpy(my_str,"You have pressed "); str_for_key(temp_str,key_lastpressed); str_cat(my_str,temp_str); print(my_str); // indicate which key while (key_any == 1) { wait(1); } // wait until key is released key_set(key_lastpressed,my_function); // assign function to key var_nsave Like var_info, but this variable is never saved. Use this type of variables for DLL and sound handles that must not be overwritten by a load or load_info instruction. Logo Users were not able to display the A5 watermark in the commercial and pro editions - this is now possible by setting the logo variable (default 0) at 1, 2, 3, or 4. D3d_monochrome When this variable is defined at 1 at game start, dynamic and static lights will be white, as with the standard or extra edition. This variable can't be changed during game play. Noshadow If this view flag is set, no dynamic model shadows are displayed in the view. Useful for horizontal mirrors where you don't want the shadow to be mirrored too. Unlit The unlit flag prevented influence of static lightsources on entities. Now also dynamic lightsources have no influence when unlit is set. Only the entities' own light (when the light flag is set) can influence an unlit entity. Scene_color Like sky_color, but colorizes the scene map. This way smooth day/night transitions can be achieved. Sun When loading a level, sun_angle.pan and sun_angle.tilt are now automatically set to the level's sun elevation and azimuth. Screen_colour This colour vector (default 0,0,0 = transparent) gives the background colour of the screen or window in D3D as well as 8 bit mode. Trace When tracing terrain, trace now delivers a hit even when the ray starting point was completely below the terrain surface. Until now, a terrain hit was only detected when the ray intersected the terrain surface, which gave terrain the behaviour of a 'hollow' object. Version This variable contains the engine version (currently 5.120). clip_size This value (default 0.5) gives the minimum number of pixels that must be covered by a model triangle for being rendered. With the default value, model triangles are not rendered if they are smaller than half a pixel. This increases the frame rate, but can lead to "holes" in ill constructed high polygon models. When using high polygon models clip_size should be set to 0. clip_factor This variable (default 2) gives the range of clipping polygons out of the BSP tree, in clip_range units. Example: clip_factor = 1.0; // clips world polygons at same range as entities D3d_entsort If this predefined variable is set to 1, transparent entities are sorted before rendering in D3D mode. This prevents a visible sorting faults of almost-intransparent entities with high alpha values or alpha maps. The drawback is a few percent decrease of the frame rate when a lot of transparent entities are on the screen. The default value of this variable is 1. View.transparent, view.alpha (Pro Edition only) By setting a view's transparent flag, the view is displayed translucent over the background (D3D mode only). The translucency can be given through the view's alpha parameter in percent. Declaring DLL functions Through the new keyword dllfunction(...), DLL functions can now be declared like normal WDL function prototypes. Vectors or other parameters can be passed to DLL functions the same way as to WDL functions. On calling a DLL function, the engine looks for a function of this name in the current DLL. If it is found, it is executed and the parameters are passed to it; otherwise an error message is displayed. This new way to call DLL functions make the dll_exec and dll_exec_vec instructions obsolete, and allows enhancing the WDL language by adding new C++ functions that are called like normal WDL functions. Example: dllfunction vec_add(&vec1,&vec2,&vec3); // dll function declaration ... dll_open("vectors.dll"); ... vec_add(temp,my.x,you.x); ... dll_close(dll_handle); In the example, the vec_add function in the DLL must accept three long parameters, and cast them to (fixed *) within the function. DLL particle functions DLL functions can also be used for particles. The A4_PARTICLE struct was added to the DLL Header file. A pointer to the particle is the sole argument of a DLL particle function. Example: // examples for a particle effect function // dllfunction DLLEffect_Explo(particle); // dllfunction DLLPart_Alphafade(particle); // start the particle effect by // effect(DLLEffect_Explo,1000,my.x,nullvector); fixed *var_time = NULL; long func_alphafade = 0; // helper function: fades out a particle DLLFUNC fixed DLLPart_Alphafade(long particle) { if (!var_time || !particle) return 0; A4_PARTICLE* p = (A4_PARTICLE*) particle; p->alpha -= *var_time * 2; if (p->alpha <= 0) p->lifespan = 0; return 0; } // helper function: return a random float float random(float max) { return (float)(rand()*max)/(float)RAND_MAX; } // particle effect: generate a blue explosion DLLFUNC fixed DLLEffect_Explo(long particle) { if (!particle) return 0; // initialize time var and alphafade function (must only be done once) if (!var_time) var_time = (fixed *)a5dll_getwdlobj("time"); if (!func_alphafade) func_alphafade = a5dll_getscript("DLLPart_Alphafade"); A4_PARTICLE* p = (A4_PARTICLE*) particle; // initialize particle parameters p->flags |= EPF_STREAK|EPF_MOVE|ENF_FLARE|ENF_BRIGHT; p->vel_x = FLOAT2FIX(random(10) - 5); p->vel_y = FLOAT2FIX(random(10) - 5); p->vel_z = FLOAT2FIX(random(10) - 5); p->red = 0; p->green = 0; p->blue = INT2FIX(255); p->alpha = FLOAT2FIX(50 + random(50)); p->function = func_alphafade; return 0; } Manipulating entity textures The example function "PaintEntitiesRed" was added to the DLL SDK as a demonstration how to modify the textures of entities. Accessing model and terrain textures A5 DLLs can now read and modify not only sprite textures, but also model and terrain skins, through the following library function A4_TEX *a5dll_tex4ent(A4_ENTITY *entity,int frame,int texnum=0); entity - the sprite, model or terrain to access the texture from frame - the frame or skin number texnum - the subtexture number, if subtextures exist. The engine splits a texture into subtextures when it is bigger than the 3D card can handle. For determining whether subtextures exist, the function must be called several times with increasing texture number. After the last subtexture, the function returns NULL. Note that the subtextures can have different sizes and can (and normally will) overlap. Calling WDL functions from a DLL A5 DLLs can now call user-defined WDL functions. The library function long a5dll_getscript(char *name); delivers a handle to a user defined WDL action or function, which can be executed through (*a5->wdl->Call). Example: // dll_exec("DLLBeepTwice",0); // calls the following function that must be defined in the WDL code: function beeptwice() { beep; beep; } DLLFUNC fixed DLLBeepTwice(fixed value) { // get the function long beeptwice = a5dll_getscript("beeptwice"); if (!beeptwice) return 0; // "beeptwice" doesn't exist // call it (*a5->wdl->Call)(beeptwice); // return something return INT2FIX(1); } msg_show(string,secs); msg_blink(string,secs); replace the old show_message and blink_message functions. animate.wdl: Added actor_adv_anim(). This allows the user to set animation cycle distances and timing on an individual entity level. See the "Scriptless Shooter" tutorial for details. camera.wdl: If new var 'camera_solidpass' is set to 1 then it no longer tries to avoid entering solid blocks (which causes the 'shaky camera' problem). Added "orbit" and "chase" cameras. They are all cycled with the F7 key. doors.wdl Fixed problem that caused doors, gates, and elevators to 'teleport' when move long distances. input.wdl Removed force doubling code in this function since KEY_FORCE is already doubled when SHIFT is pressed. Added another factor to mouse look section to keep doubling there. move.wdl Adjusted wading forces to reflect the use of my_height_passable movement.wdl Fixed wade/swim 'stutter'. venture.wdl Fixed error that causes touch text to remain on the screen. war.wdl Added ACTION: "player_walk_fight" & "actor_walk_fight" (see "The Scriptless Shooter" for details). Improved AI to be adjustable by the skills _ACCURACY, _COWARDICE, & _ALERTNESS (see "The Scriptless Shooter" for details). Fixed "self-hits" and "double-shoots" Fixed damage from ranged explosions error. weapons.wdl Added function pan_cross_toggle(). Toggles cross-hair panel Added ON_K to call pan_cross_toggle Added new weapon actions: weap_mg_animated, weap_m16, weap_rocketlauncher, Added ammo pack actions for ammo types 1-7. Improved bullet_hole to a 'FIFO' array. Added function "bullet_hole_remove_all" to remove all bullet holes from a level (must call before loading a new level). Added gun animation (the action "weap_mg_animated" uses this): - Gun must have animation frames labeled "shot1", "shot2", etc. - gun action must set "GUNFX_ANIMATE" in "_FIREMODE" ex) MY._FIREMODE = DAMAGE_SHOOT + GUNFX_ANIMATE + 0.25; Lens flares The lflare.wdl was taken over into the template scripts. The office level got a sun lens flare. MED tutorial Guidelines for animating humanoid models are added to the MED tutorial. WDL tutorial The first chapter of the WDL tutorial was modified for explaining function parameters and creating a non-3D application. ======================================================================= New features implemented in A5 engine 5.10: Renderer kernel A part of the old A4 renderer kernel was replaced by new A5 rendering algorithms. This causes a frame rate increase of 2%..10%, and a reduction of level change times of up to 50%. D3D_triplebuffer On 3D cards with more than 8 MB video memory, triple buffering is now used in fullscreen mode, otherwise double buffering. Triple buffering can increase the frame rate, but consumes video memory for a third screen buffer. Triple buffering can be prevented by redefining the d3d_triplebuffer variable to OFF, and can be forced by redefining it to ON. D3d_triplebuffer must not change during gameplay. Example: var d3d_triplebuffer = OFF; // prevent triple buffering D3d_vsync If this variable is set to OFF, the engine does not wait for the vertical sync before flipping screen buffers. This prevents the frame rate from locking at a half or a third of the video frequency, and can increase the frame rate even above the video frequency. The drawback is that without triple buffering, or when the frame rate is higher than the video frequency, tearing artifacts can be visible on the screen. The default value of D3d_vsync is OFF when triple buffering is activated, otherwise ON. Weapons.wdl The number of weapon and ammo types was increased to 7. The weapon skills _GUN_SOURCE_X, _GUN_SOURCE_Y, and _GUN_SOURCE_Z define the source position of a gun shot. If _GUN_SOURCE_X == 0, then a default position (gun_muzzle vector) is used. Crosshair helper functions pan_cross_show() and pan_cross_hide() were added. CAPS_COLOR,CAPS_FLARE,CAPS_SHADOW These keywords are defined when the engine supports colored lights, flares, or shadows. They can be used for universal functions to be run on different editions in a different way. Example: IFDEF CAPS_FLARE; create(,my.x,move_shadowflare); IFELSE; create(,my.x,move_shadowflat); ENDIF; DIRECT3D This keyword is defined when the engine runs in D3D mode. It can be used for loading different bitmaps or levels depending on the mode. Example: IFDEF DIRECT3D; bmap panel_map = ; // bitmap for d3d mode IFELSE; bmap panel_map = ; // bitmap for software mode ENDIF; Level_name This predefined string contains the name of the current level, if any. String[len] Empty strings can now also be defined by giving the length in brackets, like variables. A string content must not be given in that case. Example: string empty100[100]; // an empty string that can hold 100 characters Sky_color The red, green, and blue components of this colour vector (default 255,255,255 = white) are multiplied by the sky texture in D3D mode. This way the sky can seamlessly be darkened for day->night transitions. Bg_color Through the red, green, and blue components of this colour vector a background colour for D3D mode can be set. This colour is visible when no sky is drawn, or when no level is loaded. If all three components are set to 0 (default), no background colour is drawn. Tex_share If this variable is set to 1 before loading a level, map entities share their textures with the level and with each other if they have the same name and size. This saves memory. Worldcraft support Worldcraft MAP files can now be imported by WED. Also WAD Files of Worldcraft's WAD3 type can be used. The texture orientation, which can be set manually in Worldcraft, is replaced by WED's fixed texture orientation. DX_INTERFACE This struct holds the DirectInput, DirectPlay, DirectPlayLobby, and DirectSound pointers for the DLL interface. Pos_resolution Has now a default value of 1. ent_purge(entity); bmap_purge(bmap); These instructions release memory used by the entity or by the bitmap. Useful for freeing the video memory when a certain panel or entities of a certain type won't be seen anymore. Note that this works for model or sprite entities only; maps or terrain can't be purged. Video memory is automatically allocated again when the entity or bitmap is seen the next time. However, any ent_alphaset instructions must be done again. Thus the purge instruction, followed by ent_alphaset, can also be used to change the alpha factor of an entity texture. Example: ent_purge(player); // frees the player when in 1st person mode ent_remove(entity) Behaves equally as the remove instruction, can be used by a DLL however. Multiplayer mode improved The client/server protocol was changed. The new protocol sends the game state in compressed format to the client on joining a session, thus reducing the bandwidth hit on systems with slow connections or huge numbers of clients. Also an improved dead reckoning algorithm was implemented that predicts not only velocity, but also acceleration of entities. This smoothes entity movements on slow client/server systems with high latency time. TCP/IP is now the default multiplayer protocol, instead of IPX. The IPX protocol can be selected by the -IPX command line parameter. On internet connections, the TCP protocol is now used for essential messages like joining, send_var() or send_string(), while the UDP protocol is used for less important messages like entity updates. The packet size was limited to 1400 bytes, because routers or other equipment often discard UDP packets larger than about 1400 bytes. This makes internet multiplayer mode more reliable. On_server(string) On_client(string) This event is executed when the server receives a message from a client, resp. vice versa. The event_type variable is set to the type of the message. When the message contains a string, a variable set to a synonym of the received string is handed over to the function. There are 4 types of server events: Event_join: A client has joined. The client name is handed over. Event_leave: A client has left. The client name is handed over. Event_string: A client has sent a string. The string synonym is handed over. Event_var: A client has sent a variable or an array. There are 2 types of client events: Event_string: The server has sent a string to all clients. The string synonym is handed over. Event_var: The server has sent a variable or an array. Examples: function server_event(str) { if (event_type == event_join) { str_cpy(temp_str,str); str_cat(temp_str," joined"); scroll_message(temp_str); return; } if (event_type == event_leave) { str_cpy(temp_str,str); str_cat(temp_str," left"); scroll_message(temp_str); return; } if ((event_type == event_string) && (str == message_syn)) // synonyms can be compared directly { // server received message -> send it to all clients send_string(message_syn); return; } } // client received message -> display it function client_event(str) { if ((event_type == event_string) && (str == message_syn)) { scroll_message(message_syn); str_cpy(message_syn,empty_str); return; } } ON_SERVER = server_event; ON_CLIENT = client_event; send_vec(skill); Like send(skill), but sends a vector consisting of 3 consecutive skills. The first of the three is given as parameter. server_name server_IP These predefined strings hold the name and the first IP address of the server in a multiplayer game. On a client the strings are empty. They can be used to display the information the clients have to enter in the IP field in order to connect. For connecting on a local network the server name can be used; for connecting over the internet the IP address must be used. Example: ifdef SERVER; while (connection == 0) { wait(1); } str_cpy(temp_str,server_name); str_cat(temp_str," "); str_cat(temp_str,server_IP); scroll_message(temp_str); endif; send_var(var) Sends a variable from a client to the server, or from a server to all clients. Note that only user-defined variables can be sent; predefined system variables or old-style skills can't be sent. If the variable is a vector or an array, all elements are sent. Player_name This predefined string contains the name of the Client, either set by -pl or created by the engine. vec_dot(v1,v2); Returns the dot product of the vectors v1 and v2. pow(x,y); The pow function computes x raised to the power y. An error occurs if x is zero and y is less than or equal to 0, or if x is negative and y has a fractional part. Note that x*x is computed faster than pow(x,2). Inkey If the string for user input was not empty, the cursor is now placed at the end of the string, instead of the beginning. Debug panel The panel appearing on [D] now also contains five time values in milliseconds. They display the time per frame for a) rendering the 3D scene, b) drawing panels, texts and static entities, c) updating the screen buffer and waiting for the vsync, d) executing WDL functions and e) client/ server communication. These values can be used for optimizing the frame rate. Light reflectance By setting the METAL flag of a model, it's skin gets a specular reflectance for the sun light in D3D mode, as if made of shiny metal or glass. The intensity of the effect can be set through the model's ALBEDO parameter (0..100, default 50) between 40 and 60. MED - import skin If on importing the new skin is larger than the old one, you can adapt the mapping to the new size by checking the "adapt skin points" box. The mapping is always adapted when the new skin is smaller than the old one. Texture parameters The predefined flags tex_flag1..tex_flag8 now reflect the Flag1.. Flag8 states of a texture hit by trace() with scan_texture set. The 8 flags can be set through WED. This way floor textures can be given certain properties. The tex_fog variable is set to the Fog/Albedo value of a hit texture. sun_pos This predefined vector gives the position of the sun. It is recalculated each frame according to the sun angles. (sun_pos exists already since several versions, I've just forgotten to document it). function parameters Functions can also take synonyms and flag on/off states as arguments. As the type of arguments is undefined in javascript-style functions, a synonym argument must be assigned to a wdl-defined synonym of known type before it can be used directly for assignements. However they can be directly used as arguments in javascript-style functions. Example: // this function takes an entity synonym as argument. function flare_init(ent) { my = ent; // necessary, because my.bright = on; // ent.bright = on won't work! my.flare = on; ent_alphaset(0,10); } ... flare_init(you); flare_init(flare0_ent); ... Note that non-numeric arguments in functions keep their value only until the first wait() instruction. Also, vector arguments are not implemented yet - handing a vector over to a function will only transfer its first element. WARNING W066: Surfaces too big for Shaded mode This warning will be issued by the map compiler when you have surfaces in your level which are too big for the rendering mode selected. Extremely large surfaces should be rendered in flat mode. You can ignore the warning, but then the level will be very slow in compiling and rendering. Warning 1407: Client joined wrong level This warning message is issued by the server if a client connects which runs a different game level. Warning 1342: More than 4096 entities potentially visible This warning message is issued when way too much entities are in the camera's sight range. Error 1513: WDL crash in... This message indicates that a crash happened due to bad WDL code in a certain function, like a division by 0 or a square root of a negative number. Note that such errors are only indicated in the development engine. In the distributable version they will just crash the program. ======================================================================= New features implemented in A5 engine 5.05: str_for_entname(string,entity); str_for_entfile(string,entity); Sets the string to the WED name or to the file name of the given entity. syn_for_name(string); returns the synonym of the entity with the given WED name. Names can be assigned to entities through [Properties] in WED. This way, entities placed in a level can now be accessed in WDL actions. Example: string entname = " "; // a long empty string ... you = syn_for_name("waffe1_mdl_012"); // get synonym of that entity str_for_entfile(entname,you); // retrieve the file name ("waffe1.mdl") you.string1 = entname; // let the file name appear you.enable_touch = on; // when the entity is touched with the mouse you.event = handle_touch; Note that when an entity has no action attached, it's parameters can be read, but must not be changed during gameplay. Also it's skills above skill8 are not available. Controlling the engine through an external DLL On engine start, a DLL named "ACKAPP.DLL" is looked for in the current directory, and opened if it exists. The following function must exist in that DLL: long ackapp_main(long info); This DLL function is called at engine start, but before any video modes are set. The function can control and change all predefined variables, and thus set the desired video mode on its own through changing video_mode, video_depth, and video_screen. long ackapp_ent_init(A4_ENTITY *entity); long ackapp_ent_loop(A4_ENTITY *entity); long ackapp_ent_event(A4_ENTITY *entity); If ackapp_ent_init() exists, it is called once for each static entity - each entity without WDL action - in any level that is loaded. If the function returns 0, the entity remains static. If it returns 1, the entity becomes dynamic, that means it can move in the level even without WDL action. The ackapp_ent_loop() function is from now on called once each frame for that entity, until the entity is removed or another level is loaded. The ackapp_ent_event() function becomes the event function for that entity. The WDL handle for the ACKAPP.DLL is stored in the dll_apphandle variable. This way, in the main WDL script further calls to the DLL can be defined, like this: function main() { ... if (dll_apphandle != 0) { while(1) { dll_handle = dll_apphandle; dll_exec("ackapp_eachframe",0); // called each frame wait(1); } } } The ACKAPP DLL allows programming an A5 application completely in Visual C++ (or any other language that supports DLLs) without having to write a single line of WDL code. Only the basic WDL script must be created by clicking on the [NEW] button. Accessing sprite textures through an external DLL A4_TEX *a5dll_tex4ent(A4_ENTITY *entity,int frame); This DLL function returns the texture of a sprite entity. The frame parameter gives the frame number of the sprite. A pointer to a DirectDrawSurface7 object can be obtained from the A4_TEX struct, and can be used for implementing realtime effects like shaders or texture procedures. CLIP_RANGE Level parts outside twice the clip_range are now removed from the BSP tree before rendering in D3D mode, in order to speed up huge outside levels. The only exception are sky polygons. Near clipping in D3D mode Models with NEAR flag are rendered with a lower Z-Buffer value, in order to render them in front of other objects. This led to earlier clipping of such objects in D3D mode when they are very close to the player - as it is the case normally with weapon models. NEAR models are now rendered in a different way that prevents earlier clipping. Still, clipping happens when polygons of the weapon models are penetrating the camera plane. This should be prevented by the design and the placement of the weapon model. For fine-tuning, the predefined vector d3d_near can be used. D3d_near.x gives a z buffer offset factor (0.1..0.25, default 0.25), and d3d_near.y gives a distance factor (1..10, default 2.5). By changing these values the clipping behaviour of NEAR models can be influenced. LOD It is not necessary anymore to define LOD entities in WDL. If an entity name ends with "_0", it is assumed that similar entities ending with "_1", "_2", "_3" are the three LOD levels for that entity (Example: for "house_0.wmb" the engine expects "house_1.wmb".. "house_3.wmb" as LOD entities). Entity names can now be 20 characters long. If a LOD entity is not found, nothing is displayed at that LOD level. Note that if you had an entity name ending with "_0" by chance, rename it - otherwise that entity won't be visible anymore when not close to the camera. Ent_prevpoint Like ent_nextpoint, but finds the waypoint before the current one, and returns its number. Audible When several views are defined, only the sounds of the view with AUDIBLE flag set are heard (until now it was the last defined view). The camera view has the AUDIBLE flag set by default. Tiled terrain textures If the new tex_scale entity parameter in non-zero, a terrain texture will be scaled by the amount of this parameter in quants/pixel, and tiled automatically. If it is zero, the terrain texture will be stretched all over the terrain as before. Tex_scale is ignored in 8-bit mode. Note that mipmapping is not yet supported for terrain, so tiled textures won't look very good in the distance. TGA images with alpha channel Targa (TGA) images are now supported for models, sprites, particles and bitmaps. 24-bit and 32-bit TGA images can be used, the latter with alpha channel. This way the alpha channel of sprite or model textures does not depend on its brightness anymore. WED and MED now import TGA bitmaps for sprites and model skins. Panels with alpha channel bitmaps are always rendered in D3D mode. Clouds and scene map are rendered in flare mode when they contain alpha channel images. On alpha channel entities the FLARE flag is set by default. The alpha channel is ignored in 8-bit mode. In this mode a TGA image is rendered the same way as a 24 bit PCX or BMP image. Example: entity alphasprite { type = ; flags = visible; view = CAMERA; X = 200; y = 0; z = 0; } For creating an alpha channel for a 24 bit image in Photoshop, open the image, then open the channels window, and click onto the small "new channel" button below. Now an alpha channel is created, and you can paint onto it. When saving the picture, use the Targa format. Fading in/out of flare entities Flare models, sprites, particles, and alpha channel panels now also can use the alpha parameter for smooth fading in and out in the range of 0..50. At alpha = 50 (default) they look as before, at 0 they are completely transparent. ======================================================================= New features implemented in A4 engine V4.23 and A5 prerelease 5.03 (the A5 only features are marked with "A5") File instructions (A5) ================================================ The following A5 instructions write into or read out of text files. They can be used for exchanging data with other programs, or for many other purposes like outputting variable contents for debugging. handle = file_open_read(string) Opens a text file for reading. The file must exist in the SAVEDIR. The file name including the extension must be given by the string, without a path. This instruction returns a file handle - that is a unique number to identify the opened file. The file hande is used by other instructions to access that file. If the file can't be opened - if it does not exist, for instance - 0 is returned instead. File handles become invalid after a LOAD instruction, so file operations shouldn't be interrupted by save/load operations. handle = file_open_game(string) Like file_open_read(), but this instruction takes its file from the game directory, instead of the save directory. This way files with arbitrary data can be provided together with the game. The file must really exist in the game directory, it can't be encrypted within a resource. Example: filehandle = file_open_game("address.txt"); handle = file_open_write(string) Opens the file for writing into. If the file does not exist in the SAVEDIR, it is created; otherwise it's previous content is erased. handle = file_open_append(string) Opens the file for appending additional text at the end. If the file does not exist in the SAVEDIR, it is created. file_close(handle); Closes the file with the given handle. A file must be closed before other programs can access it, or before it can be opened again in a different mode. As soon as the file is closed, the handle becomes invalid. file_var_write(handle,var) Writes the given number or variable into the file with the given handle. The file must be open for writing or appending. The number is written with 3 decimals, followed by a blank. Example: var filehandle; ... filehandle = file_open_write("myfile.txt"); file_var_write(filehandle,123456.789); file_var_write(filehandle,sqrt(2)); file_close(filehandle); // the file now contains "123456.789 1.414 " var = file_var_read(handle) Returns the number that was written into the file with the given handle, and proceeds to the next position within the file. The file must be open for reading. If there are no further numbers, 0 is returned. Example (with the file created above): filehandle = file_open_read("myfile.txt"); temp = file_var_read(filehandle); // now temp == 123456.789 temp = file_var_read(filehandle); // now temp == 1.414 file_close(filehandle); file_str_write(handle,string) Writes the given string into the file with the given handle. The file must be open for writing or appending. If the string contains a '\n', a line feed is inserted; '\\' inserts a '\'. file_str_read(handle,string) Reads text from the file with the given handle into the given string, until a delimiter is reached. The delimiter is either a '0' byte in the file, or a line feed, or a comma (','). This way, comma separated strings from a database file can be read. The file must be open for reading. The original length of the string won't be overwritten. file_chr_read(handle,string) Reads characters from the file with the given handle into the given string, until the string is full. The file must be open for reading. The number of characters read is the original length of the string. file_asc_write(handle,var) Writes a single byte given by the number or variable into the file with the given handle. The file must be open for writing or appending. var = file_asc_read(handle) Reads a byte out of the file with the given handle, and proceeds to the next byte within the file. The file must be open for reading. If the end of the file is reached, 0 is returned. DLL Plugin functions ================================================== DLL Plugin interface DLL Plugins are customer-programmed extensions to the engine and to the WDL language. They can be used with all editions, but can only be created with the SDK that comes with the professional edition. This way, A5 professional edition owners can create arbitrary DLLs for adding new effects, actor AI or WDL instructions, and distribute or sell them to other A4 or A5 users. For A4 however only a limited access to the engine via DLL is possible. The Microsoft Visual C++ development system is required for creating Plugins. The Plugin Source Development Kit (SDK) contains a DLL interface library that must be linked to the DLL. A DLL template is also provided, which makes it pretty easy to create A5 DLLs even for not-so-experienced C programmers who have never used DLLs before. Later, SDKs for other languages like Visual Basic could be provided. DLLs work bidirectionally: WDL instructions can access DLL functions, and DLL functions can access essential A5 functions and variables. On opening a DLL, A5 transfers the pointer to an internal interface structure to the interface library. The interface contains pointers to A5 variables and functions, like the frame buffer, the DirectX interface, the network interface, the DirectInput interface, the level, the WDL functions and so on. Theoretically everything - MP3 or MOD players, a physics engine, another 3D engine or even another scripting language - can be added to A5 this way. On accessing system resources like sound, video, joystick and so on, the DLL must take care of possible resource conflicts. A5 shares its resources and expects the same from the code inside the DLL. For instance, code that requires exclusive access to the sound device (like some old MOD players) won't work. Some resources (like the midi player) can't be shared - if midi music is played by the DLL, A5 must not play a midi file at the same time. Also care must be taken that for writing something into the frame buffer it must be locked before, and unlocked afterwards. The interface library provides functions for that. This beta version comes with a DLL "ackdll.dll" that contains just a few simple example functions. "PaintScreenWhite" just paints the screen buffer all white, thus generating a brief white flash. "FlipUpsideDown" will roll the given entity by 180 degrees. The C source code for the DLL is included in dllsdk.zip. The documentation and the header files are yet uncomplete. For testing the DLL, just copy ackdll.dll into your game directory, and insert the following WDL instructions into a function assigned to a key: dll_open("ackdll.dll"); dll_exec("PaintScreenWhite",0); dll_close(dll_handle); For creating a new DLL, just unzip the SDK into any directory and open it as a VC++ project. The following WDL instructions deal with DLLs: dll_open(string) Opens and activates a DLL extension for A5, and returns a DLL handle. The predefined variable DLL_HANDLE is also set to that handle. The DLL handle is only needed if more than one DLL is used at the same time. The DLL file must really exist in the game directory, it can't be encrypted in a resource file. If the DLL is not found, 0 is returned. Example: var effects_handle; ... effects_handle = dll_open("effects.dll"); dll_close(handle) Closes the DLL with the given handle. The handle becomes invalid after this instruction. All open DLLs must be closed upon exit. dll_exec(string,argument) Executes a function within the DLL given by the DLL_HANDLE variable, and transfers the argument to it. The string contains the function name. The argument can be a number, a variable, or any WDL object like an entity, a VIEW, a TEXT, a STRING etc. The structure of important WDL objects will be given in the A5 header file that comes with the SDK, and described in the A5 Programmer's Manual. If a vector or array is given as argument, only its first number is transferred. If the DLL function returns a value, it will be returned to the WDL script. Examples: dll_exec("MoveBounce",MY); dll_exec("PlayMP3","mysong.mp3"); temp = dll_exec("SquareRoot",temp); dll_exec("Capitalize",my_string); dll_exec_vec(string,vector) Executes a function within the active DLL, and transfers a vector or array to that function. Other than DLL_exec, not the first number itself, but a pointer to the first number of the array is transferred to the function, from which the other numbers can be determined. Example: var joyffback[2]; ... joyffback[0] = 20; joyffback[1] = -50; DLL_exec_vec("DoForceFeedback",joyffback); DLL SDK (A5 professional edition) Two new functions in the a4dll.lib provide DLL access to internal WDL variables, objects and functions. This way, actor AI can now be implemented in a DLL plugin. long a5dll_getwdlobj(char *name) This C function returns the address of the WDL object or variable with the given name. It can be used to read or write any defined WDL object from inside a DLL plugin. If the object does not exist, NULL is returned and an error message will pop up. Examples for DLL functions that access WDL objects: // adds the given value to the sky speed fixed AddToSkySpeed(fixed value) { // get the address of the variable fixed *skyspeed = (fixed *)a5dll_getwdlobj("sky_speed"); if (!skyspeed) return 0; // add the value to both the x and y components skyspeed[0] += value; // skyspeed X value skyspeed[1] += value; // skyspeed y value return INT2FIX(1); } // zooms the camera view fixed ZoomIn(fixed value) { A4_VIEW *camera = (A4_VIEW *)a5dll_getwdlobj("camera"); if (!camera) return 0; return (camera->arc -= value); // change the FOV and return it } long a5dll_getwdlfunc(char *name) This C function returns the address of the WDL function with the given name. It can be used to execute WDL functions from inside a DLL plugin. Only new 'javascript style' functions are returned. If the function is not available for use in a DLL (as can be the case for some old or special WDL functions, like INKEY), NULL is returned and an error message will pop up. Example for a DLL function that uses WDL functions for scanning the environment of an entity: // returns free distance in front of MY entity until next obstacle fixed DistAhead(long my) { if (!my) return 0; // retrieve the pointer to the given entity A4_ENTITY *ent = (A4_ENTITY *)my; // get the address of some wdl variables and functions fixed *tracemode = (fixed *)a5dll_getwdlobj("trace_mode"); wdlfunc2 vecrotate = (wdlfunc2)a5dll_getwdlfunc("vec_rotate"); wdlfunc2 trace = (wdlfunc2)a5dll_getwdlfunc("trace"); if (!tracemode || !trace || !vecrotate) return 0; fixed target[3] = { FLOAT2FIX(1000.0),0,0 }; // trace target vector // rotate vector by entity engles, just as in WDL (*vecrotate)((long)target,(long)&(ent->pan)); // add entity position to target target[0] += ent->x; target[1] += ent->y; target[2] += ent->z; // set trace_mode, then trace a line between entity and target, // and return the result *tracemode = INT2FIX(TRM_IGNORE_ME + TRM_IGNORE_PASSABLE + TRM_USE_BOX); return (*trace)((long)&(ent->x),(long)target); } Path instructions (A5) ================================================ WED Through Object->Add Path a closed path can be placed which can then be used by actors or for other purposes. You can give the path a name through Properties; otherwise a default name is created. In Vertex Move mode the waypoints can be created and moved. When a path is selected, pressing [Ins] while dragging a waypoint creates another waypoint at the mouse position. The first waypoint of a path is marked by a surrounding square. ent_path(string) (A5) Finds the path with the given name, and assigns it to the MY entity if there is any. If the path is not found, 0 is returned; otherwise the number of waypoints is returned. The TARGET vector is set to the first waypoint of the array. Example: ent_path("path_001"); scan_path(array,vector) (A5) Like SCAN, but finds the next path with its first waypoint in the scan cone, and assigns it to the MY entity. The array must have at least 5 numbers. The first three numbers give the scan position, the next two the PAN and TILT angle of the scan direction. The x position of an entity can also be given here as an array that contains the entity position and angles. The PAN and TILT values of the vector give the width, the Z value gives the range of the scan cone. If a path is found, it is assigned to the MY entity if there is any. If the path is not found, 0 is returned; otherwise the distance to the first waypoint is returned. The TARGET vector is set to the first waypoint of the path. This instruction can be used to attach a nearby path to an entity. Example: temp.pan = 360; // full sphere temp.tilt = 180; temp.z = 1000; scan_path(my.x,temp); ent_waypoint(vector,number) (A5) Sets the vector to the MY entity's waypoint with the given number. The total number of waypoints is returned. ent_nextpoint(vector) (A5) If the vector was set to a waypoint of the MY entity's path, this instruction sets it to the next waypoint. Otherwise, the vector is set to the first waypoint of the path. The number of the new waypoint is returned. The following simple example, which was added to ACTORS.WDL template, lets an actor walk along the next path, of which the first waypoint is within 1000 quants of the entity's position. It replaces the old patrol action: function actor_turnto(angle) // helper function, turn MY towards angle { angle = ang(angle - MY.PAN); if (angle > 10) { temp = force * 5; } else { if (angle < -10) { temp = -force * 5; } else { temp = force * angle * 0.5; } } MY.PAN += temp * min(1,time); } action patrol_path // let entity walk a circular path { actor_init(); // set _MOVE_MODE etc. temp.pan = 360; // find and attach path to entity temp.tilt = 180; temp.z = 1000; result = scan_path(my.x,temp); if (result == 0) { return; } // no path found ent_waypoint(my._TARGET_X,1); // store first waypoint while (my._MOVEMODE > 0) { temp.x = my._TARGET_X - my.x; // find direction to waypoint temp.y = my._TARGET_Y - my.y; temp.z = 0; result = vec_to_angle(my_angle,temp); // near target? Then find next waypoint if (result < 10*time) { ent_nextpoint(my._TARGET_X); } // turn and walk towards target force = my._FORCE; actor_turnto(my_angle.pan); actor_move(); // predefined function in actors.wdl wait(1); } } Other instructions ==================================================== trace() When SCAN_TEXTURE is activated for the trace_mode, and the trace hits a model, sprite, or terrain, the file name of that entity is returned in the tex_name string. When IGNORE_PUSH is activated, the trace ignores all entities with lower push values than the MY entity. play_cd() (A5) The CD audio track player is now also included in the A5 commercial edition. snd_playing(handle) If the sound with the given handle is still playing, this function returns 0, otherwise 1. Note that sound handles are not saved, so they become invalid after a LOAD operation. scan_entity(array,vector) Like scan_path, but finds all entities within the scan cone, except the MY entity. Replaces the old SCAN instruction. ent_move(vectorRel,vectorAbs); Moves the MY entity like the MOVE instruction, and returns the distance covered. Unlike MOVE, ent_move can also be used from external DLLs. Various move modes can (and must) be set through the predefined move_mode variable before. The following move modes are available: IGNORE_YOU - ignores the YOU entity on collision detection. IGNORE_PASSABLE - ignores all passable blocks and entities. IGNORE_PASSENTS - ignores passable model and sprite entities. IGNORE_MAPS - ignores all map entities. IGNORE_MODELS - ignores all models. IGNORE_SPRITES - ignores all sprites. IGNORE_PUSH - moves over all entities with lower push values than MY. ACTIVATE_TRIGGER - enables trigger events. GLIDE - glides along walls and entities on impact. Example: move_mode = IGNORE_YOU + IGNORE_PASSABLE + IGNORE_PUSH + ACTIVATE_TRIGGER + GLIDE; result = ent_move(reldist,absdist); // same as MOVE MY,reldist,absdist; Variables and strings ================================================= Extended joystick support (A5) Up to ten joystick buttons can now be handled through the variables JOY_1..JOY_10 and ON_JOY1..ON_JOY10. Up to six axes can be read through JOY_RAW.X, JOY_RAW.Y, JOY_RAW.Z, JOY_ROT.X, JOY_ROT.Y, and JOY_ROT.Z. All axes have a range of -255..+255. Through simple WDL arithmetics the range can be changed. Example: throttle = 50 - (50/255)*JOY_RAW.Z; // gives throttle 0..100 range Fps_min This variable (default 4) limits the range of the time variable to a minimum frame rate. Below that frame rate, time stays constant. pos_resolution This variable selects the resolution of entity positions. At 0 (default) the resolution is 0.125 quants. At 1 the resolution is 0.001 quants, allowing for extremley huge levels of hundreds of square miles with very low scaled models. Objects fixed very close to the camera, like a weapon, are moving smoother in high resolution mode. The drawback is a 25% increase of the response time for multiplayer games. Pos_resolution must be set before loading the first level, and must not be changed during gameplay. d3d_mode This read-only variable reflects the quality of the 3D card; 0 = incapable, 1 = weak, 2 = slow, 3 = good (later 4 = T+L). It can be used to reduce the LOD on weak and slow 3D cards, increase the ambient light to compensate the low-contrast picture of weak 3D cards, or give the user advices to buy a better card. app_name This string contains the name of the application, for instance "office" when the main WDL file name is OFFICE.WDL. Entity parameters ===================================================== LOD - geometric levels of detail (A5) The rendering of a detailed model with ten thousands of polygons looks quite good when the model is close to the camera. However when the same model is far from the eye point, details are less noticeably. A simpler model with few polygons will look just as good in that situation, but render faster. The difference in rendering speed is quite remarkable in huge outside levels where lots of entities are visible, like trees in a wood, or an ork army, or a city made from house map entities. To get the best of both worlds, each entity can now be given up to 4 map, model or sprite files, which change automatically dependent on the distance of the entities' centre to the camera. The three further files can be assigned through the keywords LOD1, LOD2, and LOD3 in an arbitrary entity definition, like: ENTITY lodgun { TYPE ; LOD1 ; // at 12.5% clip_range LOD2 ; // at 25% clip_range LOD3 NULL; // invisible above 50% clip_range } The entity switches to LOD level 1 at a distance of 1/8 the clip_range, to level 2 at 1/4 the clip_range, and to level 3 at 1/2 the clip_range. If it's more far away than the clip_range, it won't be displayed at all (as before). LODs can also be used for creating 4 level MIP mapping for sprites. The LOD levels are valid for all entities that use the gun.mdl in the example. They must be of the same type; a model should not change into a map or a sprite. The number of frames and the frame names must be the same on all LOD levels. If NULL is given instead of a file name, the entity is not visible at the LOD level. This way, sub-entities of an entity composed of several parts can be suppressed above a certain distance. If a model has several LOD levels, it's shadow is calculated from one further level than the displayed model. This way dynamic shadows can now be rendered remarkably faster. If the model is further away than 50% of the clip_range, no shadow is rendered at all. Texture uv shifting (A5) The offset of map entity textures can now be set through the entity's U and V parameters in D3D mode. This way effects like streaming water can be achieved. Example: action water_current // assign to a water block { while (1) { my.u += 5*time; my.v += 5*time; wait (1); } } Transparent map entities (A5) Map entities can now be displayed translucent in D3D and 8-bit mode by setting their TRANSPARENT flag. In D3D mode, the translucency factor can be set through the entities' ALPHA parameter. Transparent water can be created by placing a transparent water block entity into a pool (and the water level can easily rise or fall this way). A transparent water block was placed into the office level as an example. Flare models (A5) If a model's flare flag is set, its skin will get a flare characteristic like with sprites. Alpha entity parameter (A5) The transparency of model and sprite entities in 16 or 32 bit mode can be controlled by the alpha entity parameter (0..100, default 50). At 0 the entity is totally transparent, at 100 it is totally intransparent. This way entities can smoothly be faded in and out. The transparent flag must be set. Example for fading in an entity: MY.transparent = ON; MY.alpha = 0; while (MY.alpha < 100) { MY.alpha += 5*time; wait(1); } MY.transparent = OFF; MY_ALPHA (A5) Sets the opacity percentage (0..100, default 50) of transparent particles in 16 or 32 bit mode. At 0 the particle is totally transparent, at 100 it is totally intransparent. View/Panel/Text parameters ============================================ offset_x offset_y (A5) Through those view parameters an eye point offset can be set. At 0 the eye point is in the center of the view as before; at -0.5 it is at the left or upper edge, at 0.5 it is at the right or lower edge of the view window. It must not be outside the view edges. The eye offset can be used for driving or flight simulators where the driver or pilot sits at the right or left side of the screen. Example: // set the eye point for a pilot in a two-seater camera.offset_x = -0.33; Alpha panel parameter (A5) The transparency of a D3D panel in 16 or 32 bit mode can now be controlled by the alpha panel parameter (0..100, default 50). At 0 the panel is totally transparent, at 100 it is totally intransparent. Panel elements like buttons inherit the alpha value from the panel. This way panels, buttons etc. can smoothly be faded in and out. The panel's transparent flag must be set. Example for fading in a panel: my_panel.transparent = ON; my_panel.alpha = 0; while (my_panel.alpha < 100) { my_panel.alpha += 20*time; wait(1); } my_panel.transparent = OFF; ALPHA (A5) TEXT objects now also support the ALPHA transparency parameter, like panels. DIGIT displays inherit the ALPHA value from their panels. Mirrored view (A5) If the arc of a view has a negative value, the view is now horizontally flipped in D3D mode. This way rear view mirrors can be realized. Miscellaneous ========================================================= "E1511 - dangerous instruction in event!" This runtime warning message will be issued when the given event function contains bad WDL code - mostly, a forbidden instruction (which changes something in the level or can trigger an event, like move, remove, trace, scan etc.) in the first cycle of the event. Insert a wait(1) before that instruction. The message is only issued when the warn_level variable is set above 1 on A4, and above 0 on A5. =======================================================================