Everyone

This Content can be viewed by everyone, even people with no account.

Forums

ALFA Release Notes v1.87

Change Log

As a note to builders: there is a new release of NWScriptCompiler. Builders should pick it up for use in their building.

As a note to players of Warlocks: there are many changes to invocations in this update. However, this list should be taken as mostly-complete, and Warlock players can expect their class' mechanics to be much more stable going forward. However, the class is not in a high-enough-quality state to allow new characters to take the class, as some portions of its core mechanics remain fundamentally flawed and nearly unfixable.

General Fixes

  • The ACR will no longer allow characters with trailing spaces on their names to be created. 
  • The templates provided with automated crafting now distinguish between arcane and divine
  • Crafting prototypes should no longer appear in duplicate in the craft store.
  • The DMFI renaming tool allows 48 character strings, instead of 32
  • Svirfneblin should have less mysterious trouble swimming
  • Another instance of "Rick" claiming to be a kind of clicking has been removed from the load screens.
  • The "phat lewt" random loot system will now break the weak and fragile items, instead of the heavy and sturdy ones, when bashed.
  • Kuo Toa are closer to their canonical size (about 5' tall)
  • Putting containers in pChests should no longer result in duplicate items.
  • pChests are now less vulnerable to "sticking" open.
  • Automatically-closing doors now look for PCs on both sides of the area transition to see if they're ready to close.
  • NPCs are less prone to dropping excessively-valuable items when slain.
  • A missing music file imported from Icewind Dale is corrected.
  • Stores which are opened with the default NWN2 scripts no longer exibit any of the appraise-related misbehaviors.
  • Killing-related ACR quests will more frequently credit quest advancement if a party member kills the quest creature.
  • Adjusting the appearance of items no longer logs the adjustments as acquiring the item.
  • Changing appearance to a default player appearance no longer sets movement rate to "Slow." However, this does not prevent movement from being broken when changing appearance away from a standard character model-- only between them.
  • If a player logs in with a character with non-default movement, the ACR will automatically correct the movement. However, nwn2server will not recalculate the actual walk speed until the login following. A message explaining as much will be provided when this happens.
  • Weapons will no longer have -5 damage permanently stick on them after disabling subdual damage mode, and previously-bugged weapons can be corrected by equipping them and toggling subdual mode on and off.
  • Subdual Damage turns itself off when a player dies, and bugs of a rapid infinite loop of nonlethal damage fists being created and stripped no longer happen.
  • The subdual damage item property no longer changes the price of the item it's applied to.
  • Precise Strike and Insightful Strike now help subdual damage.
  • Favored enemy bonuses now apply in subdual combat
  • Bardic Inspirations are now treated more-consistently as songs, and now use a daily use of bardic music to activate and are mutually-exclusive with stealth.
  • Young dragons now occupy space and provide a selection GUI more appropriate to their actual size.
  • The ACR Spawn system now works with instanced areas.
  • Instanced areas assume that they need to clean themselves up after a minute of inactivity if no cooldown is specified.
  • Only player characters will count as party members when calculating XP.
  • Reports of the current date won't count the 10th day of a tenday as "day 0" it will correctly report as "day 10."
  • Quarantined characters no longer save to the central vault.
  • Swim actually applies double ACP, as it claims.
  • Swim triggers are better at picking the creature leaving on that event, and are thus less likely to prompt unexplained swim checks on people elsewhere on the server.
  • Many skill descriptions that had invalid text in them are corrected.
  • Darkvision may now be used successfully as an item property.
  • Combat Expertise and Improved Combat Expertise have taken many changes:
    • The armor class bonus provided by (Improved) Combat Expertise may no longer exceed the user's base attack bonus.
    • (Improved) Combat Expertise now provides Dodge AC, instead of Untyped, and thus offers no benefit when flat-footed.
    • (Improved) Combat Expertise is now disabled when casting spells or using spell-casting items.
    • (Improved) Combat Expertise now has a server-side-enforced cooldown of 6 seconds.
    • These changes should cover our standing enforcement issues with Combat Expertise and Improved Combat Expertise. Old orders about how the feats may be used and the penalties for their misuse are thus rendered null.
  • VFX provided by PC tools are now purged during casting of Wildshape, and associated crashes should no longer occur.
  • Forge Ring, Craft Rod, Craft Staff, and Craft Construct have their advertized caster level prerequisites.
  • There is no experience point reward for fighting a creature whose CR is less than your character level by more than 8
  • Wizards automatically learn the new cantrips as part of converting to the new ACR.
  • Sorcerers now gain cantrips on every odd-numbered level to a maximum of 9, instead of 6.
  • The additional availability of orisons may cause higher-level Favored Souls to acquire a couple orisons unexpectedly (there were previously 7 available, but the class was configured to allow up to 9).

Class Changes

  • Rangers now receive Endure Elements as a level 1 spell.
  • Favored Souls no longer receive Haste 3/day at level 17.
  • Though Song of Regeneration and Curse Song were banned long ago, they are removed from feat lists this release.
  • Clerics no longer get access to Control Undead
  • Cleric Domain spells are moved to align with the SRD / Forgotten Realms Campaign Setting / Player's Guide to Faerun where possible. Many of these spells are redundant compared to the typical spell list-- due to NWN2's generally-lax implementation of the domain spell slot, these spells are thus not very visible to clerics who use them.

Spell Changes

  • Word of Faith is split into Holy Word, Blasphemy, Dictum, and Word of Chaos, selecting the appropriate spell based on the caster's alignment when casting. Unlike Word of Faith, these spells are not party friendly, and they may not effect any target with more hit dice than the caster's caster level. Effects applied to targets now must satisfy a caster level requirement (HD <= CL - 10 for death; HD <= CL - 5 for severe effect; HD <= CL -1 for minor effect; HD <= CL for trivial effect). Duration for all effects is random, uneffected by caster level, and shorter for the more-minor effects, on the same pattern as the SRD implementation.
  • See Invisibility now lasts 10 minutes / caster level, instead of 1.
  • Devour Magic is now touch range and single-target only (previously targeted identical to Dispel Magic).
  • Beshadowed Blast now only applies blindness penalties once, and can be appropriately resisted by abilities like Blindsight (previously stacked direct penalties with the blindness effect, making it impossible to resist and doubling penalties on those who weren't protected).
  • The damage over time on Brimstone Blast is now dispellable, and does not stack with itself.
  • The damage over time on Vitriolic Blast is now dispellable, and does not stack with itself.
  • Dark One's Own Luck now only provides a bonus to the lowest saving throw of the caster (though it may be cast multiple times to cycle through the different saving throws), and its bonus is capped by caster level (previously +cha to all saves, no CL cap).
  • The Dead Walk now lasts 1 minute/ level (previously hour/level)
  • Chilling Tentacles no longer applies paralysis. It applies a combination of physical and cold damage, and attempts to grapple targets in the area of effect (previously all magical damage).
  • Entropic Warding's benefits against tracking no longer manifests as a bonus to stealth (previously +4 hide/ms).
  • Flee the Scene is now a short-range dimension door, operating by line of sight (previously 1 hour of haste).
  • Hellrime Blast now lasts 10 minutes, and does not stack with itself (previously 3 rounds).
  • Retributive Invisibility only stuns for 1 round on success (previously 3).
  • Tenacious Plague now creates actual swarms, which occupy space, do not move, and do not stack on top of themselves. Characters caught in a plague's swarm must make a fort save to resist nausea each round they remain; tenacious plague is not party friendly, but the swarms' placement will initially be based on the location of enemy targets (previously, it was a terribly-ineffective damage over time effect).
  • Utterdark Blast's negative levels now last one hour (not permanent).
  • Wall of Perilous Flame now does 2d6 + caster level damage when entered (previously 2d6 + charisma modifier) and 2d4 damage per round (previously 2d6 + charisma modifier)

New Spells

  • Waterbreathing (clr 3, drd 3, sorc/wiz 3, water 3)
  • Alarm (RP only)
  • Analyze Portal (RP only)
  • Animal Messenger (RP only)
  • Arcane Mark (RP only)
  • Arcane Sight (RP only)
  • Augury (RP only)
  • Calm Animals (RP only)
  • Commune with Nature (RP only)
  • Contact Other Plane (RP only)
  • Control Weather (RP only)
  • Create Food and Water (RP only)
  • Create Water (RP only)
  • Dancing Lights (RP only)
  • Delay Poison (RP only)
  • Detect Animals or Plants (RP only)
  • Detect Poison (RP only)
  • Detect Scrying (RP only)
  • Detect Snares and Pits (RP only)
  • Detect Thoughts (RP only)
  • Dimensional Anchor (RP only)
  • Discern Location (RP only)
  • Disguise Self (RP only)
  • Divination (RP only)
  • Feather Fall (RP only)
  • Force Cage (RP only)
  • Gate Seal (RP only)
  • Geas (RP only)
  • Ghost Sound (RP only)
  • Glibness (RP only)
  • Greater Scrying (RP only)
  • Greater Teleport (RP only)
  • Hide from Animals (RP only)
  • Jump (RP only)
  • Know Direction (RP only)
  • Lesser Geas (RP only)
  • Locate Creature (RP only)
  • Locate Object (RP only)
  • Longstrider (RP only)
  • Lullaby (RP only)
  • Mage Hand (RP only)
  • Magic Aura (RP only)
  • Mending (RP only)
  • Message (RP only)
  • Miracle (RP only)
  • Mislead (RP only)
  • Mount (RP only)
  • Nondetection (RP only)
  • Open/Close (RP only)
  • Pass without Trace (RP only)
  • Permanency (RP only)
  • Prestidigitation (RP only)
  • Purify Food and Drink (RP only)
  • Reincarnate (RP only)
  • Scrying (RP only)
  • Sending (RP only)
  • Speak with Animals (RP only)
  • Speak with Dead (RP only)
  • Speak with Plants (RP only)
  • Stone Tell (RP only)
  • Summon Instrument (RP only)
  • Telepathic Bond (RP only)
  • Teleport (RP only)
  • Tongues (RP only)
  • Tree Shape (RP only)
  • Tree Stride (RP only)
  • Undetectable Alignment (RP only)
  • Wall of Force (RP only)
  • Wind Wall (RP only)
  • Wish (RP only)
  • Word of Recall (RP only)
  • Zone of Truth (RP only)

New Controls and Settings

  • The ACR now includes an ACR_HEALTHMONITOR_GAMEOBJECTUPDATE_BACKOFF variable, which can be used to slow game object updates to slower than 600ms, should a server need to improve performance beyond the limits normally provided by the health monitor.

New Building Tools and Options

  • Spike Growth may now be tooled as a spell cast property
  • Shield may now be tooled as a spell cast property
  • There is an available include, acr_notifications_i, which allows builders to send a short message to a GUI off to the right of the screen, combined with a standard icon that reflects our typical depictions of warning / error / FYI / pointer. When clicked, these provide a more-verbose message box of variety that may be selected by the builder.
    • The recommended use for this is in things which are important enough to prompt player acknowledgement, but should not steal focus to do so. For example, spotting tracks as part of a static quest would be an appropriate use of this, as the server window might be too cluttered to notice the message, and if a fight is afoot, a modal form would be hazardous to the players receiving it.
  • There is now an ACR_AddObjectToSpawnPoint function available to explicity add something which was not created by the spawn system to a spawn point, so that it behaves as though it were spawned by the point (including despawning).
  • Vampire is now available as a subrace, to be used to assist in targeting vampire-specific abilities and effects.

New Features

  • DMs may now throw their voices through the typical chat interface. To do so:
    • First, select the creature who you wish to throw your voice to.
    • Enter # followed by a single-digit number 0-9 (for example, #1, #5). The NPC is then "anchored," and you will receive all the conversation it hears if you are out of range to hear it.
    • You may throw your voice to the NPC by using # followed by the number as a preface to send chat to the NPC (for example, #1 Hello world!)
    • PCs may not be anchored in this way.
  • Wizards may throw their voice to their familiars in the same way.
  • DM teams may specify other NPCs as valid to receive voice throwing from a player by specifying the local variable HENCHMAN_LEADER and giving it the value of the player's player ID (and this may be updated dynamically, if for example a player is helping characterize well-known NPCs during an event).
  • Players using a new GSID will be prompted to link their GSIDs to their forum accounts when logging in. The interface is simple, requiring just a click and a log in, and needs to be done only once per GSID.
  • Cross-server communication now allows messages to be sent to the IRC bot on behalf of a player in game.

New Models

  • Models for wings which are compatible with the various non-human-female character models are now available via the toolset.

  • Duodrones are now available as a creature appearance.

  • Hydras are now available as a creature appearance

New Loading Screen

  • Moradin now has a loading screen, which is visible to players of characters with either 10 intelligence or at least 1 rank in knowledge (religion).

Running scripts via IPC requests

Overview

Starting with ACR 1.87, servers support an IPC message type that allows a server to be directed to run a script in-game.  The run script request can come from another server, or from an external source that has database access, such as an external process or a website-driven activity.

Remotely executed script prototype

Scripts that are remotely executed follow a standard prototype:

void main(int SourceServerID, string Argument);

The SourceServerID argument specifies the server ID of the server that initiated the request. This may be zero if the request came from a source other than a server, such as website-based automation. The Argument argument supplies an optional, script-defined parameter provided by the party that created the run script request.

Note that no reliable acknowledgement semantics are provided; if acknowledgement is required, it should be implemented in the form of a reply run script IPC request initiated by the script that was executed (for which the SourceServerID may be used for routing purposes when generating a reply run script request).

Like other IPC requests, a run script request cannot be enqueued to a server that is offline (and will be discarded when the server starts up).

NWScript and C# APIs

From NWScript, a server can request that a script runs on another server with the ACR_RunScriptOnServer function, present in acr_server_ipc_i:

int ACR_RunScriptOnServer(int DestinationServerID, string ScriptName,
    string ScriptArgument);

The API requests that the destination server (whose ID is given by DestinationServerID) runs a script named "ScriptName" (without extension). The ScriptArgument value is passed to the script entrypoint according to the standard prototype.

From C#, the ALFA.ALFADatabase class provides an ACR_RunScriptOnServer API with the same prototype.  (If writing code in the ACR_ServerCommunicator module, the RunScriptOnServer method on the ACR_ServerCommunicator class can be used instead.)

In all cases, a caller must be prepared to deal with a request to run a script that is never processed (for example, the remote server could go offline).

Database record (server_ipc_events)

The server_ipc_events record for a run script request uses the following event code:

const int ACR_SERVER_IPC_EVENT_RUN_SCRIPT = 6;

The SourcePlayerID and DestinationPlayerID columns are not used for this request and must be set to zero. If the source of the request was a game server, its server ID must be listed as the SourceServerID, otherwise zero should be supplied. The destination server is listed as the DestinationServerID.

The EventText column is formatted as follows:

ScriptName:Argument

The :Argument portion may be omitted if the script takes no arguments. Note that the script name, colon delimiter, and argument must still fit within the 256 character limit of the EventText column.

Auxiliary database connections

Overview

Starting with ACR 1.87, there is support for setting up auxiliary database connections.  This support is intended for use if your module needs to connect to database servers other than the ALFA central database.

In most cases, you should use the standard ACR_SQL* APIs in acr_db_persist_i (or the ACR_Persist variable support) instead of auxiliary database connections.

Any number of database connections can be created by the API, but using a persistent connection setup at module startup time is strongly recommended (versus creating an destroying connections on the fly).  Connections do not need to be to the same server, and connections created to the ALFA central database are not synchronized with the acr_db_persist_i APIs (and should as a result be avoided).

 Usage

Auxiliary database connection functions are provided in acr_server_misc_i.nss.  The general workflow for an auxiliary connection is as so:

- First, a connection handle must be created via a call to ACR_CreateDatabaseConnection().  You must specify a MySQL connection string and, optionally, control flags (such as SCRIPT_DATABASE_CONNECTION_DEBUG to enable query logging to the server log).  This step is usually done at module startup, in a module init script. For an example of how to build a connection string, see CLRScript\ALFAMySQLDatabase.cs : ALFA.MySQLDatabaseInternal.SetupConnectionString. You should set the Max Pool Size to 1, and you will need to provide a way for script code to learn the connection settings for the database, such as via module variables set by the toolset, or hardcoded in script code (discouraged).

- Next, the connection handle (int) returned by ACR_CreateDatabaseConnection should be saved away, such as in a named local int on the module.

- When it is time to use the connection, retrieve the connection handle from where you have saved it (e.g. as a named local on the module object) and call an appropriate ACR_*DatabaseConnection API, such as ACR_QueryDatabaseConnection.  The API design mirrors that of the standard ACR_SQL* APIs, but with different API names.

API Reference (see acr_server_misc_i.nss in alfa2_acr.hak)

 

//! Create a database connection object.
//!  - ConnectionString: Supplies the database connection string.
//!  - Flags: Supplies connection flags.  Legal values are drawn from the
//              SCRIPT_DATABASE_CONNECTION_* family of constants.
//!  - Returns: A database connection handle, or 0 on failure.
//              The handle is used for subsequent database requests.  It
//              remains valid until explicitly destroyed via a call to the
//              ACR_DestroyDatabaseConnection function.
//
//              The handle can be saved as a module local variable, or in any
//              other convenient location where an int can be stored.
int ACR_CreateDatabaseConnection(string ConnectionString, int Flags = 0);

//! Delete a database connection created by ACR_CreateDatabaseConnection.
//!  - ConnectionHandle: Supplies the connection handle that was returned by a
//                       prior call to ACR_CreateDatabaseConnection.
//!  - Returns: TRUE on success.
int ACR_DestroyDatabaseConnection(int ConnectionHandle);

//! Execute a query.  The function is similar to ACR_SQLQuery.
//!  - ConnectionHandle: Supplies the connection handle that was returned by a
//                       prior call to ACR_CreateDatabaseConnection.
//!  - Query: Supplies the query string.
//!  - Returns: TRUE on success.
int ACR_QueryDatabaseConnection(int ConnectionHandle, string Query);

//! Fetch a rowset from the database.  The function is similar to ACR_SQLFetch.
//!  - ConnectionHandle: Supplies the connection handle that was returned by a
//                       prior call to ACR_CreateDatabaseConnection.
//!  - Returns: TRUE on success.
int ACR_FetchDatabaseConnection(int ConnectionHandle);

//! Get a column from a rowset in a database query.  The function is similar to
//  ACR_SQLGetData.
//!  - ConnectionHandle: Supplies the connection handle that was returned by a
//                       prior call to ACR_CreateDatabaseConnection.
//!  - ColumnIndex: Supplies the column index (zero for the first column).
//!  - Returns: The column value, or "" on failure.
string ACR_GetColumnDatabaseConnection(int ConnectionHandle, int ColumnIndex = 0);

//! Get the affected row count in a database query rowset.  The function is
//  similar to ACR_SQLGetAffectedRows.
//!  - ConnectionHandle: Supplies the connection handle that was returned by a
//                       prior call to ACR_CreateDatabaseConnection.
//!  - Returns: The count of affected rows.
int ACR_GetAffectedRowCountDatabaseConnection(int ConnectionHandle);

//! Escape a string for use in a database query.  The function is similar to
//  ACR_SQLEncodeSpecialChars.
//!  - ConnectionHandle: Supplies the connection handle that was returned by a
//                       prior call to ACR_CreateDatabaseConnection.
//!  - String: Supplies the string to escape.
//!  - Returns: The escaped string is returned.
string ACR_EscapeStringDatabaseConnection(int ConnectionHandle, string String);

 

 

ALFA Peer to Peer Server Network Protocol

Overview

Starting with ACR 1.87, ALFA servers have the ability to perform direct, peer-to-peer communication between eachother, bypassing the database.

Presently, this communication is only used for unreliable, datagram-oriented messages (which can be lost or reordered along the way), so it is only used for non-critical activities like advising a server that it should immediately retrieve an IPC message from the central database.  Datagram protocol messages are also unauthenticated, so drastic action shouldn't be taken on receiving them.

Network protocol

The protocol operates as multiplexed over the same data port as game data traffic, and thus requires no additional firewall configuration.

Each protocol message starts out with a standard header.  All fields are in little endian.  Code to operate on parsing and building network protocol messages lives in CLRScript\ALFANetworkMessages.cs, whereas code for sending and receiving actual messages with payloads lives in alfa2_acr.hak\ACR_ServerCommunicator\ServerNetworkManager.cs.

UInt32: Magic number.  This is used to distinguish ALFA protocol messages from standard game network traffic.  The magic number always has the value 0x414C4641 (the ASCII string "ALFA").

UInt8: Protocol type.  There only ALFA protocol type currently defined is PROTOCOL_DATAGRAM, with the value 0x00.  The datagram protocol provides unreliable message delivery (messages can be discarded or reordered along the way, so it can't be used for data that must arrive in one piece).  A future connection-oriented protocol that provided reliable semantics might have a different protocol id to allow the messages to be distinguished.

UInt16: Command.  This represents one of the protocol-specific command codes.

UInt32: Message length (includes the header described here).  This represents the length of the entire message.

Datagram protocol message commands

The datagram protocol defines several message command codes, which are listed below.

CMD_IPC_WAKE (0x0000)

This message is sent to a server in order to cause it to immediately query the database for IPC messages.  The purpose of the message is to work around the lack of a LISTEN / NOTIFY mechanism in MySQL for reliable IPC messages.  The actual IPC message(s) to process are stored in the server_ipc_messages table, whereas the IPC wake datagram simply causes the target server to check the table immediately.  This reduces the latency required for a server to respond to a message (servers normally periodically poll, so the IPC wake message eliminates the added latency from the polling interval if it was successfully delivered).

(Int32) Source server id.  The database id of the server that sent the message; the message should be discarded if the sending address doesn't match that server id in the servers table.

(Int32) Destination server id.  This should match the database id of the local server, otherwise the message should be discarded.

CMD_SHUTDOWN_NOTIFY (0x0001)

This message is sent from a server, to all online servers, when a server begins a clean shutdown (as started by the Restart Server tool).  The purpose of the message is to allow any future, connection-oriented protocol targetted at the server to be shut down.  Currently, no action is taken when the message is received.

(Int32) Source server id.  The database id of the server that sent the message; the message should be discarded if the sending address doesn't match that server id in the servers table.

CMD_NOTIFY_DATABASE_STATUS (0x0002)

This message is sent to inform one server of what the other server's view of the central database's health is.  In the future, it might be used to form a quorum that might try to diagnose whether a failure in connectivity to the central database is likely to be the result of a server-local failure, or a failure actually on the central database.

The #showstate debug command can be used to dump the database online status of each known server.  This can be used to try and manually diagnose whether a database connectivity failure is local or global.

Servers rebroadcast this message every 10 minutes.  In addition, if a server's connectivity state to the central database changes state, the message is immediately broadcast at that time.

(Int32) Source server id.  The database id of the server that sent the message; the message should be discarded if the sending address doesn't match that server id in the servers table.

(UInt8) Database online disposition.  This value is 1 if the sending server has a good connection to the database, else 0 if the sending server cannot connect to the database.

 

Creating a Content Patch

Overview

ACR 1.87 supports the creation and deployment of content patches, which are server-side hotfixes that are automatically deployed to live servers on startup.  The content patch system is intended to make it easier to deploy important bugfixes to an already released ACR version.

Content patches can be used to perform the following tasks:

  • Place a file in the Override directory for the server.  Note that module and hak resources supersede "Override" resources (but Override supersedes in-box .zip files and can be used to deploy a new script that could be called by a hak, etc.).  Override-targetted content patch files go in "override\ACR_ContentPatches" on each live server.
  • Place an updated hak in the Hak directory for the server (for example, alfa2_acr.hak).

Content patches cannot be used to make client-side content changes (those must go through the standard release process).  As of ACR 1.90, the content patch system can recompile all module scripts (if the RecompileModule database column is set for a content_patch_files row that required updating), if necessary.  This facility can be used to update includes in the ACR hak and recompile scripts in a module that reference the include.

Content patches do not update the downloader XML for a server.  Server admins must be careful to not restage haks that have been hotfixed by the content patch system (typically, alfa2_acr.hak).

Content Patch Components

A content patch contains several distinct components which must be assembled:

  • The content files to patch (e.g. alfa2_acr.hak, or a free-standing file to place in the Override directory).  Any number of files can theoretically be content patched, but you're encouraged to keep the set of file small.  The content files must be placed on the central server vault, in a special directory, for them to be downloadable by the content patch system.
  • A set of database entries in the content_patch_files table that describe what ACR hak version the patch applies to (e.g. 1.87), and what file is associated with the patch.  You need a database record for each file that is contained within the content patch.
  • An optional initialization script, called "acr_patch_initialize".  If present, this script is run during module startup, to provide opportunity for a content patch to hook script callbacks or set things up.  The script is never located in the ACR hak or the module, but should only be distributed as a content_patch_files record.

Creating a Content Patch

The following is a checklist of the steps necessary to build and deploy a content patch.  Once deployed, it will be automatically picked up by live servers on their next restart.  (If necessary, you can remotely restart a server using the Restart Server tool.)

  1. First, create the content files to patch.  For example, the fixed script or the patched ACR hak.  Typically this would be done by checking out the ACR branch for the released ACR version to be patched, making the necessary changes and checking them in to the repository, and then rebuilding the hak from that branch.
  2. Next, copy the patched content files to the central vault.  They should go under ACR_ContentPatches\Global\<ACR_Version> on the central vault (for example ACR_ContentPatches\Global\1.87 for an ACR 1.87 patch).
  3. Generate a md5 checksum of each of the patched content files.  The md5sum utility (included with msysgit - http://code.google.com/p/msysgit/ - or cygwin, can do this).  You'll need these checksums to insert into the database in the next step.
  4. Create a database record in content_patch_files for each file present in the content patch.
    1. Set the FileName column to the name of the file to patch (with extension, no spaces, for example "alfa2_acr.hak").
    2. Set the HakVersion column based on the ACR version that is matched when deciding whether the content patch is applicable (for example, "1.87").
    3. Set the Location column to either "override" or "hak", depending on where the content file should be stored on live servers.
    4. Set the Checksum column to the md5sum value (32 hex characters) for the file that is being patched.
    5. Set the RecompileModule column to true if the module needs to have all scripts recompiled, else false if a recompile is not required.  A recompile is generally only necessary if an include in the ACR HAK has been changed and the include is referenced by a script distributed with the module.  This option is only supported in ACR 1.90 or higher (otherwise the module is never recompiled).
  5. Connect a test server to the database and central server vault, and restart it.  Check the log to make sure that the content patch applied successfully; the server should restart a second time after applying the patches.  There will be server log entries containing "ModuleContentPatcher" updating you with the status of content patches as they're applied.

It is highly recommended that you test the content patch on a test server before copying the patch data to the live server.  You should still verify that the patch applied correctly to a live server, however, once the patch has been deployed to production.

Content Patches and the Standard Release Process

The content patch system ensures that patches are tagged with a specific ACR version that they apply to.  When a server upgrades to a new ACR version, using the standard release process, previous content patches will no longer be applicable and won't be applied anymore.

For content patch files located in the "hak" directory, no action is taken.  It's expected that if the administrator did an ACR upgrade, that they have manually upgraded the haks anyway.  (No new haks can be added with the content patch system, only hotfixes to existing haks.)

For content patch files located in the "override" directory, the content patch system automatically removes any patch files not applicable to the ACR version the server starts up with at startup time.  Thus it's not necessary to manually clean the content patch override directory out.

Content Patch Server Log Messages

Messages in the NWN2 server log file track the progress of the content patch system. When a content patch has been successfully applied, a log message of the form "ModuleContentPatcher.ProcessContentPatches: Successfully updated content patch file <filename>." will be written to the server log. Log messages related to the content patcher can be easily identified by searching for ModuleContentPatcher in the log file. To verify that a content patch was deployed successfully, examine the server log after a server restart. Be sure to check the log message timestamp; it is usually best to start searching from the end of the server log file.

If a content patch requests a module script recompile, then the console output of the script compiler is printed to the server log file.  An error message prefixed with the standard ModuleContentPatcher prefix is printed to the server log if any scripts failed to compile.

Syndicate content