True to the can’t/won’t (more won’t than can’t, but can’t’s a part) and true to the Lua support being more common among closed-source projects, but the game engine goal is indeed what I’m arguing for. It’s quite possibly one of the stronger survival oriented game sandboxes and it already has everything readily able to be adjusted, save for a robust scripting language. Fallout: New Vegas was also designed to be a game (and bugs withstanding actually is quite excellent without mods), but even then is still far more fun in sandbox gameplay, a function for which it was never intended, especially if the Tale of Two Wastelands content is merged in. Skyrim is not even a contest between the game and the sandbox. In both cases, modding efforts almost always retain the underlying game as the foundational glue, but the unique experiences and customisations that players can introduce then turn it into something better… much better in the latter case. (I couldn’t stomach vanilla Skyrim for more than 11 hours, and those were very generous “well maybe it gets better” hours. Modded Skyrim, I’ve been going strong for 1600 hours.)
Without any non-self-taught programming skill or experience I’m almost certainly underestimating the effort involved, but I do see it as having the foundation already there and the work to add onto it would justify the expense in the long term. I have no proof other than other successful examples of the same in the closed-source world and my allegation that scripters who are non-programmers/non-sprite-artists are an untapped talent pool, however.
I’m not suggesting the whole game be available to logic – just the scripted bits that manipulate the world and the player character, like item-uses, activating biomods/mutations, tile examination actions, map generation, spawning of creatures from rot (pretty much the ideal use of external gameplay logic), creature evolution, etc; the 90% of code execution time that occurs in 10% of the code not only should remain in the engine but simply must.
As long as there’s an ability to tweak the results of anything either by polling-and-overruling or by occasional corrective factors, much of the code is fine in-engine. In the end, tweaking is the desired panacea – direct manipulation of the results that the game produces if an end user doesn’t particularly agree with them, so that they’re not forced to go full redneck and head to the hills whenever they find a feature they don’t like. =) The hard-coding and magic numbers of actual in-game environments like Necropolis, for instance, is a big no-no in my books (even in spite of how awesome Necropolis is – I probably wouldn’t change anything).
I suppose I’m still arguing the point without satisfying the conditions of “what bindings”. I can at least list from personal experience what I’ve wanted in the Gamebryo-based games; the game engines already do a great job of data-based dialogue and missions, with conditional logic on what message should be displayed when choosing a particular dialogue option even without actual scripting to do so. Where they tend to fail is their ability to produce reasonable results for adding gameplay-related features or scanning for interactive objects around the player (something that Cataclysm’s scripting language is also a little sparse on), and especially for direct access to actor variables, object trees, and game physics. FNV’s really functional for direct interaction, like triggering a lever, but requires obscene workarounds like cell scanning to apply tweak-level manipulation of characters, since each actor has only a single “one-to-rule-them-all” script that inhibits inter-mod compatibility unless everything is merged together.
For example, my NPCs-use-ammo mod for New Vegas uses the scripted logic to scan for everybody around the player, get a list of all of the items in their inventory, find the matching base class that corresponds to that inventory item instance, and then set the flags on those base classes to compel NPCs to use ammunition for those weapons (incidentally exposing a couple engine bugs on features they didn’t fully test with NPCs that do use ammo, like revolver reloading). If I had direct access to the object classes as a tree, that effort would be simpler, but that’s not available. This mod could have been done as direct modification of the objects, but then would not be automatically compatible with other people’s mods, as the “rule of one” of modifying a single weapon record’s field means that the entire weapon record needs merging. (I hard-coding a list of most object types for faster execution, but that isn’t mod compatible either, so the script needs to hack everything all the time.)
Cataclysm is both good and bad at JSON-based modifications like this: “copy-from”, “relative”, and “proportional” work wonders, but anything more intensive than that also follows the rule of one.
As a prototype of bindings that I would probably personally use:
- Retrieve array of master object table for fields, NPCs, monsters, objects, vehicles instances
- Retrieve all fields, NPCs, monsters, objects, vehicles of type within radius of singular point
- Retrieve type of tile at point (already in!)
- Get player’s X coordinate and Y coordinate (already in!)
- Get player’s overmap X and Y coordinate
- Find overmap tile of type in radius of player, return coordinates if found or nil if not found
- Get overmap type player is currently in
- Get overmap type at tile
- Replace overmap tile with another overmap tile
- Regenerate terrain for overmap tile
- Respawn monsters for overmap tile
- Get instance of object of type within singular point (can be soft coded if above are available)
- Start internal or scripted task for an NPC or creature (“move to point”, “use furniture”, “travel to overmap”, “find overmap tile of type”, “find item of type”, “attack target to kill”, “flee”, etc.)
- Directly manipulate an NPC, creature, or object instance (teleport, move, collide, edit instance parameters (mostly already in!))
- Directly manipulate an NPC, creature, or object base class (root statistics)
- Accelerate vehicle
- Decelerate vehicle
- Trigger vehicle skid
- Flag vehicle as mobile or immobile
- Apply arbitrary morale modifier to player
- Apply specific morale modifier to player with desired duration
- Add effect to NPC or creature (already in!)
- Force NPC to fire once at coordinate and/or actor in that coordinate
- Trigger scripted autopilot of player character with a brief realtime delay between successive statements, returning control to player after completion
- Start a mission
- Set a new mission target
- Set a mission stage
- Finish a mission
- Restart a mission
- Create a trigger area that will produce events upon entry
- Auto-save
- Pop-up to provide message (already in!)
- Pop-up to select arbitrary item from menu, yielding number selected as event handler
- Attach runtime-created variable to an instance (e.g., create arbitrary variable named “fnord”)
- Set, manipulate, and pull the value of runtime-created variable on instance
- Save or discard runtime-created variable
- Event handlers:
** Periodic heartbeat (already in!)
** When player or character consumes a consumable (parameters: character, consumable, amount left (0 if gone))
** When player activates a furnishing (params: character, furnishing)
** When player or character strikes NPC with weapon or bullet (params: NPC, character, weapon used), return value determines actual damage that would be caused (giving ability to modify result)
** When player or character strikes NPC with explosion firearm (same parameters and return value effect)
** When monster strikes character or player with attack (params: character, monster[, attack used]; if multiple attacks added to game)
** When player or NPC picks up an item (character, item)
** When player enters line of sight of monster (player, monster; possible to recycle safemode code for this)
** When there are no hostile entities remaining around player for several turns (similar recyclability)
** When player is killed (params: killing creature/character, method of destruction)
** When monster is killed (params: monster, killing creature/character, method of destruction)
** When NPC is killed (params: NPC, killing creature/character, method of destruction)
** When object is destroyed/disassembled/burned/otherwise deleted (object, method of destruction)
** When a new character is loaded (params: player)
** When a saved game is loaded (params: player)
** When the game is saved (params: player)
** When an effect is applied to the player or a character (params: character)
** When the player starts a mission (params: player, mission)
** When player, character, or creature enters a trigger area (params: creature, trigger area)
** When player, character, or creature exits a trigger area (params: creature, trigger area)
** When player enters conversation mode with an NPC (params: player, NPC)
** When player exits conversation mode with an NPC (params: player, NPC)
** When character or creature detects player, character, or creature by sound (params: listener, target, volume of sound, sound heard)
** When creature detects player, character, or creature by smell (params: listener, target, intensity of scent)
** When character detects sound (params: listener, sound type, approximate origin tripoint)
There’s undoubtedly much, much more that doesn’t come to mind immediately, but that alone is a great start.
Much of that can be done by creating JSON objects that are executed by native code in sequence as if they are scripts, but scripts can cut out the middle man, and some can only be done by scripts (e.g., formula modifiers to damage caused) unless particularly complex design is added to obviate them (e.g., ability to modify a character/monster instance’s damage suffered by weapons with certain flags/keywords both at runtime and as innate vulnerability/resistance).
For the former paragraph, I’m arguing in favour of a fairly pervasive system, but I’m not sure that some 500-or-so gameplay functions would need direct checking against 10000-or-so engine-related classes and features and vice versa. I’m presuming you’re stating “interfaces” in the comp-sci sense, i.e., methods and fields, but isn’t the Lua system already set up just to generate the bindings from plain-text entries? How often do methods get deleted or have their parameters changed and how often do fields get deleted or renamed? If a non-trivial amount, how often is that due to game logic and not due to changes in core mechanics?
Your latter paragraph is a pretty damned good argument, and I would very much love to have the need for scripting obviated by declarative content. =) I’m just not sure how practical it is to keep every declarative feature “in house”, especially with the breadth and scope of some changes that people might want to make. The program code is already crowdsourced, but crowdsourcing both the program code and the scripted logic would give a greater number of people the ability to write their own features independently that are still compatible with (and/or pullable into) the whole.
It could indeed turn out to be the singular worst decision ever made for the project, as it may already seem right now, but I like having faith in community-based design. If nothing else, it’d relieve a lot of forum burden by empowering people to make their own ludicrously stupid gameplay changes themselves instead of incessantly asking for them and having them shot down. (Ahem… like myself, again. =P)