Jump to content
  • A History of the Custom Scripts.dll


    OWA

    Introduction

    This Article is by Jonathan Wilson, Lead Programmer at Tiberian Technologies and Head of Scripts.dll Development 

     

    Before I start the story of scripts.dll, let me say that I have been involved with modding for the C&C series since the beginning. I was the first person to figure out the RLE compression used for the .shp files of Tiberian Sun and I spent many hours in the debugger extracting filenames for the old games (anyone who knows how the old games worked will know that they didn't store filenames in the mix files and the community had to figure out the correct filename for all the files in each mix file).

    Origins

    The scripts.dll story begins when the mod tools came out.

    When they came out I started fiddling with them and pulling the game and tools apart to see how they worked (as I had done with previous games).

     

    I wrote a number of things back then including a fairly primitive W3D viewer (I still remember asking Greg Hjelstrom a LOT of questions to fill in the gaps in the knowledge of the w3d file format).

     

    In terms of scripts.dll and its history, I did 3 things at that point. Firstly, I was involved (with a few others from memory) in convincing Greg to write a few rather useful scripts and include them in one of the later patches to Renegade. (these are the scripts that start with GTH).

     Secondly, I was involved in an effort to convince EA to release (to the public) the source code to the scripts.dll (not the engine itself, just the scripts.dll) to allow people to write their own gameplay scripts. This didn't happen (despite a fairly well-supported online petition) mostly because EA was concerned about the code being abused (malware etc).

     

    And thirdly I was pulling the scripts.dll apart to figure out how it worked and what various of the scripts actually did. The first result of this was a tool called "scripts test" that simply dumped a list of all the scripts in the scripts.dll.

     

    Other than the leveledit debug strings I found (and what I was able to figure out from reverse engineering and testing) I did also make use of a bunch of info given to me by Greg Hjelsrom at various points (I wont go into details since I don't have all the relavent emails etc handy and I probably should say too much in public anyway but lets just say that info was vital to getting things to work in those early days.)

     

    My memory is a little hazy as to when I first decided to start writing my own gameplay scripts but the first official release came out on the 20th of August 2002 and was named version 0.9 beta. According to the old readme file I found (the only part of 0.9 beta I still have), version 0.9 beta contained 3 scripts named JFW_Spawn_Object_Death,JFW_Create_Objective_Death and JFW_Update_Objective_Death. JFW_Spawn_Object_Death (the first script I ever wrote) is still in the scripts.dll even today (and what the script does hasn't changed in all that time). The reverse engineering work at that time was (from memory) mostly done with various versions of IDA Pro (I forget if I was still using SoftIce for Renegade or not) and all the code was being written with Visual Studio 6.0.

     

    That was quickly followed by 0.91 beta, 0.92 beta, 0.93 beta, 0.94 beta, 0.95 beta, 0.96 RC, 0.97 RC, 0.98 RC, 0.99 RC, 1.0 RC1 and then 1.0 RC2 (the oldest version I still have on my disk). Work continued on figuring out the internals of scripts.dll and the way scripts.dll talked to the engine (to expand what scripts.dll could do). By the time 1.0 RC2 hit, I had discovered a new source of information in the form of debug strings in the Renegade level editor. This gave us (the people working on scripts.dll at the time) the names of a bunch of things in the engine (including lots of the script commands).

     

    Most of the work at this point was done by myself, Dante and Sir_Kane although some scripts had also been written by NameHunter. 1.0RC2 contains somewhere around 80 scripts or so, mostly written by me but also a few by NameHunter and Dante. Highlights include the first construction yard scripts,the beginnings of AI scripting and some nice utility functions including the first functions for sending a custom on zone entry.

     

    The next part will cover the rest of the 1.x series (I no longer have copies of 1.0 final, 1.1, 1.1.1, 1.2 or 1.3 but I have all scripts versions from 1.3.1 through to 1.9.3 and will be able to talk more about what changed through those versions)

    Scripts 1.x

    Scripts 1.0-1.9

    After 1.0 RC2 came 1.0 final (which I no longer have) then 1.1.

    I still have an incomplete copy of a build labeled "1.1" in the readme file (although I dont know exactly what build it is, whether its 1.1 or 1.1.1 or something in between builds or what)

     The big change in 1.1 was the discovery of a complete symbol table in the Linux FDS (in layman's terms its a list of all the functions in the executable file with their names and definitions). Discovering this allowed me to completly rewrite the code to be a lot more like the original Westwood way of doing things. Too many changes between 1.0 RC2 and the code I have labeled 1.1 for me to go into any more detail.

     

    Then after 1.1 came 1.1.1, 1.2, 1.3 and then 1.3.1 (the next build I still have)

    In the time between the 1.1 code I have and the 1.3.1 release, work continued on reverse engineering the engine and I continued to write scripts to do cool stuff (and to take advantage of any new engine discoveries I made). NameHunter wrote more scripts and the first scripts for Reborn (not sure who wrote these early scripts) and RenAlert (written by Dante) were written. Also some scripts for something called Survival (not sure what this was or who wrote these early scripts) got written.

     

    1.4 continued the general improvements along with more new scripts by me. This also marked the start of some scripts being written by Vloktboky. Further additions were made to the Reborn scripts (not sure by who) and the RenAlert scripts (this marked the beginning of work on RenAlert scripts by NeoSaber)

     

    New in 1.5 was support for the Linux FDS thanks to Datalore (who did a great job of dealing with the funky way GCC does inline assembler and the other Linux-specific weirdness). Also new in 1.5 was a refactoring of some core code to be closer to how the real thing is laid out along with more engine research and general improvements. New scripts were written by Vloktboky and myself.

    1.6 had more scripts by me, more cleanups, more scripts by Vloktboky, a couple new scripts by NameHunter and some new RenAlert scripts by NeoSaber. It also introduced some scripts for a mod called RA2 Vengeance.

     

    1.7 had still more cleanups and engine research, more scripts by me (including the cloning of a bunch of interesting stock scripts), more scripts by NeoSaber (both for RenAlert and otherwise), some new scripts from TimeFX and a bunch of scripts from E! for a Generals mod called SCUD Storm.

     

    In 1.7.1, the big change was a move from Visual C++ 6 to Visual C++ .NET 2003. Cleanups and engine research continued although this build contained no new scripts.

     

    1.8 introduced the first engine calls (with a LOT of hacks involved). Cleanups and general engine research also continued. More scripts for Scud Storm, RenAlert and RA2Vengeance were added along with new scripts by me.(including more clones of stock scripts). One of the engine calls introduced in this first batch was the first engine call to use the special "debug fly" flying infantry logic westwood left in the game.

     

    Scripts 1.9 was a major milestone with the first engine hacks being added. New console commands were added. Various engine calls were fixed to work over the network including animation, stealth, explosions, audio and poke. Exported engine functions were made available to do per-player screen fade and player terminal display. Fixes, cleanups and engine research continued as usual. More engine calls were added to engine.cpp including console input and output calls. New scripts were added by me along with new RenAlert scripts from NeoSaber.

     

    1.9.1 was just some bug fixes on top of 1.9.

    1.9.2 was more bug fixes on top of 1.9.1.

    1.9.3 was just a bug fix on top of 1.9.2.

    Scripts 2.x

    Scripts 2.0 - 2.1

    2.0 was released around xmas of 2004 and by this time the Blackhand Studios development group was well established and quite a few other people also worked on engine work besides me  (I dont plan to cover things like RenGuard or the Core Patches in this history series, nor do I plan to cover things written by other people like brenbot, the old pre-4.x SSAOW/SSGM/SSCTF stuff, Dragonade or Renegade Resurrection)

     

    In 2.0, a number of script commands were made to work correctly in multiplayer including screen fade. Per-player commands were added for playing audio and some other things. The first commands to display messages on the client were added in 2.0 as well. Various other bhs.dll fixes were made including making Set_Model work correctly over the network for vehicles and infantry and stuff and making the harvesting arms of the tiberium harvester animate when its harvesting. A fix was also added for granting weapons to vehicles and changing the weapon of a vehicle. More console commands also got added.

     

    New engine calls got added to engine.cpp including engine calls to remove scripts from an object, get the occupants of vehicles, get the weapon an object is using, get the hierarchy/skeleton name of an object, get the "sex" of an object (so you can use the correct infantry animation set) and kick the occupants out of a vehicle.

     

    Some scripts were written by Dan, Vloktboky and myself along with an AI script from NeoSaber. General cleanups/fixes and engine research continued as usual. TheKGBSpy wrote more scripts for RA2 Vengeance. Due to some crap going on at the time that I wont go into, RenAlert wasn't shipping newer scripts builds or bhs.dll at the time but instead shipping their own thing (I will not be discussing the details of what was going on at the time since its long since over, all the people involved have left the community AFAIK, all the "secret" scripts were eventually published and all the engine know-how the relavent people were hoarding has long since been figured out)

    2.0.1 followed soon after and fixed a couple of bugs.

     

    Then came scripts 2.1. 2.1 added more new console commands. 2.1 also introduced code to output screenshots in .png format instead of the default .tga format. A hack was introduced that made maps load much faster but (unbeknownst to me at the time) made things load a lot slower in-game by disabling some code to pre-load and parse a bunch of w3d files on map load. The object create hook system was added in 2.1, as was the custom key hooks and the first version of the custom sniper scope code. Extra log files started to be created to log all sorts of messages (the details of why we started creating these log files is lost in the mists of time). The chat hook was first introduced in 2.1 as well as was a fix for the invisible harvester bug with airstrips. A fix was added to make the infantry death sound and powerup collection sound play in multiplayer. An engine call was added to get the version of bhs.dll.

     

    Engine research and general fixes/improvements/cleanups also continued in 2.1. Engine calls were added to access the cGameData instance among other engine calls.By this time we had figured out the initial definitions of classes in Renegade including cGameData and WeaponBagClass as well as utility classes like Vector4, Matrix3D, SList, SimpleVecClass, SimpleDynVecClass, VectorClass and DynamicVectorClass. I wrote more scripts including clones of all the "secret" scripts RenAlert was using at the time (and at that point was refusing to share). The first scripts to be written by scripts contributor and later engine guru Saberhawk got added in 2.1 as well.

    2.1.1 and 2.1.2 were just bug fixes on top of 2.1 to fix some issues with the AGT scripts.

     

    2.1.3 added some stuff to disable some of the logging on the client (since some people didn't want those logs). It also featured code cleanup and improvements and bug fixes and the first efforts to block specific "bad" nicknames (e.g. nickname too long, nickname containing bad characters etc). Code was also added to disable certain netcode that could be used to cheat.

     

    Scripts 2.2

    After 2.1.3 came 2.2 which was a big release.

     

    In 2.2, all of my scripts were re-organized into new source files divided up based on what sort of script it was (e.g. sounds, weapons, cinematics, vehicles, powerups, script zones etc). The usual cleanups, bug fixing and engine reverse engineering continued. New engine calls were added including the first engine call for changing the spawn character. Reborn got the first scripts for walkers/mecha and some new deployable vehicle stuff. I wrote some new scripts as well.

     

    bhs.dll got a lot of improvements. Lots of work went into bug fixing, fixing crashes etc. 2.2 introduced the new crashdump code where the code to emit _except.txt when crashes happened was ripped out and replaced with new code to spit out a crashdump.txt with more info than _except.txt had. This made debugging crashes much easier. The chat hook was modified to support unicode messages (important for players using foreign language characters like ö in their chat strings). A hook was added to allow you to listen to "host messages" (i.e. messages sent from the server in various ways).

     

    Scripts 2.2 was quickly followed up by scripts 2.2.1 and then 2.2.2. Both versions contained only bug fixes on top of 2.2.

     

    Around the same time as scripts 2.2 came out, I also released a hacked improved version of leveledit (numbered 1.0.0.4) that fixed a bunch of bugs. Highlights of this release included making it read scripts.dll/scripts2.dll from the Renegade folder (no more need to copy them to the mod folder), fixing some crashes, adding the "export to mix" menu option to the menus (the logic was already there, it just needed to be made visible), displaying the current mod package name on the status bar and properly reading the game data files (including always2.dat). 1.0.0.4 no longer had problems when placing certain objects like multiplayer helicopters.

     

    Scripts 2.3-2.4

    Scripts 2.3 hit in January of 2006. It featured the usual bug fixes, cleanups and engine research. It also added some stuff to make Set_Obj_Radar_Blip_Shape and Set_Obj_Radar_Blip_Color work over the network. Code was added to include the Windows version and the date and time in crashdump.txt files. An engine call was added to let you switch to a different main hud texture at runtime. Improvements were made to the keyhook stuff. More scripts were written by me. WhiteDragon also wrote some scripts and some stuff was added for Reborn.

     

    Scripts 2.3.1 then followed soon after with a few bug fixes.

     

    After that came scripts 2.4 a few months later.

     

    2.4 added some console commands to set and get the bandwidth for a player. The player join hook, load level hook and game over hook were added. The first hud.ini stuff was added (changing the colors used for the teams in chat etc). Engine calls were added to identify if running on Linux vs Windows and Dedicated server vs game client along with a way to identify the current game mode (WOL vs gamespy vs lan vs etc) and a couple of others.

     

    The usual scripts cleanup, bug fixing and engine research also happened for 2.4 along with some new scripts by me. The split between the RenAlert guys and myself went away and all the secret stuff stopped. My reverse engineered clones of the formerly-closed-source scripts were removed and replaced with the real thing thanks to NeoSaber.

     

    The "secret" scripts stuff was basically some stuff that for whatever reason the RenAlert guys didn't want to share. It had the missile silo scripts, CanyonRiver and Metro scripts, underwater stuff, submarine script and vehicle script. I dont want to go into details of the whole fight over the issue (and over the various engine related things that the "secret" scripts made use of) so this is all I will say on the matter.

     

    Scripts 2.5-2.6

    2.5 came out next and added a special console command and a few other things for the Linux FDS and some WOL stuff people were doing at the time. Code was added to disable the GameSpy serial number check (the GameSpy serial number database was missing serials from The First Decade so TFD players were unable to play on GameSpy without this change).

     

    More cleanups, fixes and engine research happened as well along with the addition of some engine calls for getting information from players (current money, current score, things like that) although no new scripts were added in 2.5.

    2.5.1 came out soon afterwards and fixed a bug with some things in 2.5 then 2.5.2 fixed more things.

     

    Next came scripts 2.6. The usual cleanups and fixes and engine research continued, as did some new console commands for changing the vehicle limit as well as the commands for sending messages to the client and having them appear in the chat box alongside messages like "unit ready". Display_Health_Bar was made to work over the network as well as entries in hud.ini to let you change the public and private message colors. Per-player radar blip shape engine calls were added at this point along with engine calls for vehicle limit and message sending.

     

    A bunch of new engine calls were added to engine.h including the first engine calls that worked with strings from strings.tdb. A bunch of new scripts got added by me.

     

    Scripts 2.7

    Scripts 2.7 again had the usual bug fixes/cleanups/engine enhancements.

     

    Console commands were added to disarm C4 and beacons for a player along with some more stuff for LFDS WOL work. The Disable_All_Collisions, Disable_Physical_Collisions and Enable_Collisions engine calls were made to work over the network. A hook that gets triggered any time a player sends their version to the server was added along with a Set_Wireframe_Mode engine call and some work on an engine call for removing a weapon from a player. The first attempt at code to let you change the PT data at runtime was also added.

     

    2.7 also marked the introduction of the first custom HUD code with large parts of the HUD (health/shield bar, time, credits, radar, weapons and other things) being customizable. Engine calls were added to engine.cpp for getting/setting the current ammo for weapons in various ways, disarming beacons and working with the PT data. 2.7 was the first version to expose the ini reading functionality to scripts.dll so people could use it to read and write ini files (instead of whatever code they had been using previously). I wrote some new scripts as did WhiteDragon.

     

    2.7.1 followed 2.7 and contained bug fixes.

     

    Then 2.7.2 followed 2.7.1 with more bug fixes.

     

    Scripts 2.8-2.9

    2.8 had more bug fixes/cleanups/engine research. It introduced per-player fog commands, Improvements were made to the code for sending the PT data changes over the network. Improvements were made to the custom HUD logic. New hud.ini keywords were added to let you change the cost and time multipliers that apply when the power is down, to disable the "locked to the player who bought it" logic, enable the use of the "hidden" PT pages globally and enable some special logic for purchasing. Fixes were made to try and stop certain server exploits. A change was made to make disabling the radar work better. Hooks were added for powerup purchase, vehicle purchase and character purchase as well as hooks for monitoring those purchase types (used if you just want to log things rather than actually change how the purchasing happens).

     

    Engine calls were added to get the build time multiplier (i.e. the value used to increase the build time when the power plant goes down), change some settings related to the scrolling radar map feature, set/get a flag that will display "building" for vehicle buttons (used as part of various scripts that I will get to later). Code was added to send everything that would be written to the console through a UDP packet (intended so you can have something such as a server bot catch it and do stuff with it and not need to parse log files for the same info).

    The first definitions of the classes NetworkObjectClass, OBBoxClass and BaseControllerClass were added. Engine calls were added to turn the base power off/on, toggle the base radar, find buildings of different types, identify if a map is a flying map (i.e. if the checkbox in LE is ticked), do things with script zones and some other stuff. I wrote some new scripts and some scripts written by Kamuix were added. Some new scripts written by WhiteDragon were also added including the first version of the ExpVehFac stuff for creating working naval yards and helipads where you buy stuff directly from the regular PTs

    After 2.8 came 2.9.

     

    2.9 included the usual cleanups/fixes/engine research along with new scripts by me. WhiteDragon wrote one new script. Engine calls were added to get the type and size of a script zone, to create a script zone at runtime and to identify if a given xyz coordinate is inside a given script zone. Console commands to change the player limit and time values were added. A new hud.ini keyword was added to turn off some code related to the disabling of the "vehicle" button when a vehicle is building. Hud.ini keywords were added to change a bunch of colors related to the UI as well as to disable the glow around the large menu item text icons. Hud.ini keywords were added to allow you to make certain units unsquishable and change certain things associated with the stealth texture. The first version of the sidebar logic also appeared in 2.9. A hook to grab all the console output was added along with a way to change the reticle textures for a given client at runtime. Engine calls to do things related to fog got added along with various ways to change the player limit. A fix got added for a glitch with the "start" button when connecting to XWIS/WOL and a hook to let you do special checks of hud.ini to prevent modifications for cheat purposes (the forerunner to the current scripts anti-cheat code). A new dialog box to display the chat history was added (since the sidebar doesn't have an inbuilt chat history like the PTs do)

     

    2.9.1 followed up with some bug fixes and then 2.9.2 came after that with more bug fixes as well as some changes to prevent people mixing incompatible versions of scripts.dll and bhs.dll (e.g. trying to use a newer bhs.dll with an older SSAOW or similar)

    Scripts 3.x

    Scripts 3.0

    3.0 was the first release to include the massive graphics enhancement that was shaders.dll. Saberhawk contributed a lot of the graphics code to this release and StealthEye did work on the netcode. This was the first version built using Visual C++ 2005.

     

    Console commands to display a w3d file in-game and to turn off the HUD were added. More information was added to crashdump.txt. Improvements were made to the custom hud code. More colors related to the UI became customizable. Purchase sounds were added to the sidebar. A fix was added for vehicles getting stuck near ladders (including aircraft flying over them). A player leave hook was finally added. "wall lag" was fixed. C4 objects now triggered scripts attached to them properly. Turret lag was fixed. The first version of the "extended options" dialog got added (to allow in-game setting of various scripts.dll options). An engine call was added to trigger the "you aren't allowed to use this dialog" (like you get when you use an enemy PT).

     

    Renegade was updated to detect more video cards and driver versions. 3.0 was the first version that moved Renegade so it was using Direct3D9 instead of Direct3D8. The shadow quality was improved. Programmable shader stuff was added including a normal mapping shader, a glass effect shader, a glow shader and some post-processing shaders. The usual scripts cleanups/fixes/engine research continued. A lot more classes in the game had their definition figured out or expanded/fleshed out (including for the first time, several of the GameObject classes). Engine calls were written to open a file (such that it would read from the mix files or data folder as appropriate), access weapon and ammo definitions and do some other stuff.

     

    The first scripts for the RenAlert gap generators were added in 3.0 along with some other scripts for that mod. A clone of the Test_Cinematic script was added and I wrote several other new scripts. Kamuix wrote some more scripts as did WhiteDragon. Saberhawk wrote one new script. Work was done to make sure the scripts compiled with Visual C++ 2005 Express (the free version)

     

    Scripts 3.1

    Scripts 3.1 came out shortly before xmas of 2006 and contained a lot of bug fixes, cleanups and engine research. The "vsync" feature was added. I wrote some new scripts. Stuff got added to do different things with shaders and scopes. 3.1 may not sound like a big release but a lot of bug fixing and cleanup went into it to try and solve as many of the "3.0 sucks" complaints that were happening on renforums at the time.

     

    3.1.1 followed soon after with a bunch more bug fixes and cleanups then 3.1.2 soon after with more fixes. Work continued on solving all the crashes and glitches people were reporting. A lot of the problems people had with the 3.x released turned out to be crappy graphics drivers, having shaders enabled on cards that just couldn't handle them properly or using the example shader databases in ways they weren't intended for.

     

    3.1.3 came out next and had more bug fixes and cleanups. Then 3.1.4 followed (which was 3.1.3 with bhs.dll from 3.1.2 since I was unable to release a new bhs.dll at the time)

     

    Then came 3.2 with even more bug fixes, cleanups and engine research. The graphics system continued to be improved and fixed. 3.2 also improved the generation of crashdump files so it wold keep multiple dumps around. Improvements were made to the unsquishable logic and a hud.ini keyword was added to let you disable the standard kill messages. Extra debug logging was added to the d3d9 code. Lots of shader work was done. "post process" shaders were renamed scene shaders. Some new memory leak detection code was added to the scripts.dll and a lot of memory leaks fixed (including memory leaks that existed in the stock game). Multi-sample anti-aliasing was added. An engine call was added to help you identify what object caused an explosion when one happens (i.e. beacon/c4 explosions). A bunch of classes were mapped out and reverse engineered and a bunch of engine calls (including one to let you iterate the player list) were added.

    The old engine.cpp file was split up into multiple files to make it easier to manage. A lot of effort was put into performance as well. The first use of SSE in scripts.dll happened in 3.2. I wrote some new scripts. The first scripts for the Roleplay2 mod by Jerad Grey were added along with some more scripts from Kamiux. Zunnie wrote his first scripts and some more scripts were added for APB. The custom HUD code was further improved (and a chunk of it was opened up in shaders.dll at this point, a decision I still regret to this day).

    3.2.1 followed with more bug fixes then 3.2.2 followed with even more fixes and 3.2.3 with yet more fixes.

     

    Scripts 3.2

    Scripts 3.3 came next. In 3.3, the Control_Enable command was made to work over the network. Improvements were made to the shader code. Some font code was cloned, rewritten and improved. Support for "shader plugins" (which with the benefit of hindsight was a stupid idea) was added. The vehicle management dialog was added to let you kick people out of your vehicle. More fixes, cleanups and engine research continued as per usual. A Set_Vehicle_Gunner engine call was added. I wrote some new scripts. The normal map shader was improved (in particular fog now affected normal mapped objects). APB got some new scripts.

    Then came 3.4. with more bug fixes/cleanups/engine research. A feature was added to change the default sort order for WOL servers so it sorted by player count rather than name (this took away the incentive for people to horde nicknames like aaaaaaaaaaaaa just to be first on the list). I write some more new scripts. Saberhawk added one new script and one script was written for APB.

    3.4.1 followed soon after that with a bunch of bug fixes then 3.4.2 with more bug fixes, 3.4.3 with more bug fixes again then 3.4.4 (the final release of the 3.x series) came after that.

    Credits

    I would like to give thanks to all the people who's help in many different ways has made the scripts.dll project what it is today.

    • Greg Hjelstrom
    • Greg Underwood
    • Aaron "Apoc" Kaufman
    • Olaf Van Der Spek
    • StealthEye
    • Ghostshaw
    • WhiteDragon
    • Dblaney
    • danpaul88
    • Saberhawk
    • Sir_Kane
    • Chronojam
    • NeoSaber
    • Deezire
    • moonsense715
    • Romanov
    • CCHyper
    • Jerad Grey
    • Triattack
    • Zunnie
    • YRR
    • E!
    • Vloktboky
    • TheKGBSpy
    • EvilWhiteDragon
    • Mac
    • Crimson
    • Blazer
    • v00d00
    • Scorpio9a
    • Reborn
    • Pushwall
    • Wallywood
    • Dante
    • Datalore
    • NameHunter
    • TimeFX
    • GeneralCamo

    • Laeubi

    • ChopBam

    • OWA

    And of course all the people involved in producing C&C Renegade and all the C&C Renegade Mods that exist out there and in testing the scripts.dll over the many years of development and anyone else I forget who has somehow contributed in some way to getting us where we are today.


    User Feedback

    Recommended Comments

    There are no comments to display.



    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Guest
    Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
    Add a comment...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...