All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Added
- Added in-game pause menu when pressing
Esc
. PressingShift + Esc
will skip this menu and pause into scenario/conquest menu.
Changed
-
Unofficial modules (mods) now use Semantic Versioning to check which version of the game they target.
As such, theIndex.ini
propertySupportedGameVersion
must now be a valid semantic version number. The game version has also been updated to match this standard.The
SupportedGameVersion
version number must be of the formX.Y.z
, where:X
matches the major version of the game,
Y
is the minimum minor version of the game the mod requires,
z
is the patch number, which is currently not enforced.Mods published for any development builds must match that development version exactly.
Fixed
- Fixed music resuming from incorrect position when unpausing.
Removed
0.1.0 pre-release 5.0 - 2023/06/17
Added
-
New INI
HDFirearm
propertyLegacyCompatibilityRoundsAlwaysFireUnflipped
. This is used to make guns fire their projectiles unflipped, like they used to in old game versions, and should only be turned on forHDFirearms
in old mods that need it. -
New INI and Lua (R)
HDFirearm
propertyInheritsFirerVelocity
, which determines whether or not the particles in aRound
should inherit their firer's velocity. Defaults to true to preserve normal behavior. -
New INI
BuyableMode
settingBuyableMode = 3
for script only items.
This makes the item unable to be bought by any player at all as if it wereBuyable = 0
, but without removing the item from theCreateRandom
Lua functions that the AI and activities use.
That way players can still find these weapons used by activities and AI enemies, and modders can have big arsenals, without actually having big arsenals. -
New
DataModule
INI propertySupportedGameVersion
to define what version of the game a mod supports. This must be specified, and must match the current game version, in order for the mod to load successfully. -
New Lua event functions for
HDFirearm
-OnFire(self)
that triggers when the gun fires, andOnReload(self, hadMagazineBeforeReload)
that triggers when the gun is reloaded. -
New
MOSRotating
INI and Lua (R/W)MOSRotating
propertyGibAtEndOfLifetime
that, when set to true, will make theMOSRotating
gib if its age exceeds its lifetime, rather than deleting as it normally would. -
New
Actor
INI propertiesOrganic = 0/1
andMechanical = 0/1
and supporting Lua functionsActor:IsOrganic()
andActor:IsMechanical()
.
These have no direct gameplay effect (and default to false), but will be very useful for inter-mod compatibility, as they allow scripts to know if anActor
is organic or mechanical, and treat them accordingly. -
New INI and Lua (R/W)
ACDropShip
propertyHoverHeightModifier
. This allows for modification of the height at which anACDropShip
will hover when unloading cargo, or staying at a location. -
New
Scene
Lua propertyBackgroundLayers
(R/O) to access an iterator of theScene
'sSLBackground
layers. -
SLBackground
layers can now be animated using the same INI and Lua animation controls as everything else (FrameCount
,SpriteAnimMode
, etc). (Issue #66)
The collection of theScene
's background layers can be accessed viascene.BackgroundLayers
. -
Added
SLBackground
auto-scrolling INI and Lua controls. (Issue #66)
The INI definition looks like this:CanAutoScrollX = 0/1 // Whether this can auto-scroll on the X axis. Scrolling will take effect only when combined with WrapX = 1, otherwise ignored. CanAutoScrollY = 0/1 // Whether this can auto-scroll on the Y axis. Scrolling will take effect only when combined with WrapY = 1, otherwise ignored. AutoScrollStepInterval = intValue // The duration between auto-scrolling steps on both axis, in milliseconds. AutoScrollStep = Vector X = intValue // The number of pixels to progress the scrolling on the X axis each step. Float values are supported but may end up choppy and inconsistent due to internal rounding and lack of sub-pixel precision. Y = intValue // The number of pixels to progress the scrolling on the Y axis each step. Float values are supported but may end up choppy and inconsistent due to internal rounding and lack of sub-pixel precision.
You can read and write the following Lua properties:
slBackground.CanAutoScrollX = bool -- this may be true even if X axis scrolling is not in effect due to WrapX = 0. slBackground.CanAutoScrollY = bool -- this may be true even if Y axis scrolling is not in effect due to WrapY = 0. slBackground.AutoScrollInterval = intValue slBackground.AutoScrollStep = vector slBackground.AutoScrollStepX = intValue slBackground.AutoScrollStepY = intValue
slBackground:IsAutoScrolling()
- (R/O) returns whether auto-scrolling is actually in effect on either axis (meaning eitherWrapX
andCanAutoScrollX
orWrapY
andCanAutoScrollY
are true).The collection of the
Scene
's background layers can be accessed viascene.BackgroundLayers
. -
New
Settings.ini
propertySceneBackgroundAutoScaleMode = 0/1/2
. (Issue #243)
Auto-scaling modes are: 0 = Off, 1 = Fit Screen, 2 = Always 2x.
This will auto-scale allScene
background layers to cover the whole screen vertically in cases where the layer's sprite is too short and creates a gap at the bottom.
In cases where a layer is short by design, auto-scaling behavior can be disabled on a per-layer basis using theSLBackground
INI propertyIgnoreAutoScaling
, otherwise it may be excessively scaled up to 2x (maximum).
Note that anyScaleFactor
definitions in layers that aren't set to ignore auto-scaling will be overridden.Only relevant when playing on un-scaled vertical resolutions of 640p and above as most background layer sprites are currently around 580px tall, and comes with a minor performance impact.
Note that in fit screen mode each layer is scaled individually so some layers may be scaled more than others, or not scaled at all.
In always 2x mode all layers will be equally scaled to 2x. -
New
SLBackground
INI propertyIgnoreAutoScaling = 0/1
to ignore the global background layer auto-scaling setting and use theScaleFactor
defined in the preset, if any. -
New
SLBackground
INI propertyOriginPointOffset
to offset the layer from the top left corner of the screen. -
Added new
TerrainDebris
scattering functionality. (Issue #152)
New INI properties are:MinRotation/MaxRotation = angleDegrees // Rotates each debris piece to a random angle within the specified values. Values in degrees, negative values are counter-clockwise. FlipChance = floatValue // Chance for a debris piece to be flipped when either `CanHFlip` or `CanYFlip` are set true. 0-1, defaults to 0.5. CanHFlip/CanVFlip = 0/1 // Flips each debris piece on the X, Y or both axis.
-
Added support for
Material
background textures with INI propertyBGTextureFile
. -
New
MovableObject
INI and Lua (R/W) propertySimUpdatesBetweenScriptedUpdates
, that letsMovableObject
s run their Lua update function less frequently, for performance benefits. -
Added faction themes.
Faction themes apply to theBuyMenu
when the faction is set as the native module (i.e. playing as the faction) in both Conquest and Scenario battle.The theme properties are defined in the
DataModule
'sIndex.ini
(before anyIncludeFile
lines) like so:FactionBuyMenuTheme = BuyMenuTheme SkinFile = pathToSkinFile // GUI element visuals (NOT actual layout). BackgroundColorIndex = paletteIndex // Color of the parent box that holds all the elements. Palette colors only, no support for images. BannerFile = pathToBannerImage LogoFile = pathToLogoImage
All properties are optional, any combination works.
The skin and background color are also applied to theObjectPicker
(scene object placer) for visual consistency. -
New
Settings.ini
propertyDisableFactionBuyMenuThemes = 0/1
which will cause custom faction theme definitions in all modules to be ignored and the default theme to be used instead. -
New
Settings.ini
propertyDisableFactionBuyMenuThemeCursors = 0/1
which will cause custom faction theme cursor definitions in all modules to be ignored and the default cursors to be used instead. -
New
Settings.ini
andSceneMan
Lua (R/W) propertyScrapCompactingHeight
which determines the maximum height of a column of scrap terrain to collapse when the bottom pixel is knocked loose. 0 means no columns of terrain are ever collapsed, much like in old builds of CC. -
New
DataModule
INI and Lua (R/O) propertyIsMerchant
which determines whether a module is an independent merchant. Defaults to false (0). (Issue #401)
A module defined as a merchant will stop being playable (in Conquest, etc.) but will have its buyable content available for purchase/placement when playing as any other faction (like how base content is).
Only has a noticeable effect when the "Allow purchases from other factions" (Settings.ini
ShowForeignItems
) gameplay setting is disabled.Note that this property takes priority over the
IsFaction
property. A module that is set as bothIsFaction = 1
andIsMerchant = 1
will be treated asIsFaction = 0
. -
Made
Vector
propertiesAbsRadAngle
andAbsDegAngle
writable, so you can set aVector
's direction directly, instead of rotating it by an angle viaRadRotate
andDegRotate
. -
New
HDFirearm
Lua functionGetNextMagazineName()
, that gets the name of the nextMagazine
to be loaded into theHDFirearm
. -
New INI and Lua (R/W)
Actor
propertyPieMenu
. This allows you to set anActor
'sPieMenu
via INI and Lua. If no value is set for this, the defaultPieMenu
for the type ofActor
will be used, these can be found inBase.rte/GUIs/PieMenus/PieMenus.ini
. -
PieMenu
s have been completely redone, and are now fully defined in INI and customizable in Lua. Additionally,PieMenu
s can have sub-PieMenu
s to allow for better organization and more controls.You can define
PieMenu
s in INI using standard INI concepts likeCopyOf
andPresetName
, and modify their visuals as you please. They have the following INI properties:IconSeparatorMode // The visuals style of the PieMenu's separators. The options are "Line", "Circle" and "Square". Defaults to "Line". FullInnerRadius // The inner radius of the PieMenu when it's fully expanded, in pixels. Defaults to 58. BackgroundThickness // The thickness of the background ring of the PieMenu. Defaults to 16. BackgroundSeparatorSize // The size of the background separators (lines, circles, squares). Defaults to 2. DrawBackgroundTransparent // Whether or not the PieMenu's background should be drawn transparent. Defaults to true. BackgroundColor // The color used to draw the background ring of the PieMenu. Color values are palette indexes. BackgroundBorderColor // The color used to draw the border around the background ring of the PieMenu. Color values are palette indexes. SelectedItemBackgroundColor // The color used to highlight selected PieSlices in the PieMenu. Color values are palette indexes. AddPieSlice = PieSlice // Add a PieSlice to the PieMenu. Standard INI concepts like CopyOf, etc. apply.
Additionally,
PieMenu
s have the following Lua properties and functions:Owner
(R) - Gets the owningActor
for thePieMenu
, if there is one.
Controller
(R) - Gets theController
controlling thePieMenu
. If there's anActor
owner, it'll be thatActor
'sController
, otherwise it's probably a generalController
used for handling in-game menu inputs.
AffectedObject
(R) - Gets the affectedMovableObject
for thePieMenu
if there is one. Support isn't fully here for it yet, butPieMenu
s can theoretically be made to affect objects that aren'tActors
.
Pos
(R) - Gets the position of the center of thePieMenu
. Generally updated to move with itsOwner
orAffectedObject
.
RotAngle
(R/W) - Gets/sets the rotation of thePieMenu
. Note that changing this may cause oddities and issues, especially if thePieMenu
is currently visible.
FullInnerRadius
(R/W) - Gets/sets the inner radius of thePieMenu
, i.e. the radius distance before the inside of the ring.
PieSlices
- Gets all of thePieSlice
s in thePieMenu
for iterating over in a for loop.IsEnabled()
- Gets whether or not thePieMenu
is enabled or enabling.
IsEnabling()
- Gets whether or not thePieMenu
is currently enabling.
IsDisabling()
- Gets whether or not thePieMenu
is currently disabling.
IsEnablingOrDisabling()
- Gets whether or not thePieMenu
is currently enabling or disabling.
IsVisible()
- Gets whether or not thePieMenu
is currently visible (i.e. not disabled).
HasSubPieMenuOpen()
- Gets whether thePieMenu
has a sub-PieMenu
open, and is thus transferring commands to that sub-PieMenu
.
SetAnimationModeToNormal()
- Sets thePieMenu
back to normal animation mode, and disables it so it's ready for use.
DoDisableAnimation()
- Makes thePieMenu
do its disabling animation.
Wobble()
- Makes thePieMenu
do its wobbling animation.
FreezeAtRadius(radius)
- Makes thePieMenu
freeze open at the given radius.
GetPieCommand()
- Gets the command given to thePieMenu
, either by pressing aPieSlice
button, or by selecting aPieSlice
and closing thePieMenu
.
GetFirstPieSliceByPresetName(presetName)
- Searches through thePieSlice
s in thePieMenu
and returns the first one with the givenPresetName
.
GetFirstPieSliceByType(pieSliceType)
- Searches through thePieSlice
s in thePieMenu
and returns the first one with the givenPieSlice
Type
.AddPieSlice(pieSliceToAdd, pieSliceOriginalSource, optional_onlyCheckPieSlicesWithSameOriginalSource, optional_allowQuadrantOverflow)
- Adds the givenPieSlice
to thePieMenu
, returning whether or not thePieSlice
was added.
ThepieSliceOriginalSource
is the object that added thePieSlice
to thePieMenu
, and it's very important you set this properly (much of the time you'll want it to beself
if, say, you have a gun adding aPieSlice
), otherwise you can end up with ghostPieSlice
s.
allowQuadrantOverflow
is optional and defaults to false, it determines whether thePieSlice
can only be added in its specified direction (false), or if it can overflow if that direction is full ofPieSlice
s (true).AddPieSliceIfPresetNameIsUnique(pieSliceToAdd, pieSliceOriginalSource, optionalAllowQuadrantOverflow)
- LikeAddPieSlice
, this adds the givenPieSlice
to thePieMenu
and returns whether or not thePieSlice
was added, but only if thePieMenu
doesn't contain aPieSlice
with thisPieSlice
's preset name, optionally only checkingPieSlice
s with the same original source (by default it checks allPieSlice
s in thePieMenu
).
PieSlice
s with no preset name will always be added by this.RemovePieSlice(pieSliceToRemove)
- Removes the givenPieSlice
from thePieMenu
, and returns it to Lua so you can add it to anotherPieMenu
if you want.
RemovePieSlicesByPresetName(presetNameToRemoveBy)
- Removes anyPieSlice
s with the given preset name from thePieMenu
. Note that, unlikeRemovePieSlice
, thePieSlice
is not returned, since multiplePieSlices
can be removed this way. Instead, this returns true if anyPieSlice
s were removed.
RemovePieSlicesByType(pieSliceTypeToRemoveBy)
- Removes anyPieSlice
s with the givenPieSlice
Type
from thePieMenu
. Note that, unlikeRemovePieSlice
, thePieSlice
is not returned, since multiplePieSlices
can be removed this way. Instead, this returns true if anyPieSlice
s were removed.
RemovePieSlicesByOriginalSource(originalSource)
- Removes anyPieSlice
s with the original source from thePieMenu
. Note that, unlikeRemovePieSlice
, thePieSlice
is not returned, since multiplePieSlices
can be removed this way. Instead, this returns true if anyPieSlice
s were removed.**
ReplacePieSlice
(pieSliceToReplace, replacementPieSlice)** - Replaces the specified
PieSliceto replace, if it exists in the
PieMenu, with the replacement
PieSliceand returns the replaced
PieSlicefor use (e.g. for adding to a different
PieMenu). The replacement
PieSlicetakes the replaced
PieSlice`'s original source, direction, middle slice eligibility, angles and slot count, so it seamlessly replaces it. -
PieSlice
s have been modified to supportPieMenu
s being defined in INI. They have the following properties:Type
(INI, Lua R/W) - Gets or sets thePieSlice
's type, useful for invoking hardcoded game actions (e.g. pickup).
Direction
(INI, Lua R/W) - Gets or sets thePieSlice
's direction, i.e what direction thePieSlice
should be added in to aPieMenu
. Defaults toAny
, which means it will be added to the least populated direction. Note that if you set this via Lua, you will need to remove and readd thePieSlice
for it to take effect.
CanBeMiddleSlice
(INI, Lua R/W) - Gets or sets whether or not thisPieSlice
can be the middle slice (i.e. a cardinal one like reload) in its direction, when added to aPieMenu
. Defaults to true. Note that if you set this via Lua, you will need to remove and readd thePieSlice
for it to take effect.
Enabled
(INI, Lua R/W) - Gets or sets whether or not thisPieSlice
is enabled and usable.
ScriptPath
(INI, Lua R/W) - Gets or sets the filepath to the script that should be run when thisPieSlice
is activated. A script function name is also required for this to work.
ScriptFunctionName
(INI Lua R/W) - Gets or sets the name of the function that should be run when thisPieSlice
is activated. A script path is also required for this to work.
SubPieMenu
(INI Lua R/W) - Gets or sets the sub-PieMenu
that should be opened when thisPieSlice
is activated. Note thatPieSlice
s with sub-PieMenu
s will not perform any other actions, though they will run scripts.
Icon
(INI) - The icon for thisPieSlice
to show in itsPieMenu
.
OriginalSource
(Lua R) - The object that added thisPieSlice
to itsPieMenu
. -
Added
Directions
enum with the following values:(-1) None (0) Up (1) Down (2) Left (3) Right (4) Any
-
Added
GameActivity
INI propertyBuyMenuEnabled
to match the Lua property, and made the buy menuPieSlice
disappear ifBuyMenuEnabled
is false.
Note that, if you toggle this from off to on in Lua for a runningGameActivity
, you'll need to re-add the buy menuPieSlice
manually. -
Added
Controller
Lua functionIsGamepadControlled()
, that lets you tell if aController
is being controlled by any of the gamepad inputs, much like the pre-existingIsMouseControlled()
function. -
Added some useful global angle helper functions:
NormalizeAngleBetween0And2PI(angle) -- Takes an angle in radians, and returns that angle modified so it's not negative or larger than 2PI. NormalizeAngleBetweenNegativePIAndPI(angle) -- Takes an angle in radians, and returns that angle modified so angles larger than PI are instead represented as negative angles, and no angle is larger than PI or smaller than -PI. AngleWithinRange(float angleToCheck, float startAngle, float endAngle) -- Returns whether or not the angleToCheck is between the startAngle and endAngle, in a counter-clockwise direction (e.g. 0.5rad is between 0rad and 1rad, and 0.3rad is between 2.5rad and 1 rad). ClampAngle(float angleToClamp, float startAngle, float endAngle) -- Returns the angleToClamp, clamped between the startAngle and endAngle.
-
Added support for nested block comments in INI. (Issue #248)
The reader will track block comment open tags and crash if a file ends while a block is open, reporting the line it was opened on. -
Added thickness option to Line primitives. (Issue #403)
New bindings with argument for thickness are:
PrimitiveMan:DrawLinePrimitive(startPos, endPos, color, thickness)
PrimitiveMan:DrawLinePrimitive(player, startPos, endPos, color, thickness)
Original bindings with no thickness argument are untouched and can be called as they were. -
Added rotation option to Text primitives.
New bindings with argument for rotation are:
PrimitiveMan:DrawTextPrimitive(pos, text, bool useSmallFont, alignment, rotAngleInRadians)
PrimitiveMan:DrawTextPrimitive(player, pos, text, bool useSmallFont, alignment, rotAngleInRadians)
Original bindings with no rotation argument are untouched and can be called as they were. -
Added option to draw bitmap from file instead of from
MOSPrite
based object to Bitmap primitives.
New bindings with argument for file path are:
PrimitiveMan:DrawBitmapPrimitive(pos, filePath, rotAngleInRadians)
PrimitiveMan:DrawBitmapPrimitive(pos, filePath, rotAngleInRadians, hFlipped, vFlipped)
PrimitiveMan:DrawBitmapPrimitive(player, pos, filePath, rotAngleInRadians)
PrimitiveMan:DrawBitmapPrimitive(player, pos, filePath, rotAngleInRadians, hFlipped, vFlipped)
Note that theframe
argument does not exist in these bindings.
Original bindings with no filepath argument are untouched and can be called as they were. -
Added new primitive drawing functions to
PrimitiveMan
:-- Polygon PrimitiveMan:DrawPolygonPrimitive(Vector startPos, color, { Vector vertexRelPos, ... }) PrimitiveMan:DrawPolygonPrimitive(player, Vector startPos, { Vector vertexRelPos, ... }) PrimitiveMan:DrawPolygonFillPrimitive(Vector startPos, color, { Vector vertexRelPos, ... }) PrimitiveMan:DrawPolygonFillPrimitive(player, Vector startPos, { Vector vertexRelPos, ... })
The vertices table contains
Vector
s with the position of each vertex of the polygon RELATIVE to the starting position. The starting position will be automatically added to each vertex position, doing so manually will lead to unexpected results.
A minimum of 2 vertices (which would result in a line) are required to draw a polygon primitive. A console error will be printed and drawing will be skipped if less are provided.
There may be a limit for the number of vertices inPolygonFillPrimitive
because it has different handling but it was not reached during testing.The order of vertices is of high importance. Bad ordering will lead to unexpected results.
For example:{ Vector(10, 0), Vector(10, 10), Vector(0, 10), Vector(0, 0) }
will result in a square, while{ Vector(10, 0), Vector(0, 10), Vector(10, 10), Vector(0, 0) }
will result in an hourglass shape.
Note that all vertices of the shape must be specified, as the last vertex will be connected to the first vertex and not to the starting position (whether it is used as center or as a corner) to complete the shape.
Omitting the lastVector(0, 0)
in the above example would result in a right angle triangle.The
Vector
s in the vertices table are single use! They will be deleted after being drawn, so they cannot be re-used!Usage example:
local myVertices = { Vector(10, 0), Vector(10, 10), Vector(0, 10), Vector(0, 0) }; PrimitiveMan:DrawPolygonPrimitive(self.Pos, 13, myVertices); -- myVertices no longer contains valid Vectors for this call, they were deleted after being drawn by the previous call. PrimitiveMan:DrawPolygonFillPrimitive(self.Pos, 13, { Vector(10, 0), Vector(10, 10), Vector(0, 10), Vector(0, 0) });
-
Added blended drawing functions to
PrimitiveMan
:
There are 10 blending modes available to produce different color and transparency effects for both true primitives and bitmap based primitives.
Blended drawing effects are not the same as post-processing (glows), as they are all drawn in indexed color mode and will produce widely different results.Note that blended drawing is very expensive and chugs FPS like no tomorrow. It should not be abused!
There are 3 blended drawing function overloads:
-
PrimitiveMan:DrawPrimitives(blendMode, blendAmountR, blendAmountG, blendAmountB, blendAmountA, { primitiveObj, ... })
This is the fully fledged blended drawing function which allows individual control over each color channel blend amount.
Blend amounts are in percentages, where 0 means no blending and 100 means full blending (e.g.blendAmountA = 100
will result in a fully transparent primitive, as if it was not drawn at all).
The blend mode and amounts will be applied to all the primitives in the primitive table.
Note that blend amounts are internally rounded to multiples of 5 (e.g. 32 will round to 30, 33 will round to 35) to reduce memory usage and because smaller steps are hardly noticeable. -
PrimitiveMan:DrawPrimitives(blendMode, blendAmountRGBA, { primitiveObj, ... })
This overload allows selecting a blend mode and applies the blend amount to all color channels at once.
This overload is for convenience when using certain modes (e.g.Invert
andDissolve
). See blend mode specifics further below. -
PrimitiveMan:DrawPrimitives(transBlendAmount, { primitiveObj, ... })
This overload uses the transparency blending mode and applies the blend amount to all color channels at once.
Transparency blending is likely to be the most commonly used mode so this exists for convenience.
The blending modes are defined in the new
DrawBlendMode
enum as follows:(0) NoBlend (1) Burn (2) Color (3) Difference (4) Dissolve (5) Dodge (6) Invert (7) Luminance (8) Multiply (9) Saturation (10) Screen (11) Transparency (12) BlendModeCount
The blending modes are common and information on what the result of each is can be found with a quick search.
Some blend mode specifics:
Invert
andDissolve
modes only use alpha channel blend amount. RGB channels blend amounts are ignored in these modes.Transparency
mode ignores alpha channel blend amount. Only RGB channels blend amounts are used in this mode.- Some trial and error is expected to produce desired results in other modes.
The primitives table must be filled with
GraphicalPrimitive
objects. For this the constructors for all the supported primitives have been exposed:LinePrimitive(player, startPos, endPos, color) ArcPrimitive(player, centerPos, startAngle, endAngle, radius, thickness, color) SplinePrimitive(player, startPos, guideA, guideB, endPos, color) BoxPrimitive(player, topLeftPos, bottomRightPos, color) BoxFillPrimitive(player, topLeftPos, bottomRightPos, color) RoundedBoxPrimitive(player, topLeftPos, bottomRightPos, cornerRadius, color) RoundedBoxFillPrimitive(player, topLeftPos, bottomRightPos, cornerRadius, color) CirclePrimitive(player, centerPos, radius, color) CircleFillPrimitive(player, centerPos, radius, color) EllipsePrimitive(player, centerPos, horizRadius, vertRadius, color) EllipseFillPrimitive(player, centerPos, horizRadius, vertRadius, color) TrianglePrimitive(player, pointA, pointB, pointC, color) TriangleFillPrimitive(player, pointA, pointB, pointC, color) TextPrimitive(player, pos, text, useSmallFont, alignment, rotAngle) BitmapPrimitive(player, centerPos, moSprite, rotAngle, frame, hFlipped, vFlipped) BitmapPrimitive(player, centerPos, filePath, rotAngle, hFlipped, vFlipped)
Note that
PolygonPrimitive
,IconPrimitive
andLinePrimitive
with thickness do not support blended drawing.The
GraphicalPrimitive
s in the primitives table are single use! They will be deleted after being drawn, so they cannot be re-used!Usage example:
local myPrimitives = { CircleFillPrimitive(-1, self.Pos + Vector(-100, 0), 20, 13), BitmapPrimitive(-1, self.Pos + Vector(100, 0), "Base.rte/Craft/Rockets/MK2/RocketMK2000.png", 0, false, false) }; PrimitiveMan:DrawPrimitives(DrawBlendMode.Screen, 50, 0, 50, 0, myPrimitives); -- myPrimitives no longer contains valid primitives for this call, they were deleted after being drawn by the previous call. PrimitiveMan:DrawPrimitives(DrawBlendMode.Dissolve, 50, { CircleFillPrimitive(-1, self.Pos + Vector(-100, -100), 20, 13), BitmapPrimitive(-1, self.Pos + Vector(100, -100), "Base.rte/Craft/Rockets/MK2/RocketMK2000.png", 0, false, false) }); PrimitiveMan:DrawPrimitives(50, { CircleFillPrimitive(-1, self.Pos + Vector(-100, -200), 20, 13), BitmapPrimitive(-1, self.Pos + Vector(100, -200), "Base.rte/Craft/Rockets/MK2/RocketMK2000.png", 0, false, false) }); -- NoBlend will draw the primitives without any blending mode (solid mode). Any color channel blend amounts are ignored. PrimitiveMan:DrawPrimitives(DrawBlendMode.NoBlend, 0, 0, 0, 0, { CircleFillPrimitive(-1, self.Pos + Vector(-100, -300), 20, 13), BitmapPrimitive(-1, self.Pos + Vector(100, -300), "Base.rte/Craft/Rockets/MK2/RocketMK2000.png", 0, false, false) }); -- It is equivalent to calling the individual draw functions like so: -- PrimitiveMan:DrawCircleFillPrimitive(-1, self.Pos + Vector(-100, -200), 20, 13); -- PrimitiveMan:DrawBitmapPrimitive(-1, self.Pos + Vector(100, -200), "Base.rte/Craft/Rockets/MK2/RocketMK2000.png", 0, false, false);
-
-
New
Vector
Lua (R/O) propertySqrMagnitude
which returns the squared magnitude of theVector
.
Should be used for more efficient comparison withvector.SqrMagnitude > (floatValue * floatValue)
overvector.Magnitude > floatValue
. -
New
Vector
Lua convenience functions for more efficient magnitude comparison.-- These perform vector.SqrMagnitude > or < (floatValue * floatValue). vector:MagnitudeIsGreaterThan(floatValue) -- Note that you can use (not vector:MagnitudeIsGreaterThan(floatValue)) in place of (vector.SqrMagnitude <= (floatValue * floatValue)). vector:MagnitudeIsLessThan(floatValue) -- Note that you can use (not vector:MagnitudeIsLessThan(floatValue)) in place of (vector.SqrMagnitude >= (floatValue * floatValue)).
-
The game now supports saving and loading. The easiest way to do this is to quick-save with
F5
, and quick-load withF9
. Console clearing is now done withF10
.ActivityMan:SaveGame(fileName) -- Saves the currently playing Scene and Activity. The save result will be printed to the console. ActivityMan:LoadGame(fileName) -- Loads and resumes a previously saved Scene and Activity.
The
Activity
start function now looks likefunction activityName:StartActivity(isNewGame)
. The newisNewGame
parameter is true if a game is beingly newly started (or restarted), and false if it's being loaded.Scripts on
Activities
now have a new callback functionOnSave
(in addition toCreate
,Update
, etc), which is called whenever a scene is saved. This function must exist for theActivity
to be saveable!
To support saving and loading,Activity
now has several Lua convenience functions to for dealing with script variables:Activity:SaveNumber(stringKey, floatValue) -- Saves a float value which can later be retrieved using stringKey. Activity:LoadNumber(stringKey) -- Retrieves a previously saved float value with key stringKey. Activity:SaveString(stringKey, stringValue) -- Saves a string value which can later be retrieved using stringKey. Activity:LoadString(stringKey) -- Retrieves a previously saved string value with key stringKey.
A new
GlobalScript
has been added that will automatically save the game every three minutes. To turn it on, enable the AutosavingGlobalScript
in the main menu mod manager's Global Scripts section.
To load games saved by this script, open the console and enter the commandActivityMan:LoadGame("Autosave")
, or use theCtrl + F9
shortcut. -
New hardcoded
MovableObject
functionOnGameSave(self)
that gets run for eachMovableObject
with it when the game is saved. This can be used in tandem with custom values (forMOSRotatings
and child classes) to store data, which can be read duringCreate
when the game is loaded. -
New Lua
AEmitter
properties:
TotalParticlesPerMinute (R/O) - The rate at which all of theEmission
s of thisAEmitter
combined, emit their particles.
TotalBurstSize (R/O) - The number of particles that will be emitted by all theEmission
s of thisAEmitter
combined, in one shot when a burst is triggered.
EmitCount (R/O) - The number of emissions emitted since emission was last enabled.
EmitOffset (R/W) - The offset (Vector
) of the emission point from thisAEmitter
's sprite center. -
New
PresetMan
Lua functionReloadEntityPreset(presetName, className, optionalDefinedInModule)
that allows hot-reloadingEntity
INI presets (along with all other entity presets referenced in the reloaded entity preset).
If theoptionalDefinedInModule
argument is not specified, the game will look through everyDataModule
to find anEntity
preset that matches the name and type.
Once anEntity
preset has been reloaded via the function, the key combinationCtrl + F2
can be used to quickly reload it as many times as necessary.
Note that any changes made to theEntity
preset will not be reflected in existing copies of theEntity
, only in new ones created after the reload.
Also note that this will reload theEntity
's sprites (and of all other referenced entity presets), which will be reflected immediately in all existing copies of theEntity
. -
New INI and Lua (R/W)
Actor
propertyAIBaseDigStrength
, used to determine the strength of the terrain theActor
can attempt to move through without digging tools. Normally used for moving through things like terrain debris and corpses. Defaults to 35. -
New optional parameter
ignoreMaterial
for Lua functionSceneMan:CastMaxStrengthRay(start, end, skip, ignoreMaterial)
, which allows specifying a material that the ray will ignore. Defaults to the door material, for legacy compatibility purposes. -
New
Settings.ini
propertyPathFinderGridNodeSize
to define the size of the pathfinder's graph nodes, in pixels. -
New
Settings.ini
propertyAIUpdateInterval
to define how often actor AI will update, in simulation updates. Higher values may give better performance with large actor counts, at a cost of AI capability and awareness.
This can be accessed via the new Lua (R/W)SettingsMan
propertyAIUpdateInterval
. -
New Lua (R)
TimerMan
propertiesAIDeltaTimeMS
andAIDeltaTimeSecs
to get the time that has passed since the last AI update. -
Added
MOSRotating
INI propertyDetachAttachablesBeforeGibbingFromWounds
that makesAttachables
fall off before theMOSRotating
gibs from having too many wounds, for nice visuals. Defaults to true. -
New
MOSRotating
Lua propertyGibs
(R/O) to access an iterator of theMOSRotating
'sGib
s. -
Expose
Gib
to Lua.
You can read and write the following properties:gib.ParticlePreset = movableObject; gib.Offset = vector; gib.Count = intValue; gib.Spread = angleInRadians; gib.MinVelocity = floatValue; gib.MaxVelocity = floatValue; gib.LifeVariation = floatValue; gib.InheritsVel = bool; gib.IgnoresTeamHits = bool; gib.SpreadMode = SpreadMode;
The
SpreadMode
property accepts values from theSpreadMode
enum:(0) Gib.SpreadRandom (1) Gib.SpreadEven (2) Gib.SpreadSpiral
The collection of a
MOSRotating
'sGib
s can be accessed viamosRotating.Gibs
. -
New
Settings.ini
propertyServerUseDeltaCompression = 0/1
to enable delta compression in dedicated server mode which reduces bandwidth usage. Enabled by default. -
New
Settings.ini
propertySubPieMenuHoverOpenDelay
that determines how long, in milliseconds,aPieSlice
with a sub-PieMenu
must be hovered over for the sub-PieMenu
to automatically open. Default is 1000 milliseconds. -
Added
PieSlice
Lua functionReloadScripts()
. Works the same as theMovableObject
function, but forPieSlice
s. -
Added key combinations for resetting time scales to defaults while performance stats are visible.
Ctrl + 1
to reset the time scale.
Ctrl + 3
to reset theRealToSimCap
.
Ctrl + 5
to reset theDeltaTime
. -
Added
Alt + P
key combination for toggling advanced performance stats (graphs) visibility while performance stats are visible. -
Added new
UPS
(Updates per second) measurement to the performance stats which is probably the most reliable performance indicator.
The sim update target is ~60 UPS (defined byDeltaTime
).
When UPS dips due to load there will be noticeable FPS impact because more time is spent updating the sim and less time is left to draw frames before the next sim update.
When UPS dips to ~30 the FPS will be equal to UPS because there is only enough time to draw one frame before it is time for the next sim update.
When UPS is capped at the target, FPS will be greater than UPS because there is enough time to perform multiple draws before it is time for the next sim update.
Results will obviously vary depending on system performance. -
Added
LuaMan
Lua functionsGetDirectoryList(pathToGetDirectoryNamesIn)
andGetFileList(pathToGetFileNamesIn)
, that get the names of all directories or files at the specified file path. -
Added a new Lua scripted function for
Actor
s:OnControllerInputModeChange(self, previousControllerMode, previousControllingPlayer)
that triggers when anActor
'sController
's input state changes (between AI/Player/Network control etc). This provides a script hook that fires when a player starts/stops controlling anActor
. -
Added
ACrab
INI properties for setting individual footAtomGroup
s, as opposed to setting the same footAtomGroup
s for bothLegs
on the left or right side.
These areLeftFGFootGroup
,LeftBGFootGroup
,RightFGFootGroup
andRightBGFootGroup
. -
Buy Menu Quality-of-Life improvements:
Shift-clicking an item (or Shift + Fire in keyboard-only) in the cart will now empty the entire cart.
Items in the cart will be indented to signify what actor's inventory they belong to.
Middle-clicking (or pressing the Pickup key) on an item will duplicate it. This also duplicates an actor's inventory.
You can now reorganize the cart by click-dragging. For kbd-only you can do this by holding the sharp aim key and pressing up/down. -
Added to Lua enum
ControlState
the stateRELEASE_FACEBUTTON
. -
Added screen-shake. The screen-shake strength can be tweaked or disabled in the options menu.
NewMOSRotating
INI propertyGibScreenShakeAmount
, which determines how much this will shake the screen when gibbed. This defaults to automatically calculating a screen-shake amount based on the energy involved in the gib.
NewHDFirearm
INI propertyRecoilScreenShakeAmount
, which determines how much this weapon will shake the screen when fired. This defaults to automatically calculating a screen-shake amount based on the recoil energy.New
Settings.ini
screen-shake properties:
ScreenShakeStrength
- a global multiplier applied to screen shaking strength.
ScreenShakeDecay
- how quickly screen shake falls off.
MaxScreenShakeTime
- the amount of screen shake time, i.e. the maximum number of seconds screen shake will happen until ScreenShakeDecay reduces it to zero.
DefaultShakePerUnitOfGibEnergy
- how much the screen should shake per unit of energy from gibbing (i.e explosions), when the screen shake amount is auto-calculated.
DefaultShakePerUnitOfRecoilEnergy
- how much the screen should shake per unit of energy for recoil, when the screen shake amount is auto-calculated.
DefaultShakeFromRecoilMaximum
- the maximum amount of screen shake recoil can cause, when the screen shake amount is auto-calculated. This is ignored by per-firearm shake settings. -
Added new Lua manager
CameraMan
, to handle camera movement. New Lua functions on CameraMan:AddScreenShake(screenShakeAmount, screen); -- Can be used to shake a particular screen. AddScreenShake(screenShakeAmount, position); -- Applies screenshake at a position in the game world. All screens looking near this position will have their screen shaken.
Several
SceneMan
Lua functions have been moved into CameraMan. For the full list, see the Changed section below. -
Added
MovableMan
Lua functionsGetMOsInRadius(position, radius, ignoreTeam, getsHitByMOsOnly)
andGetMOsInBox(box, ignoreTeam, getsHitByMOsOnly)
that'll return all of the MOs either within a circular radius of a position, or in an axis-aligned-bounding-box. TheignoreTeam
parameter defaults toTeam.NOTEAM
. ThegetsHitByMOsOnly
defaults to false, which will get everyMovableObject
. -
SceneMan
sGetMOIDPixel(x, y, ignoreTeam)
Lua function has a new optionalignoreTeam
parameter. This defaults toTeam.NOTEAM
. -
Added alternative
Actor
Lua functionRemoveInventoryItem(moduleName, presetName)
, that lets you specify the module and preset name of the inventory item, instead of just the preset name. -
Added alternative
AHuman
Lua functionEquipNamedDevice(moduleName, presetName, doEquip)
, that lets you specify the module and preset name of theHeldDevice
to equip, instead of just the preset name. -
Added Lua access (R/W) to
Attachable
propertyDeleteWhenRemovedFromParent
, which determines whether the givenAttachable
should delete itself when it's removed from its current parent. -
Added Lua convenience function
RoundToNearestMultiple(num, multiple)
which returns a number rounded to the nearest specified multiple.
Note that this operates on integers, so fractional parts will be truncated towards zero by type conversion. -
Added
Actor
INI and Lua property (R/W)PlayerControllable
, that determines whether theActor
can be swapped to by human players. Note that Lua can probably break this, by forcing theController
s ofActor
s that aren'tPlayerControllable
to theCIM_PLAYER
input mode. -
Added alternative
MovableMan:GetClosestTeamActor(team, player, scenePoint, maxRadius, getDistance, onlyPlayerControllableActors, actorToExclude)
that acts like the existing version, but allows you to specify whether or not to only getActors
that arePlayerControllable
. -
New
Attachable
INI and Lua propertyIgnoresParticlesWhileAttached
, which determines whether theAttachable
should ignore collisions (and penetrations) with single-atom particles. Useful for preventingHeldDevice
s from being destroyed by bullets while equipped. -
Added
AHuman
INI and Lua (R/W) propertyDeviceArmSwayRate
, that defines how muchHeldDevices
will sway when walking. 0 is no sway, 1 directly couples sway with leg movement, >1 may be funny. Defaults to 0.75. -
Added
AHuman
INI and Lua (R/W) propertyReloadOffset
, that defines whereHands
should move to when reloading, if they're not holding a supportedHeldDevice
. -
Added
AHuman
Lua functionFirearmsAreReloading(onlyIfAllFirearmsAreReloading)
which returns whether or not thisAHuman
'sHeldDevices
are currently reloading. If the parameter is set to true and theAHuman
is holding multipleHeldDevices
, this will only return true if all of them are reloading. -
Added
AHuman
Lua functionReloadFirearms(onlyReloadEmptyFirearms)
. This behaves the same as the pre-existingReloadFirearms
function, but if the parameter is set to true, onlyHDFirearms
that are empty will be reloaded. -
Added
AHuman
Lua property (R/W)UpperBodyState
, that lets you get and set theAHuman
'sUpperBodyState
. If you don't know what this does, you probably don't need or want it. -
Added
AHuman
Lua property (R/W)MovementState
, that lets you get and set theAHuman
'sMovementState
. If you don't know what this does, you probably don't need or want it. -
Added
AHuman
Lua property (R/W)ProneState
, that lets you get and set theAHuman
'sProneState
. If you don't know what this does, you probably don't need or want it. -
Added
Actor
Lua property (R/W)LimbPushForcesAndCollisionsDisabled
. If this is true, any of theActor
'sArm
s andLeg
s won't do any movement or collide with terrain, and will just swing around with momentum. -
Added
HeldDevice
INI and Lua (R/W) propertyDualReloadable
, that determines whether or not a one-handedHeldDevice
can be dual-reloaded (i.e. old reload behaviour). Note that for dual-reload to happen, both equippedHDFirearms
must have this flag enabled. -
Added
HeldDevice
INI and Lua (R/W) propertyOneHandedReloadTimeMultiplier
, that determines how much faster or slower anHeldDevice
is when reloading one-handed (i.e. if it's one-handed and the otherArm
is missing, or is holding something). -
Added
HeldDevice
INI and Lua (R/W) propertySupportable
, that determines whether or not aHeldDevice
can be supported by a backgroundArm
. -
Added
Timer
Lua functionGetSimTimeLimitMS()
that gets the sim time limit of theTimer
in milliseconds. -
Added
Timer
Lua functionGetSimTimeLimitS()
that gets the sim time limit of theTimer
in seconds. -
Ground pressure calculations revamp. Ground pressure, by default, is now calculated using a pseudo-3d model which takes into account the depth of an object colliding with terrain. This means actors cause much less terrain deformation from walking, especially large actors walking on smooth ground.
New
AtomGroup
INI propertyAreaDistributionType
, with the following options:Linear // Legacy CC behaviour. This is best for long but flat objects, like guns. Circle // Calculates ground pressure assuming objects are cylindrical with a diameter equal to the object's width. This is best for roundish objects, like feet. Square // Similar to Circle, but instead assuming that the object is a cuboid with a depth equal to the object's width.
New
AtomGroup
INI properyAreaDistributionSurfaceAreaMultiplier
. This is a multiplier to the calculated surface area, i.e how "blunt" an object is. Large values lead to objects having lower ground pressure, and so dig into the terrain less.The default values are
AreaDistributionType = Circle
andAreaDistributionSurfaceAreaMultiplier = 0.5
, meaning that an object is assumed to be an oval with a depth of half it's width. -
New
SceneMan
Lua functionDislodgePixel(posX, posY)
that removes a pixel of terrain at the passed in coordinates and turns it into aMOPixel
. Returns the dislodged pixel as aMovableObject
, ornil
if no pixel terrain was found at the passed in position. -
New
HDFirearm
Lua propertyCanFire
which accurately indicates whether the firearm is ready to fire off another round. -
New
HDFirearm
Lua propertyMSPerRound
which returns the minimum amount of MS in between shots, relative toRateOfFire
. -
New
HDFirearm
INI and Lua (R/W) propertiesReloadAngle
andOneHandedReloadAngle
which determine the width of the reload animation angle in radians, the latter being used when the device is held with no supportingArm
available. 0 means the animation is disabled. -
New
HDFirearm
Lua (R) propertyCurrentReloadAngle
which gets the reload angle being currently used. I.e. theReloadAngle
when there's a supportingArm
available, and theOneHandedReloadAngle
when there isn't. -
New
HDFirearm
Lua propertyMSPerRound
which returns the minimum amount of MS in between shots, relative toRateOfFire
. -
New
Attachable
INI and Lua (R/W) propertyGibWhenRemovedFromParent
which gibs theAttachable
in question when it's removed from its parent.DeleteWhenRemovedFromParent
will always override this. -
New
Settings.ini
propertyAutomaticGoldDeposit
which determines whether gold gathered by actors is automatically added into the team's funds. False means that gold needs to be manually transported into orbit via craft, the old school way. Enabled by default.
A noteworthy change in comparison to previous logic is that gold is no longer converted into objects, andGoldCarried
is now automatically transferred into craft upon entering them. This effectively allows the same actor to resume prospecting without having to return to orbit with the craft.
Regardless of the setting, this behavior is always disabled for AI-only teams for the time being, until the actor AI is accommodated accordingly. -
New
Actor
Lua functionAddGold(goldOz)
which adds the passed-in amount of gold either to the team's funds, or theGoldCarried
of the actor in question, depending on whether automatic gold depositing is enabled. This effectively simulates the actor collecting gold. -
New
Actor
Lua functionDropAllGold()
which converts all of the actor'sGoldCarried
into particles and spews them on the ground. -
Added
Alt + F2
key combination to reload all cached sprites. This allows you to see changes made to sprites immediately in-game. -
New
MovableObject
Lua (R) propertyDistanceTravelled
which returns the amount of pixels the object has travelled since its creation. -
Added
Activity
Lua functionForceSetTeamAsActive(team)
, which forcefully sets a team as active. Necessary forActivity
s that don't want to define/show all used teams, but still wantActor
s of hidden teams to work properly. -
Added
GameActivity
INI propertyDefaultGoldMaxDifficulty
, which lets you specify the default gold when the difficulty slider is maxed out. -
Added
HDFirearm
Lua (R/W) propertyBaseReloadTime
that lets you get and set theHDFirearm
's base reload time (i.e. the reload time before it's adjusted for one-handed reloads where appropriate). -
Added
Actor
INI and Lua property (R/W)PlayerControllable
, that determines whether theActor
can be swapped to by human players. Note that Lua can probably break this, by forcing theController
s ofActor
s that aren'tPlayerControllable
to theCIM_PLAYER
input mode. -
Added alternative
MovableMan:GetClosestTeamActor(team, player, scenePoint, maxRadius, getDistance, onlyPlayerControllableActors, actorToExclude)
that acts like the existing version, but allows you to specify whether or not to only getActors
that arePlayerControllable
. -
Added new
Timer
constructorstimer = Timer(elapsedSimTimeMS)
andtimer = Timer(elapsedSimTimeMS, simTimeLimitMS)
that let you setupTimer
s more cleanly. -
Added
Timer
Lua (R) propertiesRealTimeLimitProgress
andSimTimeLimitProgress
, that get how much progress theTimer
has made towards itsRealTimeLimit
orSimTimeLimit
. 0 means no progress, 1.0 means the timer has reached or passed the time limit. -
New
Settings.ini
propertyEnableVSync
to enable vertical synchronization. Enabled by default. -
New
Settings.ini
propertyIgnoreMultiDisplays
to ignore all displays except the one the window is currently positioned at when changing resolution. -
Added Lua (R/W) properties for
ACrab
AimRangeUpperLimit
andAimRangeLowerLimit
. INI bindings already existed and are mentioned in an earlier changelog entry. -
Added
TerrainObject
INI propertyClearChildObjects
that lets you clear child objects when doing aCopyOf
of anotherTerrainObject
. -
Added
Actor
Lua (R) propertyMovePathEnd
that gets you the last point in theActor
's move path. -
Added
Actor
Lua (R) propertySceneWaypoints
that lets you iterate over theActor
's scene waypoints. -
Added
MovableObject
Lua (R) propertyHasEverBeenAddedToMovableMan
that tells you whether or not theMovableObject
has ever been added toMovableMan
. -
Added alternate version of
Scene
Lua functionCalculatePath(startPos, endPos, movePathToGround, digStrength, team)
that works as the previous one, but lets you specify the team to calculate the path for, allowing you to ignore doors on your team. -
Added
Controller
Lua functionIsKeyboardOnlyControlled
that tells you whether theController
is being controlled by keyboard only. Previously the only way to do this was to check that it's not mouse controlled and not gamepad controlled. -
Added
Controller
control statePIE_MENU_OPENED
that is true for the first Update in which thePieMenu
is opened. -
Added
Activity
Lua functionGetPlayerController
, which gets you theController
used for GUI stuff and when there's noActor
selected in anActivity
. Be aware, it's very likely possible to cause problems by doing dumb things with this. -
Added
LuaMan
Lua functionFileExists
, which lets you check whether a specified file exists. Like withFileOpen
, the file must be inside a folder ending in.rte
.
Changed
-
Codebase now uses the C++20 standard.
-
Dramatic performance enhancements, especially with high actor counts and large maps. FPS has been more-than-doubled.
-
Greatly reduce online multiplayer bandwidth usage.
-
Swapped MoonJIT to LuaJIT. Compiled from d0e88930ddde28ff662503f9f20facf34f7265aa.
-
Swapped to SDL2 for window management and input handling.
-
Settings.ini
and player loadouts (BuyMenu presets) are now stored in theUserdata
directory instead ofBase.rte
. -
Lua scripts are now run in a more efficient way. As part of this change,
PieSlice
scripts need to be reloaded likeMovableObject
scripts (i.e. usingpieSlice:ReloadScripts()
, in order for their changes to be reflected in-game.
PresetMan:ReloadAllScripts()
will reloadPieSlice
preset scripts, like it does forMovableObject
s. -
The landing zone cursor will now show the width of the selected delivery craft.
-
Completely replaced
ScriptFile
withScriptPath
. -
Changed the
Vector
functionClampMagnitude
so its parameter order makes sense, it's nowVector:ClampMagnitude(lowerMagnitudeLimit, upperMagnitudeLimit)
. -
Changed the
MovableMan
functionAddItem
so it now only acceptsHeldDevice
s and sub-classes (i.e.HDFirearm
,ThrownDevice
,TDExplosive
), because it always expected that anyway, and it's good to enforce it. -
Scene
background layer presets in INI are now defined asSLBackground
rather thanSceneLayer
. -
TerrainDebris
INI propertyOnlyOnSurface = 0/1
replaced withDebrisPlacementMode = 0-6
.
Placement modes are:0 (NoPlacementRestrictions) // Debris will be placed anywhere where there is target material (currently not strictly enforced when being offset by min/max depth, so can end up being placed mid-air/cavity unless set to OnlyBuried = 1). 1 (OnSurfaceOnly) // Debris will be placed only on the surface (scanning from top to bottom) where no background cavity material (material index 1) was encountered before the target material. 2 (OnCavitySurfaceOnly) // Debris will be placed only on the surface (scanning from top to bottom) where background cavity material (material index 1) was encountered before the target material. 3 (OnSurfaceAndCavitySurface) // Debris will be placed only on the surface (scanning from top to bottom) regardless whether background cavity material (material index 1) was encountered before the target material. 4 (OnOverhangOnly) // Debris will be placed only on overhangs (scanning from bottom to top) where no background cavity material (material index 1) was encountered before the target material. 5 (OnCavityOverhangOnly) // Debris will be placed only on overhangs (scanning from bottom to top) where background cavity material (material index 1) was encountered before the target material. 6 (OnOverhangAndCavityOverhang) // Debris will be placed only on overhangs (scanning from bottom to top) regardless whether background cavity material (material index 1) was encountered before the target material.
-
Material
INI propertyTextureFile
renamed toFGTextureFile
to accommodate new background texture property. -
TerrainObject
s no longer have a hard requirement forFG
andMat
layer sprites. Any layer may be omitted as long as at least one is defined. -
Scene
layer data will now be saved as compressed PNG to reduce file sizes of MetaGame saves and is threaded to prevent the game from freezing when layer data is being saved. -
Lua function
BuyMenuGUI:SetHeaderImage
renamed toSetBannerImage
. -
Lua functions run by
PieSlice
s will now have the following signature:pieSliceFunction(pieMenuOwner, pieMenu, pieSlice)
. The details for these are as follows:
pieMenuOwner
- TheActor
owner of thisPieMenu
, or theMovableObject
affected object of it if it has no owner.pieMenu
- ThePieMenu
that is being used, and is calling this function. Note that this may be a sub-PieMenu
.
pieSlice
- ThePieSlice
that has been activated to call this function. -
OnPieMenu(self)
event function has been changed toWhilePieMenuOpen(self, openedPieMenu)
and will run as long as thePieMenu
is open. -
Any
Attachable
on anActor
(not justHeldDevice
s) can now have aWhilePieMenuOpen(self, openedPieMenu)
function, and can addPieSlice
s and run functions when they're pressed. -
PieSliceIndex
enum has been renamed toSliceType
to better match the source. More relevantly for modders, its values have also been renamed, they are as follows:(0) NoType // The following are used for inventory management: (1) Pickup (2) Drop (3) NextItem (4) PreviousItem (5) Reload // The following are used for menu and GUI activation: (6) BuyMenu (7) FullInventory (8) Stats (9) Map (10) Ceasefire // The following is used for squad management: (11) FormSquad // The following are used for AI mode management: (12) AIModes (13) Sentry (14) Patrol (15) BrainHunt (16) GoldDig (17) GoTo (18) Return (19) Stay (20) Deliver (21) Scuttle // The following are used for game editors: (22) EditorDone (23) EditorLoad (24) EditorSave (25) EditorNew (26) EditorPick (27) EditorMove (28) EditorRemove (29) EditorInFront (30) EditorBehind (31) EditorZoomIn (32) EditorZoomOut (33) EditorTeam1 (34) EditorTeam2 (35) EditorTeam3 (36) EditorTeam4
-
Major improvements to pathfinding performance and AI decision making.
-
Having the pie menu open no longer blocks user input when using mouse+keyboard or a controller.
-
MOSRotating
based presets without anAtomGroup
definition will now crash with error message during loading. -
Over-indentation in INI will crash with error message if detected during loading instead of skipping entire blocks or in some cases the rest of the file.
There is never a case where there should be a positive difference of more than one tab between lines, but this means that lines likeIncludeFile
which would previously load fine even if over-indented will also crash, but you should never have those indented to begin with.Examples of structure that will cause a crash:
AddSomething = Something PresetName = Thing // Over-indented. Will crash. SomeProperty = Whatever AddSomething = Something PresetName = Thing SomeObjectProperty = Something CopyOf = Thing // Over-indented. Will crash.
-
Improve accuracy of the
MSPF
measurement in performance stats, which also improves the accuracy of theFPS
measurement.
TheMSPF
measurement now displays 3 values:
Frame
(previouslyMSPF
) - The total frame time (game loop iteration), in milliseconds.
Update
- The total time spent updating the sim during the frame (as the sim can be updated multiple times per frame), in milliseconds.
Draw
- The time spend drawing during the frame, in milliseconds. -
Advanced performance stats (graphs) will now scale to
RealToSimCap
. -
The keyboard shortcut for clearing the console is now
F10
, sinceF5
is used for quick-saving (F9
quick-loads). -
BitmapPrimitive
drawing functions now acceptMOSprite
instead ofEntity
for the object they get the bitmap to draw from.
This changes nothing regarding the bindings, but will now print an error to the console when attempting to draw a non-MOSprite
based object (e.g.MOPixel
), instead of silently skipping it. -
Unless set to dual-reload, one-handed
HDFirearms
will now reload one-at-a-time. To maintain this behaviour in Lua scripts, it is recommend to useAHuman:ReloadFirearms()
instead of reloadingHeldDevices
directly, as the latter will ignore restrictions. -
Made a lot of changes to
Arms
- they can now only holdHeldDevices
(and subclasses likeHDFirearms
andThrownDevices
), andAHumans
have a lot ofArm
animations, including sway when walking and holding something, smootherArm
movement and reload animations.
They now have the following INI properties:MaxLength - The max length of the Arm in pixels. MoveSpeed - How quickly the Arm moves between targets. 0 means no movement, 1 means instant movement. HandIdleOffset - The idle offset this Arm's hand will move to if it has no targets, and nothing else affecting its idle offset (e.g. it's not holding or supporting a HeldDevice). IdleOffset is also allowed for compatibility. HandSprite - The sprite file for this Arm's hand. Hand is also allowed for compatibility. GripStrength - The Arm's grip strength when holding HeldDevices. Further described below, in the entry where it was added. ThrowStrength - The Arm's throw strength when throwing ThrownDevices. Further described below, in the entry where it was added. HeldDevice - Allows you to set the HeldDevice attached to this Arm.
They now have the following Lua properties and functions:
MaxLength
(R) - Allows getting theArm
's maximum length.
MoveSpeed
(R/W) - Allows getting and setting theArm
's movement speed. 0 means no movement, 1 means instant movement.
HandIdleOffset
(R/W) - Allows getting and setting theArm
's default idle hand offset, i.e. where the hand will go when it has no targets and isn't holding or supporting anything.
HandPos
(R/W) - Gets and sets the current position of the hand. Note that this will override any animations and move the hand to the position instantly, so it's generally not recommended.
HasAnyHandTargets
(R) - Gets whether or not thisArm
has any hand targets, i.e. any positions theArm
is supposed to try to move its hand to.
NumberOfHandTargets
(R) - Gets the number of hand targets thisArm
has.
NextHandTargetDescription
(R/W) - Gets the description of the next target thisArm
's hand is moving to, or an empty string if there are no targets.
NextHandTargetPosition
(R/W) - Gets the position of the next target thisArm
's hand is moving to, orVector(0, 0)
if there are no targets.
HandHasReachedCurrentTarget
(R) - Gets whether or not thisArm
's hand has reached its current target. This may not be reliably accessible from Lua since it can often get reset before being read from Lua, if the target has no delay. Note that this will be true if there are no targets but that hand has reached its appropriate idle offset.
GripStrength
(R/W) - Gets and sets theArm
's grip strength when holdingHeldDevices
. Further described below, in the entry where it was added.
ThrowStrength
(R/W) - Gets and sets theArm
's throw strength when throwingThrownDevices
. Further described below, in the entry where it was added.
HeldDevice
(R/W) - Gets and sets theHeldDevice
held by thisArm
.
SupportedHeldDevice
(R) - Gets theHeldDevice
thisArm
is supporting. For obvious reasons, this will be empty if this is not the BGArm
or if it has aHeldDevice
of its own.
AddHandTarget(description, positionOnScene)
- Adds a target for thisArm
's hand to move to. The target goes to the back of the queue, allowing for multiple animations to be added in succession. The description is arbitrary, but useful for identification, and if the target being added has the same description as the target at the end of the queue, they will be merged to avoid duplication.
AddHandTarget(description, positionOnScene, delayAtTarget)
- Adds a target for thisArm
's hand to move to as above, but the hand will wait at the target for the specified amount of time.
RemoveNextHandTarget()
- Removes the next hand target from the queue, if there are any.
ClearHandTargets()
- Empties the queue of hand targets. Once the queue is empty, the hand will move towards its appropriate idle offset. -
The following
SceneMan
functions have been moved toCameraMan
:SetOffset(offsetVector, screenId); GetScreenOcclusion(screenId); SetScreenOcclusion(occlusionVector, screenId); GetScrollTarget(screenId); SetScrollTarget(targetPosition, screenId); TargetDistanceScalar(point); CheckOffset(screenId); SetScroll(center, screenId);
-
HDFirearm
Lua propertyReloadTime
is no longer writable. UseBaseReloadTime
instead. INI propertyReloadTime
has been renamed toBaseReloadTime
, thoughReloadTime
still works as well. -
GameActivity
default gold INI properties have been renamed, so they all haveDifficulty
at the end. The full set of properties is:
DefaultGoldCakeDifficulty
,DefaultGoldEasyDifficulty
,DefaultGoldMediumDifficulty
,DefaultGoldHardDifficulty
,DefaultGoldNutsDifficulty
,DefaultGoldMaxDifficulty
. -
UInputMan
Lua functionsKeyPressed
,KeyReleased
andKeyHeld
now takeSDL_Keycode
values instead of Allegro scancodes.
Keycodes take keyboard layout into account and should be the preferred way of detecting input.If detecting by scancode (physical key location independent of layout) is absolutely necessary, the following functions have been added:
ScancodePressed
,ScancodeReleased
,ScancodeHeld
Info on the keycode and scancode Lua tables and how to access them be found here: SDL Keycode and Scancode enum values in Lua.
-
Replace
PrintScreen
withF12
for dumping a single screenshot, asPrintScreen
was unreliable. -
AHuman
,ACrab
andACRockt
will now attempt to fallback to using eachLeg
'sFoot
attachable'sAtomGroup
as the appropriateFootGroup
.
This allows using auto-generatedAtomGroup
s instead of manually defining eachAtom
in aFootGroup
when creating actors with larger or irregularly shaped feet simply by removing theFootGroup
properties from the actor preset. -
Failing to create actor
FootGroup
s during loading will now crash with error message instead of straight to desktop. -
Gib
propertyInheritsVel
now works as afloat
scalar from 0 to 1, defining the portion of velocity inherited from the parent object. -
Jetpack burst fuel consumption is now scaled according to the total burst size instead of always being tenfold.
Bursts during downtime from burst spacing are now less punishing, scaling according to half of the burst size. -
New
Activity
Lua functionactivity:SetPlayerHadBrain(player, whetherOrNotPlayerHadBrain)
, which sets whether or not the given player had a brain. Probably mostly useful for dealing with loading a game with multiple players, where one player is dead and you have to sort out brain assignment. -
Changed
LuaMan:FileOpen
access modes so it only allows"r", "r+", "w", "w+", "a", "a+"
, i.e. specifying type (text, binary) is not supported. See this reference page for details on the access modes.
Fixed
-
Improved support for varied resolutions and aspect ratios. 1366x768 users rejoice.
-
Multi-display fullscreen now works regardless of window position or which screen in the arrangement is set as primary.
Still limited to horizontal arrangements that are top or bottom edge aligned (or anywhere in between for arrangements with different height displays). -
Controller hot-plug and disconnect is now properly detected at any point and will attempt to reconnect devices to the same gamepad slot.
-
Fixed material view not drawing correctly when viewed in split-screen. (Issue #54)
-
Fix
TerrainObject
s not wrapping when placed over the Y seam on Y-wrapped scenes. -
Fix black striping in online multiplayer when client screen width isn't divisible by transmitted box width.
-
Fixed issue where actors refused to pathfind around enemy doors. (Issue #396)
-
Fix advanced performance stats (graphs) peak values stuck at 0.
-
Fix
MOSRotating
GetWounds()
Lua function missing its implementation. -
Fixed
Entity.ModuleName
returning an empty string forEntities
defined inBase.rte
. They now return "Base.rte", as they should. -
Fixed
MOSRotating
s registering all penetrations in one frame even when exceeding gibbing conditions. They now omit all collisions after being flagged for deletion, allowing particles like grenade fragments to penetrate other objects. -
Fixed immobile
SoundContainers
not pausing and resuming when you pause/resume anActivity
.
Removed
-
Removed
SLTerrain
andSLBackground
INI propertyOffset
. Internal and shouldn't have been exposed. -
Removed
SLTerrain
INI alt propertyAddTerrainObject
. UsePlaceTerrainObject
for consistency with similar properties. -
Removed
TerrainObject
INI propertyDisplayAsTerrain
. Wasn't implemented and did nothing. -
Removed
SceneMan
Lua functionAddTerrainObject
.SceneMan:AddSceneObject
should be used instead. -
Removed
Activity
Lua functionEnteredOrbit
. This tells theActivity
to consider anACraft
as having entered orbit, and should never actually have been accessible to Lua. -
Removed
OnPieMenu
listeners forActivity
s andGlobalScript
s, and removed theProvidesPieMenuContext
concept and everything around it. These things should no longer be necessary since you can modifyPieMenu
s on the fly at any time, and they made this already complex set of code even more complicated. -
Removed
SceneMan
Lua functionsSetOffsetX(x, screenId)
andSetOffsetY(y, screenId)
. UseCameraMan:SetOffset(offsetVector, screenId)
instead. -
Removed
whichStick
parameter for the followingUInputMan
Lua functions:
JoyDirectionPressed
,JoyDirectionReleased
,JoyDirectionHeld
,AnalogAxisValue
No longer used or meaningful. -
Removed
UInputMan
Lua functionWhichKeyHeld
. -
Dedicated fullscreen has been removed (again) along with the following
Settings.ini
properties:ForceVirtualFullScreenGfxDriver
,ForceDedicatedFullScreenGfxDriver
0.1.0 pre-release 4.0 - 2022/02/28
Added
-
Executable can be compiled as 64bit.
-
New
Settings.ini
propertyMeasureModuleLoadTime = 0/1
to measure the duration of module loading (archived module extraction included). For benchmarking purposes. -
Color
object's RGB values can now be set with index number.Color/TrailColor = Color Index = 0-255 // Corresponds with index in palette.bmp
-
New
Settings.ini
propertyForceDedicatedFullScreenGfxDriver
to force the game to run in previously removed dedicated fullscreen mode, allowing using lower resolutions (and 1366x768) while still maintaining fullscreen. -
Added Lua (R/W) properties for all hardcoded
Attachables
. You can now set them on the fly to be created objects of the relevant type. Note that trying to set things inappropriately (e.g. setting anHDFirearm
as something'sLeg
) will probably crash the game; that's your problem to deal with.
You can read and write the following properties:
AHuman
-Head
,Jetpack
,FGArm
,BGArm
,FGLeg
,BGLeg
,FGFoot
,BGFoot
ACrab
-Turret
,Jetpack
,LeftFGLeg
,LeftBGLeg
,RightFGLeg
,RightBGLeg
ACDropShip
-RightEngine
,LeftEngine
,RightThruster
,LeftThruster
,RightHatch
,LeftHatch
ACRocket
-RightLeg
,LeftLeg
,MainEngine
,LeftEngine
,RightEngine
,LeftThruster
,RightThruster
ADoor
-Door
Turret
-MountedDevice
Leg
-Foot
HDFirearm
-Magazine
,Flash
AEmitter
-Flash
-
Added
Vector:ClampMagnitude(upperLimit, lowerLimit)
Lua function that lets you limit a Vector's upper and lower magnitude. -
Added
MOSRotating
GibBlastStrength
INI and Lua (R/W) property. This lets you define how much force createdGibs
and anyAttachables
will get launched with when theMOSRotating
gibs. -
New INI and Lua (R/W) properties for
Attachables
:
ParentBreakWound = AEmitter...
- allows you to optionally define differentBreakWounds
for theAttachable
and its parent. By default it matchesBreakWound
for ease of use.BreakWound
is also now R/W accessible to Lua.
InheritsHFlipped = -1/0/1
- allows you to define whether theAttachable
will inherit its parent's HFlipped value or not.
-1 means reversed inheritance (i.e. if the parent's HFlipped value is true, thisAttachable
's HFlipped value will be false), 0 means no inheritance, 1 means normal inheritance. Defaults to 1 to preserve normal behavior.
InheritedRotAngleRadOffset = angle
- andInheritedRotAngleDegOffset = angle
allow you specify an offset to keep anAttachable
's rotation at whenInheritsRotAngle
is set to true. For example,InheritedRotAngleDegOffset = 90
would make theAttachable
always face perpendicular to its parent. In Lua there's onlyInheritedRotAngleOffset
, which takes/returns radians to avoid confusion. Note that this property does nothing if theAttachable
'sInheritsRotAngle
is set to false or theAttachable
has no parent.
GibWithParentChance = 0 - 1
- allows you to specify whether thisAttachable
should be gibbed when its parent does and what the chance of that happening is. 0 means never, 1 means always.
ParentGibBlastStrengthMultiplier = number
- allows you to specify a multiplier for how strongly thisAttachable
will apply its parent's gib blast strength to itself when the parent gibs. Usually this would be a positive number, but it doesn't have to be. -
New INI and Lua (R/W)
Arm
propertyGripStrength
. This effectively replaces theJointStrength
of the heldHeldDevice
, allowingArms
to control how tightly equipment is held. -
New INI and Lua (R/W)
HeldDevice
propertyGripStrengthMultiplier
. This allowsHeldDevices
to multiply theGripStrength
of theirArms
to support them being more or less easy to hold. -
New Lua
MovableObject
functionGetWhichMOToNotHit
. This provides access to the MO that has been set to not be hit bySetWhichMOToNotHit
. -
Added
HeldDevice
handling to limit whichActor(s)
can pick it up. Note that pickup limitations are all done by PresetName, so you can not use this to precisely specify individualActors
.
The INI definition looks like this:PickupableBy = PickupableByEntries AddPresetNameEntry = First Actor PresetName Here AddPresetNameEntry = Second Actor PresetName Here // Alternatively, if you want this not to be pickupable PickupableBy = None
The Lua properties and functions are as follows:
heldDevice.HasPickupLimitations; --(R) Whether or not this HeldDevice has any limitations affecting whether it can be picked up. heldDevice.UnPickupable --(R/W) Whether this HeldDevice is/should be pickupable. heldDevice:IsPickupableBy(actor) -- Whether or not a given Actor can pick up this HeldDevice. heldDevice:AddPickupableByPresetName(presetName) -- Allows Actors with the given PresetName to pick up this HeldDevice. heldDevice:RemovePickupableByPresetName(presetName) -- Disallows Actors with the given PresetNames from picking up this HeldDevice (as long as there are other pickup limitations).
-
Added
MOSRotating
Lua (R) propertyIndividualMass
. This provides access to theMOSRotating
's actual mass value, not including anyAttachables
or inventory items. Note that the normalMass
property is still used to set theMOSRotating
's mass. -
Added
Actor
Lua (R) propertyInventoryMass
. This provides access to the mass of theActor
's inventory separate from theActor
's actual mass. -
Added
LimbPath
INI propertyEndSegCount
, which allows you to specify a segment after which the owningActor
's foot will not collide with terrain. This lets you add extra visual-only frames to yourLimbPaths
. -
Added
AHuman
INI propertyCrouchLimbPathBG
to allow you to specify a differentLimbPath
for the background leg while crouching. -
Added
AHuman
INI propertiesStandRotAngleTarget
,WalkRotAngleTarget
,CrouchRotAngleTarget
andJumpRotAngleTarget
that let you define the rot angle the body should aim towards when in the correspondingMovementState
. -
Added
AHuman
Lua methodsGetRotAngleTarget(movementState)
andSetRotAngleTarget(movementState, newRotAngleTarget)
that allow you to get and set rot angle targets forMovementStates
. Note that only theMovementStates
mentioned above will actually work. -
LimbPaths
are now Lua accessible forACrabs
andAHumans
. You can useGetLimbPath(Layer, MovementState)
forAHumans
andGetLimbPath(Side, Layer, MovementState)
forACrabs
.
LimbPaths
have the following properties:
limbPath.StartOffset
(R/W) - the start offset for theLimbPath
. Also defines its position if it has no actual path.
limbPath.SegmentCount
(R) - the number of segments in theLimbPath
.
limbPath:GetSegment(segmentIndex)
- Gets the segment Vector for the given segment index. You can use this to modifyLimbPaths
. -
Added
OnStride
special Lua function forAHumans
that is called whenever they stride (i.e. when theirStrideSound
is played). Like playingStrideSound
, this does not happen when the AHuman is climbing. -
New
AHuman
andACrab
INI and Lua (R/W) propertyJetAngleRange
which defines the rate at which the angle of theJetpack
's thrust follows the aim angle of the actor (default being 0.25). -
New
AHuman
INI propertyLookToAimRatio
at which theHead
turns in the direction of aiming (default being 0.7). -
New
AHuman
INI propertiesFGArmFlailScalar
andBGArmFlailScalar
. Used to change the rate at which eachArm
follows the rotation angle of theActor
, regardless of aim angle. 0 means theArm
will always point in aiming direction. -
New
Actor
INI and Lua (R/W) propertyCanRevealUnseen
which can be used to disable the ability to reveal unseen areas. -
New
MOPixel
Lua (R/W) propertyTrailLength
which returns the trail length of theAtom
affiliated with thisMOPixel
. -
New
HDFirearm
INI propertyShellEjectAngle
which lets you define the angle at whichShell
particles are ejected relative to theHDFirearm
's rotation. -
New
Gib
INI propertyIgnoresTeamHits
. -
New
Atom
INI propertyTrailLengthVariation
. Used to randomizeTrailLength
on every frame. 0 means no randomization (default), 1 means anything between full length and zero. -
New
ACraft
INI and Lua (R/W) propertyHatchCloseSound
. This is now required separately toHatchOpenSound
. -
Exposed
MOSRotating
propertyOrientToVel
to Lua (R/W). -
Exposed
DataModule
propertiesAuthor
,Description
andVersion
to Lua (R). -
Exposed
Actor
propertiesHolsterOffset
andItemInReach
to Lua (R/W). -
Exposed
Arm
propertyMaxLength
to Lua (R). -
Exposed broad range of sounds to Lua (R/W) through their relevant SoundContainers. For each class, these include:
Actor
-BodyHitSound
,PainSound
,DeathSound
,DeviceSwitchSound
,AlarmSound
AHuman & ACrab
-StrideSound
HDFirearm
-FireSound
,FireEchoSound
,EmptySound
,ReloadStartSound
,ReloadEndSound
,ActiveSound
,DeactivationSound
,PreFireSound
AEmitter
-EmissionSound
,BurstSound
,EndSound
ACraft
-HatchOpenSound
,HatchCloseSound
,CrashSound
MOSRotating
-GibSound
ADoor
-DoorMoveStartSound
,DoorMoveSound
,DoorDirectionChangeSound
,DoorMoveEndSound
-
Added Lua function
RoundFloatToPrecision
. Utility function to round and format floating point numbers for display in strings.
RoundFloatToPrecision(floatValue, digitsPastDecimal, roundingMode) -- Rounding mode 0 for system default, 1 for floored remainder, 2 for ceiled remainder, 3 for ceiled remainder with the last decimal place rounded to the nearest 0 or 5 (i.e. if option 2 gave 10.1, this would give 10.5, if it gave 10.369 this would give 10.370, etc.)
-
The Lua console (and all text boxes) now support using
Ctrl
to move the cursor around and select or delete text. -
Added
mosRotating:RemoveAttachable(attachableOrUniqueID, addToMovableMan, addBreakWounds)
method that allows you to remove anAttachable
and specify whether it should be added toMovableMan
or not, and whether breakwounds should be added (if defined) to theAttachable
and parentMOSRotating
. This method returns the removedAttachable
, see theChanged
section for important details on that. -
Added
mosRotating:RemoveEmitter(attachableOrUniqueID, addToMovableMan, addBreakWounds)
method that is identical to theRemoveAttachable
function mentioned above. -
Added
attachable:RemoveFromParent()
andattachable:RemoveFromParent(addToMovableMan, addBreakWounds)
that allow you to removeAttachables
from their parents without having to useGetParent
first. Their return value is the same asRemoveAttachable
above. -
Added
Settings.ini
debug properties to allow modders to turn on some potentially useful information visualizations.
DrawAtomGroupVisualizations
- anyMOSRotating
will draw itsAtomGroup
to the standard view.
DrawHandAndFootGroupVisualizations
- anyActor
subclasses with will draw its hand and footAtomGroup
s to the standard view.
DrawLimbPathVisualizations
- anyAHumans
orACrabs
will draw some of theirLimbPaths
to the standard view.
DrawRayCastVisualizations
- any rays cast bySceneMan
will be drawn to the standard view.
DrawPixelCheckVisualizations
- any pixel checks made bySceneMan:GetTerrMatter
orSceneMan:GetMOIDPixel
will be drawn to the standard view. -
Added a fully featured inventory view for managing
AHuman
inventories (to be expanded to other things in future). -
New
Settings.ini
propertyCaseSensitiveFilePaths = 0/1
to enable/disable file path case sensitivity in INIs. Enabled by default.
It is STRONGLY ill-advised to disable this behavior as it makes case sensitivity mismatches immediately obvious and allows fixing them with ease to ensure a path related crash free cross-platform experience.
Only disable this if for some reason case sensitivity increases the loading times on your system (which it generally should not). Loading times can be benchmarked using theSettings.ini
propertyMeasureModuleLoadTime
. The result will be printed to the console. -
Added
MovableObject
Lua functionEnableOrDisableAllScripts
that allows you to enable or disable all scripts on aMovableObject
based on the passed in value. -
Added
AEmitter
andPEmitter
Lua (R/W) propertiesNegativeThrottleMultiplier
andPositiveThrottleMultiplier
that affect the emission rate relative to throttle. -
Added
Attachable
Lua function and INI propertyInheritsFrame
which letsAttachables
inherit their parent's frame. It is set to false by default. -
Added
MovableObject
Lua (R/W) and INI propertiesApplyWoundDamageOnCollision
andApplyWoundBurstDamageOnCollision
which allowMovableObject
s to apply theEntryWound
damage/burst damage that would occur when they penetrate another object, without actually creating a wound. -
Turret
s can now support an unlimited number of mountedHeldDevice
s. Properties have been added to Lua and INI to support this:
AddMountedDevice = ...
(INI) andturret:AddMountedDevice
(Lua) - this adds the specifiedHeldDevice
orHDFirearm
as a mounted device on theTurret
.
turret:GetMountedDevices
(Lua) - this gives you access to all the mountedHeldDevice
s on theTurret
. You can loop through them with a for loop, and remove or modify them as needed.
Note thatMountedDevice = ...
(INI) andturret.MountedDevice
(Lua R/W) deals with the first mountedHeldDevice
, which is treated as the primary one for things like sharp-aiming. -
Added
Turret
Lua (R/W) and INI propertyMountedDeviceRotationOffset
that lets you specify a standard rotation offset for all mountedHeldDevices
on a turret. -
Added option for players to vote to restart multiplayer activities by holding the backslash key,
\
. Requires all players to vote to pass.
This is an alternative to the existing ability to vote to end the activity and return to the multiplayer lobby, by holdingBackspace
key. -
New
Settings.ini
propertiesMuteMaster = 0/1
,MuteMusic = 0/1
andMuteSound = 0/1
to control muting of master/music/sound channels without changing the volume property values. -
New
Settings.ini
propertyTwoPlayerSplitscreenVertSplit = 0/1
to force two player splitscreen into a vertical split mode (horizontal by default). -
Controller hot-plugging is now supported (Windows only).
-
Console text can be set to use a monospace font through
Settings.ini
propertyConsoleUseMonospaceFont = 0/1
or through the in-game settings. -
New
ThrownDevice
INI propertyStrikerLever
, which is the same asShell
forRound
inHDFirearm
, but for grenades. Represents the lever/pin coming off when activated. -
New
Arm
INI and Lua (R/W) propertyThrowStrength
which now calculates how farThrownDevice
s are thrown, which also takes to account the weight of the device.ThrownDevice
s can still defineMaxThrowVel
andMinThrowVel
to override this. -
New
Settings.ini
propertyDisableLuaJIT = 0/1
to disable LuaJIT (MoonJIT) to (potentially) improve performance on machines that seem to struggle with it. -
New
Settings.ini
propertyShowEnemyHUD
which allows disabling of enemy actor HUD in its entirety. -
New
DataModule
INI and Lua (R) propertyIsFaction
which determines whether a module is a playable faction (in MetaGame, etc.). This replaces the need to put "Tech" in the module name. Defaults to false (0). -
New
MOSRotating
INI and Lua (R) propertyWoundCountAffectsImpulseLimitRatio
which can be used to make objects more prone to gibbing from impulse when they have also received wounds. -
New
Gib
INI propertySpreadMode
which sports two new spread logic variants which alter the way velocity is applied to theGibParticle
s when they spawn. This can be used to create richer explosion effects.
SpreadMode = 0
is the default, fully randomized spread according toMinVelocity
,MaxVelocity
andSpread
values. Think: a piece of grenade fragment, launching out in an arbitrary direction.
SpreadMode = 1
is the same as the default, but with evenly spaced out angles. Think: an air blast shockwave, dispersing evenly outward from the explosion.
SpreadMode = 2
has an entirely different behavior of its own, which utilizes the fermat spiral as means to evenly disperse the particles in a circular area, according toMaxVelocity
andMinVelocity
. Since this mode will always result in a full, 360-degree spread, theSpread
property can be used to add randomization to the gib particles. Think: a cloud of smoke. -
New
Actor
INI and Lua (R/W) propertyStableRecoverDelay
which determines how long it takes for an actor to regainSTABLE
status after being renderedUNSTABLE
. -
New
AHuman
Lua (R) propertyThrowProgress
which returns the current throw chargeup progress as a scalar from 0 to 1. -
New
HDFirearm
INI and Lua (R/W) propertyShellVelVariation
which can be used to randomize the magnitude at which shells are ejected. -
New
HDFirearm
Lua (R) propertyReloadProgress
which returns the current reload progress as a scalar from 0 to 1. -
New
HDFirearm
INI and Lua (R/W) propertyReloadable
which can be used to disable the ability to reload said device. -
New
HDFirearm
Lua (R) propertyRoundInMagCapacity
which returns the maximum capacity of theMagazine
or, if there's not currently aMagazine
, the maximum capacity of the nextMagazine
.
This means that the property will always return the maximum ammo capacity of the device, even when reloading. -
New
Entity
Lua (R) propertyModuleName
which returns the filename of the data module from which the entity originates from. -
Arm
s will now react to the recoil ofHeldDevice
s. This is affected by theArm
'sGripStrength
and theHeldDevice
'sRecoilTransmission
, in the same way as recoil itself. -
HDFirearm
reload progress now shows up as a HUD element. -
New
Round
INI propertyLifeVariation
which can be used to randomize theLifetime
of shot particles. -
Exposed
MOSprite
propertyPrevRotAngle
to Lua (R). -
New
ACraft
INI and Lua (R/W) propertyScuttleOnDeath
which can be used to disable the automatic self-destruct sequence when the craft's health drops down to zero. -
New
Settings.ini
propertyUnheldItemsHUDDisplayRange = numPixels
that hides the HUD of stranded items at a set distance. Default is 500 (25 meters). Value of -1 or anything below means all HUDs will be hidden and the only indication an item can be picked up will be on theActor
's HUD when standing on top of it. Value of 0 means there is no range limit and all items on Scene will display the pick-up HUD. Valid range values are 1-1000, anything above will be considered as no range limit. -
Various improvements to the Buy Menu. You can now navigate tabs with the actor swap buttons, and the menu will smartly navigate when you add an
Actor
to your shop list, so you can quickly select weapons, etc..
There is also a newSettings.ini
property,SmartBuyMenuNavigation = 0/1
, which allows you to turn off this smart buy menu navigation, in case you prefer not to have it. -
Exposed
ACraft
propertyHatchDelay
to Lua (R/W). -
New
Settings.ini
propertySimplifiedCollisionDetection = 0/1
to enable more performant but less accurate MO collision detection (previouslyPreciseCollisions = 0
). Disabled by default. -
New INI property
BuyableMode
to specify in which buy lists aBuyable = 1
item should appear in.
BuyableMode = 0 // No restrictions
- item will appear in both lists as usual. Default value, does not need to be explicitly specified.BuyableMode = 1 // BuyMenu only
- item will not appear in any group in the object picker during the editing phase, but will be available to purchase from the buy menu.
BuyableMode = 2 // ObjectPicker only
- item will not appear in any tab in the buy menu when making an order, but will be available for placement from the object picker during editing phase. -
New
MovableMan
Lua functionKillAllTeamActors
, which kills allActor
s on the givenTeam
. -
New
ACRocket
INI propertyMaxGimbalAngle
, which enables automatic stabilization via tilting of the main engine. -
Added Lua bindings for
scene.Areas
andarea.Boxes
that you can iterate through to get all theAreas
in aScene
and all theBoxes
in anArea
. -
Added
Area
Lua functionarea:RemoveBox(boxToRemove)
which removes the givenBox
from theArea
. Note that this removal is done by comparing theBox
'sCorner
,Width
andHeight
, so you're actually removing the firstBox
that matches the passed-in boxToRemove. -
Added
Area
Lua propertyarea.FirstBox
that returns the firstBox
in thisArea
. Useful forAreas
that only have oneBox
. -
Added
Area
Lua properties forarea.Center
andarea.RandomPoint
. They're exactly the same as the existingarea:GetCenterPoint()
andarea:GetRandomPoint()
functions, but a bit more convenient. -
Added
SceneMan
Lua functionSceneMan:WrapBox(boxToWrap)
which takes aBox
and, if it passes over the seam, splits it into multiple boxes and returns them. Useful for creatingBoxes
without having to worry about the seam. -
Added Lua binding for
AudioMan:StopMusic()
, which stops all playing music.AudioMan:StopAll()
used to do this, but now it actually stops all sounds and music. -
New
Actor
Lua (R) propertySharpAimProgress
, which returns the current sharp-aiming progress as a scalar from 0 to 1. -
New
HeldDevice
Lua (R/W) propertySupported
, which indicates whether or not the device is currently being supported by a background hand. -
New
HeldDevice
Lua functionIsEmpty
, which indicates whether the device is devoid of ammo. Can be used to skip an extra step to check for aMagazine
. Will always returnfalse
for non-HDFirearm
devices. -
New
SoundContainer
INI and Lua (R/W) propertyPitchVariation
, which can be used to randomize the pitch of the sounds being played. -
New
AHuman
andACrab
INI and Lua (R/W) propertyJetReplenishRate
, which determines how fast jump time (i.e. jetpack fuel) is replenished during downtime. -
Added
Entity
Lua functionentity:RemoveFromGroup(groupToRemoveFrom)
which removes the given group from theEntity
. The reverse ofAddToGroup
. -
New
AHuman
Lua functionsGetWalkAngle(layer)
andSetWalkAngle(layer, angle)
, which can be used to read and override walk path rotation of both Legs/Layers respectively. Note that the walk path rotation is automatically updated on each step to match the curvature of the terrain, so this value resets every update. -
New
AHuman
INI and Lua (R/W) propertyArmSwingRate
, which now controls the arms' walking animation, according to each arm'sIdleOffset
.1
is the default value,0
means that the arms stay still. -
New
Attachable
Lua (R) propertyJointPos
, which gets the position of the object's joint in scene coordinates. -
New
AHuman
Lua (R) propertyIsClimbing
, which indicates whether the actor is currently climbing using either of the arms. -
New
AHuman
Lua functionsUnequipFGArm()
andUnequipArms()
which unequip the currently held item(s) and put them into the actor's inventory. -
You can now execute multiple copies of your delivery order by holding UP or DOWN while choosing the landing zone.
-
New
MOSprite
INI propertyIconFile
, which can be used to define a separate sprite to be displayed in GUI elements, such as the Buy Menu.
Defined similarly toSpriteFile
, i.e.IconFile = ContentFile
followed up by aFilePath
to the sprite. -
New
MOSprite
Lua functionsGetIconWidth()
andGetIconHeight()
which return the dimensions of its GUI representation. -
New
PrimitiveMan
Lua functionsDrawIconPrimitive(player, pos, entity)
andDrawIconPrimitive(pos, entity)
which can be used to draw the GUI representation of the passed in entity. -
New
AEmitter
andPEmitter
Lua (R) propertyThrottleFactor
, which gets the throttle strength as a multiplier value that factors in either the positive or negative throttle multiplier according to throttle. -
New
AHuman
Lua (R) propertyEquippedMass
, which returns the total mass of anyHeldDevice
s currently equipped by the actor. -
New Settings.ini flag
UseExperimentalMultiplayerSpeedBoosts = 1/0
. When turned on, it will use some code that may speed up multiplayer. -
New
FrameMan
Lua functionSplitStringToFitWidth(stringToSplit, widthLimit, useSmallFont)
, which lets you split up a string so it fits within a given width limit for the specified font. Does not try to perfectly fit strings, and can be wonky if the width limit is small. Mostly used to ensure text fits on the screen!
Changed
-
ACrab
actors will now default to showing theirTurret
sprite as their GUI icon. If no turret is defined, theACrab
's own sprite will be used.
In a similar fashion,AHuman
will now default to its torso sprite as its GUI representation if noHead
has somehow been defined. -
ThrownDevice
s will now useStanceOffset
,SharpStanceOffset
andSupportOffset
in the same way as any otherHeldDevice
. In addition,EndThrowOffset
will be used to set the BG hand position while sharp aiming or throwing. -
AHuman
throwing angle will no longer be affected by the rotation of the body. -
Exposed
MovableObject
propertyRestThreshold
to Lua (R/W). -
ACRocket
s can now function without a full set of thrusters. This also means that "Null Emitter" thrusters are no longer required for rockets. -
Changed
MOSprite
propertySpriteAnimMode
Enum
LOOPWHENMOVING
toLOOPWHENACTIVE
as it also describes active devices. -
Changed
Activity
Lua (R) propertiesRunning
,Paused
andActivityOver
toIsRunning
,IsPaused
andIsOver
respectively. (NOTE: correspondingActivityMan
functions remain unchanged) -
Exposed
ThrownDevice
propertiesStartThrowOffset
andEndThrowOffset
to Lua (R/W). -
HeldDevice
s can now show up as "Tools" in the buy menu, rather than just as "Shields". -
Keyboard-only controlled
AHuman
s andACrab
s can now strafe while sharp-aiming. -
Lowered the default
AHuman
Head damage multiplier from 5 to 4. -
"Fixed" grenades and other fast-moving objects bouncing violently off of doors and other stationary objects.
-
AEmitter
andPEmitter
throttle logic has changed:
The propertiesMinThrottleRange
andMaxThrottleRange
have been changed toNegativeThrottleMultiplier
andPositiveThrottleMultiplier
respectively.
The new logic uses the multipliers to multiply the emission rate relative to the absolute throttle value.NegativeThrottleMultiplier
is used when throttle is negative, and vice versa. -
Doors in
Team = -1
will now open up for all actors. -
MovableMan
functionKillAllActors
(commonly found in activities) has been appropriately renamedKillAllEnemyActors
. -
Wound limit gibbing logic has changed for
MOSRotating
(and all its subclasses), where objects will now gib when they reach theirGibWoundLimit
rather than when they surpass it. This allows for one-wound gibbing, which was previously infeasible. For objects with lowGibWoundLimit
s, you may want to adjust limits to account for this change. -
TDExplosive
s will no longer default to a looping animation when activated. Instead, they change to the second frame (i.e 001), similarly toHDFirearm
. SetSpriteAnimMode
to4
if you wish to enable the looping active animation. -
AHuman
can now manually reload BG devices. -
Jetpack thrust angle is now properly clamped when controlled with an analog stick.
-
Aim reticle dots can now be hidden per device by setting
SharpLength
to 0. -
Craft will now automatically scuttle when opening doors at a 90° angle rather than 45°.
-
AHuman
s can now sharp-aim slightly while walking, however not while reloading. -
Recoil when firing weapons now affects sharp aim.
-
The distance arguments for
MovableMan
functionsGetClosestActor
andGetClosestTeamActor
are now of typeVector
rather thanfloat
. -
File paths in INIs are now case sensitive.
-
Hands will now draw in transparent drawing mode, i.e. editing menu.
-
AHuman
backgroundLeg
will no longer draw in front of theAHuman
. The real result of this is that the background foot will no longer draw in front of the foreground one. -
Everything draws better when flashing white, including craft which used to be terrible at it.
-
Reworked Attachable managment:
DamageMultiplier
onAttachables
now works as expected, allAttachables
can now transfer damage to their root parent.
This will travel up chains ofAttachables
, as long as everyAttachable
in the chain has a non-zero DamageMultiplier (yes, negative numbers are supported if you wanna have healing instead of damage or weirdness with chaining negative multipliers). Note that the defaultDamageMultiplier
forAttachables
is 0, so you have to set it if you want it. Also note that wounds will default this value to 1 instead of 0.
Attachable
terrain collision has been reworked so that it can be changed simply by settingCollidesWithTerrainWhileAttached = true/false
in INI or Lua. Also,Attachables
attached to otherAttachables
will now collide with terrain properly.
BreakWounds
onAttachables
now gets added to both theAttachable
and the parent when theAttachable
is broken off. IfParentBreakWound
is defined, the parent will use this instead of the regularBreakWound
. -
Attachable.BreakWound
now has R/W access in Lua. -
Attachable.DeleteWithParent
is nowAttachable.DeleteWhenRemovedFromParent
, since this more accurately describes what it does. -
Attachable.OnlyLinearForces
has been renamed toAttachable.ApplyTransferredForcesAtOffset
and its effect has been reversed, so something that checkedOnlyLinearForces == true
would now checkApplyTransferredForcesAtOffset == false
, since this makes more sense to use. -
Arms
andLegs
onAHumans
will no longer bleed out indefinitely. If you want this to happen, adjust theirBreakWound
orParentBreakWound
accordingly. -
Reworked wound management:
Wound management is now always done withMOSRotating
functions, instead of requiring different ones forActors
. This means TotalWoundCount and RemoveAnyRandomWounds no longer exist.
In place of these functions, you can get all wounds withGetWounds
, you can get the wound count withGetWoundCount
(or using the pre-existing WoundCount property), and remove wounds withRemoveWounds
. You can also get the total gib wound limit withGetGibWoundLimit
(or using the pre-existing GibWoundLimit property).
All of these functions have two variants, one lets you just specify any normal arguments (e.g. number of wounds to remove), the other lets you also specify whether you want to include any of the following, in order:Attachables
with a positiveDamageMultiplier
(i.e.Attachables
that damage their parent),Attachables
with a negativeDamageMultiplier
(i.e.Attachables
that heal their parent) orAttachables
with noDamageMultiplier
(i.e.Attachables
that don't affect their parent).
Without any arguments,GetWoundCount
andRemoveWounds
will only includeAttachables
with a positiveDamageMultiplier
in their counting calculations, andGetGibWoundLimit
will not include anyAttachables
in its counting calculations. The property variants (e.g.mosr.WoundCount
) behave the same way as the no-argument versions.
Note that this process is recursive, so if anAttachable
that satisfies the conditions hasAttachable
s that also satisfy the conditions, their wounds will be included in the results. -
Renamed
Turret
INI propertyMountedMO
toMountedDevice
to better match the new reality thatTurrets
can only mountHeldDevices
and their child classes. -
Renamed
ACrab
LFGLeg
,LBGLeg
,RFGLeg
andRBGLeg
Lua properties toLeftFGLeg
,LeftBGLeg
,RightFGLeg
,RightBGLeg
respectively, to be more consistent with other naming.
For the time being, the INI properties (as well as the ones for settingFootGroups
andLimbPaths
) support both single letter and written out versions (i.e.LStandLimbPath
andLeftStandLimbPath
are both supported). This single letter versions will probably be deprecated over time. -
To better align with the other changes, hardcoded
Attachable
INI definitions forACDropShips
andACRockets
can now support spelled out words. The following options are all supported in INI:
ACDropShip
-RThruster
/RightThruster
/RightEngine
,LThruster
/LeftThruster
/LeftEngine
,URThruster
/UpRightThruster
,ULThruster
/UpLeftThruster
,RHatchDoor
/RightHatchDoor
,LHatchDoor
/LeftHatchDoor
ACRocket
-RLeg
/RightLeg
,LLeg
/LeftLeg
,RFootGroup
/RightFootGroup
,LFootGroup
/LeftFootGroup
,MThruster
/MainThruster
,RThruster
/RightThruster
,LThruster
/LeftThruster
,URThruster
/UpRightThruster
,ULThruster
/UpLeftThruster
-
MovableMan:AddMO
will now addHeldDevices
(or any child class ofHeldDevice
) to itsItems
collection, making it able to provide the functionality ofAddParticle
,AddActor
andAddItem
. -
Changed and cleaned up how gibbing works and how it affects
Attachables
. In particular, limbs will better inherit velocity during gibbing and things are more customizable. SeeAttachable
properties for more details.
As an added bonus,Attachables
onACDropShips
andACRockets
can now be shot down when the craft gibs; fight back against the baleful dropship engines! -
Improved native recoil handling! Guns transfer recoil to arms/turrets, which transfer it to AHumans/ACrabs, all of it properly accounts for joint strengths (or grip strengths) and offsets at every step. Future work will be done on this to improve it. (Issue #7 and Issue #8).
-
Attachables
now use theirGibImpulseLimit
as well as theirJointStrength
when determining whether they should be detached by strong forces. To maintain backwards compatibility, if theGibImpulseLimit
is less than theJointStrength
, theJointStrength
will be used instead for this purpose. -
The
FacingAngle
function has been moved fromActor
toMOSprite
so it can be used more widely. -
Lifetime
andToDelete
now work on wounds, giving modders more control over them. -
Some functionality has been moved from
AudioMan
toSoundContainer
for consistency. As such, the followingAudioMan
Lua bindings have been replaced:
AudioMan:FadeOutSound(fadeOutTime);
has been replaced withsoundContainer:FadeOut(fadeOutTime);
AudioMan:StopSound(soundContainer);
andAudioMan:StopSound(soundContainer, player);
have been replaced withsoundContainer:Stop();
andsoundContainer:Stop(player);
-
Pressing escape when a buy menu is open now closes it instead of pausing the game.
-
GetParent
will now return anMOSRotating
instead of aMovableObject
so it doesn't need to be casted withToMOSRotating
. Additionally, it will always return null for objects with no parents, instead of returning the self object for things that weren'tAttachables
.
This makes things more consistent and reasonable throughout and will rarely, if ever, cause Lua problems. -
Previews generated by the
SceneEditor
are now the same asScenePreviewDumps
. Also, both are now saved as PNGs. -
Attachable
terrain collisions will now propagate to any childAttachables
on them. This means thatAttachables
will not collide with terrain, even if set to, if they're attached to a parent that doesn't collide with terrain.
This means that theattachable.CollidesWithTerrainWhileAttached
value may not represent the true state of things, you should instead useattachable.CanCollideWithTerrain
to determine whether a givenAttachable
can collide with terrain. -
Actor selection keys can be used to cycle the selected
ObjectPicker
item while it's closed during building phase and in editors. -
The
Actor
propertyMaxMass
now no longer includes theMass
of theActor
, and has been renamed toMaxInventoryMass
for clarity. In mods, this is most important forACraft
, which will now need their totalMass
subtracted from the old value. -
BuyMenu
tooltips now display item info as well as a description. This includesMaxInventoryMass
andMaxPassengers
forACraft
,Mass
andPassengerSlots
required forActors
, andMass
for otherMoveableObjects
. -
Replaced the above-HUD pie menu inventory view with an animating inventory carousel.
-
AHuman:ReloadFirearm
Lua function has been changed toAHuman:ReloadFirearms
and will now reload offhand weapons as well, if appropriate. -
ACrab:ReloadFirearm
Lua function has been changed toACrab:ReloadFirearms
and will now reload all of theACrab
's weapons. -
When using the Settings.ini flag
LaunchIntoActivity
, you will start with some default amount of gold; either theActivity
's medium difficulty gold amount, or its funds for Team 1, which default to 2000 when not set. -
AEmitter
s will now obeySpriteAnimMode
set in Lua while they're emitting. When they stop emitting this will reset toNOANIM
. -
Attachable
Lua methodIsDrawnAfterParent
has been changed to the propertyDrawnAfterParent
, and is now R/W. -
All
mosRotating:RemoveAttachable
,mosRotating:RemoveEmitter
andattachable:RemoveFromParent
functions will return the removedAttachable
if it hasn't been added toMovableMan
, or nil if it has. If theAttachable
is returned, it will belong to Lua like it would if it were newly Created. You could then, for example, add it to MovableMan, an inventory, or attach it to something else. -
Settings.ini
propertyMenuTransitionDuration
renamed toMenuTransitionDurationMultiplier
. -
Settings.ini
propertyDisableLoadingScreen
renamed toDisableLoadingScreenProgressReport
. -
Scenario scene markers are now color coded to help distinguish them visually:
Base.rte
scenes are yellow as always.
Missions.rte
scenes are now green.
Scenes.rte
or any other mod/user scenes are now cyan. -
Main menu and sub-menus were given a major facelift.
-
Settings menu was reworked to make it less useless.
-
Esc has been disabled in server mode to not disrupt simulation for clients, use Alt+F4 or the window close button to exit.
-
Placing "Tech" in a
DataModule
'sModuleName
no longer makes the module a playable faction (in MetaGame, etc.). TheIsFaction
property should be used instead.
The word "Tech" will also not be omitted from the module name when displayed in any faction selection dropdown list. -
Renamed Lua methods
GetRadRotated
andGetDegRotated
toGetRadRotatedCopy
andGetDegRotatedCopy
for clarity. -
Added support for multiple lines in DataModule descriptions in their Index.inis. See earlier entry on multiple lines in descriptions for details on how to use this.
-
FrameMan
screen text will now always try to fit on the screen, splitting into multiple lines if needed. If you want more control of this, split your screen text manually with the"\n"
new line character.
Fixed
-
Fixed the logic for
Gib
andEmission
propertyLifeVariation
where it would round down to zero, giving particles infinite lifetime. -
Fixed legs going bonkers for one frame when turning around.
-
HFlipped
is now properly assigned to emissions, gibs and particles that are shot from aHDFirearm
'sRound
when the source object is also flipped. -
MovableObject:SetWhichMOToNotHit
will now work properly for Attachables. They will also not hit the relevant MO. When they're removed, Attachables will check if they have the same MO for this value and, if so, unset it so they can hit that MO. -
Craft sucking up objects now works properly again.
-
Getting the
Mass
of aMOSRotating
has now been made more efficient. Additionally,Attachables
ofAttachables
will now be properly included in Mass, so some things have gotten a lot heavier (e.g. Dummy Dreadnought). -
The moment of inertia of
AtomGroups
now updates when the mass or Atoms change, meaning losingAttachables
or changing mass will properly affect how rotational forces apply to MOSRotatings. -
WoundDamageMultipliers
on projectiles will now properly stack with wounds'DamageMultiplier
. Prior to this, if you set theDamageMultiplier
of a wound on some object, it'd be overwritten by the hitting projectile'sWoundDamageMultiplier
. Now they multiply together properly. -
Radius
andDiameter
now account forAttachables
on objects that can have them. If you want just theRadius
orDiameter
of the object, useIndividualRadius
andIndividualDiameter
(only available forMOSRotating
and subclasses). This means thatRadius
andDiameter
will now give you a good estimation of an object's total size. -
Fixed various audio bugs that were in Pre3, and fixed clicking noise on sounds that played far away. The game should sound way better now!
-
Mobile sounds (i.e. generally things that aren't GUI related) will now pause and resume when you pause and resume your activity.
-
The
DeactivationSound
ofHDFirearms
now respects itsSoundOverlapMode
instead of never allowing overlap. If you don't want it overlapping, set it up accordingly. -
Enabled DPI Awareness to fix issues with resolution settings when Windows scaling is enabled.
-
Fixed a bug that caused the game to crash when the crab bomb effect was triggered while there were multiple crab bomb eligible Craft in an activity.
-
Renamed
Attachable
INI propertyCollidesWithTerrainWhenAttached
to more correct, consistentCollidesWithTerrainWhileAttached
. -
You can now modify all hardcoded
Attachable
CopyOf
INI definitions without setting a newPresetName
. This means you could, for example,CopyOf
a predefinedLeg
and change it, without having to set a newPresetName
. This is optional, and comes with the obvious limitation of not being able to find that modified copy in-game with Lua. -
OnCollideWithMO
now works forMOPixels
andMOSParticles
so you can use it to check if your bullets collide with things. -
OnCollideWithMO
andOnCollideWithTerrain
(and other special functions) will run more reliably right after the object is spawned. E.g.OnCollideWithTerrain
on a bullet should now work even if your gun is jammed into terrain when you shoot. -
You can now sharp-aim through friendlies when playing as any team, instead of just as red team.
-
The reload hotkey now works even if you're on top of a pickupable object.
-
Improved LZ behaviour on wrapping maps, so your buy cursor will no longer annoyingly wrap around the LZ area.
-
Fixed a bug with metagame saves that caused
Player
andTeam
numbers to be off by 1. -
Vote counts to end a multiplayer activity now display as intended.
-
Fixed a bug where choosing
-Random-
as a player's tech and pressing start game had a 1 in (number of techs + 1) chance to crash the game. -
Console error spam will no longer cripple performance over time.
-
AudioMan:StopAll()
now actually stops all sounds, instead of just stopping music. -
Fixed incorrect mouse bounds during splitscreen when the mouse player was not Player 1.
Removed
-
Removed obsolete graphics drivers and their
Settings.ini
propertiesForceOverlayedWindowGfxDriver
andForceNonOverlayedWindowGfxDriver
. -
Removed
Attachable
Lua write capability forAtomSubGroupID
as changing this can cause all kinds of problems. -
Removed
MaxLength
property fromLeg
, since it was a mostly unused leftover caused by Leg being originally copied from Arm, and was actually a fake setting that just set other properties. To replace it, set the following:ContractedOffset = Vector X = //Old MaxLength/2 Y = 0 ExtendedOffset = Vector X = //Old MaxLength Y = 0
-
Removed
Attachable.RotTarget
from Lua and INI. The property never worked and no longer exists. -
Removed
Attachable:CollectDamage
,Attachable:TransferJointForces
andAttachable:TransferJointImpulses
Lua function definitions. These are internal functions that should never have been exposed to Lua. -
Removed
MOSRotating:ApplyForces
andMOSRotating:ApplyImpulses
Lua functions. These are both internal functions that should never have been exposed to Lua. -
Removed hardcoded INI constraint that forced
Mass
ofMovableObjects
to not be 0. Previously, anytime aMass
of 0 was read in from INI, it was changed to 0.0001, now 0Mass
is allowed and supported. -
Removed the quit confirmation dialog from the scenarios screen. Now pressing escape will return you to the main menu.
-
Removed
Settings.ini
propertiesHSplitScreen
andVSplitScreen
. Superseded byTwoPlayerSplitscreenVertSplit
.
0.1.0 pre-release 3.0 - 2020/12/25
Added
-
Implemented Lua Just-In-Time compilation (MoonJIT 2.2.0).
-
Implemented PNG file loading and saving. PNGs still need to be indexed just like BMPs! Transparency (alpha) not supported (yet).
-
New
Settings.ini
propertyLoadingScreenReportPrecision = intValue
to control how accurately the module loading progress reports what line is currently being read.
Only relevant whenDisableLoadingScreen = 0
. Default value is 100, lower values increase loading times (especially if set to 1).
This should be used for debugging where you need to pinpoint the exact line that is crashing and the crash message isn't helping or doesn't exist at all. -
New
Settings.ini
propertyMenuTransitionDuration = floatValue
to control how fast transitions between different menu screens happen (e.g main menu to activity selection screen and back).
This property is a multiplier, the default value is 1 (being the default hardcoded values), lower values decrease transition durations. 0 makes transitions instant. -
New
ADoor
sound properties: (Issue #106)// Played when the door starts moving from fully open/closed position towards the opposite end. DoorMoveStartSound = SoundContainer AddSound = ContentFile FilePath = pathToFile // Played while the door is moving, between fully open/closed position. DoorMoveSound = SoundContainer AddSound = ContentFile FilePath = pathToFile LoopSetting = -1 // Doesn't have to loop indefinitely, but generally should. // Played when the door changes direction while moving between fully open/closed position. DoorDirectionChangeSound = SoundContainer AddSound = ContentFile FilePath = pathToFile // Played when the door stops moving and is at fully open/closed position. DoorMoveEndSound = SoundContainer AddSound = ContentFile FilePath = pathToFile
-
Exposed
Actor.StableVelocityThreshold
to lua. New bindings are: (Issue #101)
Actor:GetStableVelocityThreshold()
returns aVector
with the currently set stable velocity threshold.
Actor:SetStableVelocityThreshold(xFloatValue, yFloatValue)
sets the stable velocity threshold to the passed in float values.
Actor:SetStableVelocityThreshold(Vector)
sets the stable velocity threshold to the passed inVector
. -
New
Attachable
andAEmitter
propertyDeleteWithParent = 0/1
. If enabled the attachable/emitter will be deleted along with the parent if parent is deleted/gibbed/destroyed. (Issue #97) -
New
Settings.ini
propertyLaunchIntoActivity = 0/1
. WithPlayIntro
functionality changed to actually skip the intro and load into main menu, this flag exists to skip both the intro and main menu and load directly into the set default activity. -
Exposed
AHuman.ThrowPrepTime
to lua and ini: (Issue #101)
ThrowPrepTime = valueInMS
will set how long it takes theAHuman
to fully charge a throw. Default value is 1000.
AHuman.ThrowPrepTime
to get/set values via lua. -
Added new
SpriteAnimMode
modes:SpriteAnimMode = 7 // OVERLIFETIME
This mode handles exactly like (now removed)
MOSParticle.Framerate = 0
and will complete the sprite's animation cycle over the course of its existence.SpriteAnimDuration
is inapplicable when using this mode and will do nothing.
For example, an object that has a sprite with 10 frames and a lifetime of 10 seconds will animate at a rate of 1 frame per second, finishing its animation cycle just before being deleted from the scene.
If this mode is used on an object that hasLifeTime = 0
(infinite) it will be overridden toSpriteAnimMode = 1
(ALWAYSLOOP) otherwise it will never animate.SpriteAnimMode = 8 // ONCOLLIDE
This mode will drive the animation forward based on collisions this object has with other MOs or the terrain.
SpriteAnimDuration
is inapplicable when using this mode and will do nothing.
This mode isMOSParticle
specific and used mainly for animating casings and small gibs. Using this mode on anything other thanMOSParticle
will do nothing. -
New
Settings.ini
propertiesEnableCrabBombs = 0/1
andCrabBombThreshold = intValue
.
WhenEnableCrabBombs
is enabled, releasing a number of crabs equal toCrabBombThreshold
or more at once will trigger the crab bomb effect.
If disabled releasing whatever number of crabs will do nothing except release whatever number of crabs. -
Doors can now be stopped at their exact position using
ADoor:StopDoor()
via lua. When stopped, doors will stop updating their sensors and will not try to reset to a default state.
If the door was stopped in a script, it needs to opened/closed by calling eitherADoor:OpenDoor()
orADoor:CloseDoor()
otherwise it will remain in the exact position it was stopped forever.
If eitherDrawMaterialLayerWhenOpen
orDrawMaterialLayerWhenClosed
properties are set true, a material layer will be drawn when the door is stopped. This is to prevent a situation where the material layer will be drawn only if the door is travelling in one direction, without adding an extra property. -
New value
STOPPED
(4) was to theADoor.DoorState
enumeration.ADoor:GetDoorState
will return this if the door was stopped by the user viaADoor:StopDoor
. -
New shortcut
ALT + W
to generate a detailed 140x55px miniWorldDump
to be used for scene previews. No relying onSceneEditor
, stretches over whole image, no ugly cyan bunkers, no actors or glows, has sky gradient, indexed to palette. -
All text in TextBox (any TextBox) can now be selected using
CTRL + A
. -
Console can now be resized using
CTRL + UP/DOWN
(arrow keys) while open. -
Added new lua function
UInputMan:GetInputDevice(playerNum)
to get a number value representing the input device used by the specified player. Should be useful for making custom key bindings compatible with different input devices. -
Scripts can now be attached to
ACrab.Turret
andLeg
. Additionally, a binding to get the Foot of a Leg has been added. -
Added H/V flipping capabilities to Bitmap primitives. New bindings with arguments for flip are:
PrimitiveMan:DrawBitmapPrimitive(pos, entity, rotAngle, frame, bool hFlipped, bool vFlipped)
PrimitiveMan:DrawBitmapPrimitive(player, pos, entity, rotAngle, frame, bool hFlipped, bool vFlipped)
Original bindings with no flip arguments are untouched and can be called as they were. -
Added new primitive drawing functions to
PrimitiveMan
:-- Arc PrimitiveMan:DrawArcPrimitive(Vector pos, startAngle, endAngle, radius, color) PrimitiveMan:DrawArcPrimitive(player, Vector pos, startAngle, endAngle, radius, color) PrimitiveMan:DrawArcPrimitive(Vector pos, startAngle, endAngle, radius, color, thickness) PrimitiveMan:DrawArcPrimitive(player, Vector pos, startAngle, endAngle, radius, color, thickness) -- Spline (Bézier Curve) PrimitiveMan:DrawSplinePrimitive(Vector start, Vector guideA, Vector guideB, Vector end, color) PrimitiveMan:DrawSplinePrimitive(player, Vector start, Vector guideA, Vector guideB, Vector end, color) -- Box with rounded corners PrimitiveMan:DrawRoundedBoxPrimitive(Vector upperLeftCorner, Vector bottomRightCorner, cornerRadius, color) PrimitiveMan:DrawRoundedBoxPrimitive(player, Vector upperLeftCorner, Vector bottomRightCorner, cornerRadius, color) PrimitiveMan:DrawRoundedBoxFillPrimitive(Vector upperLeftCorner, Vector bottomRightCorner, cornerRadius, color) PrimitiveMan:DrawRoundedBoxFillPrimitive(player, Vector upperLeftCorner, Vector bottomRightCorner, cornerRadius, color) -- Triangle PrimitiveMan:DrawTrianglePrimitive(Vector pointA, Vector pointB, Vector pointC, color) PrimitiveMan:DrawTrianglePrimitive(player, Vector pointA, Vector pointB, Vector pointC, color) PrimitiveMan:DrawTriangleFillPrimitive(Vector pointA, Vector pointB, Vector pointC, color) PrimitiveMan:DrawTriangleFillPrimitive(player, Vector pointA, Vector pointB, Vector pointC, color) -- Ellipse PrimitiveMan:DrawEllipsePrimitive(Vector pos, horizRadius, vertRadius, color) PrimitiveMan:DrawEllipsePrimitive(player, Vector pos, horizRadius, vertRadius, color) PrimitiveMan:DrawEllipseFillPrimitive(Vector pos, short horizRadius, short vertRadius, color) PrimitiveMan:DrawEllipseFillPrimitive(player, Vector pos, horizRadius, vertRadius, color)
-
Added log for non-fatal loading errors. This log will show image files that have been loaded with incorrect extensions (has no side effects but should be addressed) and audio files that failed loading entirely and will not be audible.
If errors are present the console will be forced open to notify the player (only when loading into main menu).
Log will be automatically deleted if warnings are no longer present to avoid polluting the root directory. -
Game window resolution can now be changed without restarting the game.
-
GUI sliders (like for music volume) can now be adjusted with the mouse scroll wheel.
-
Exposed
PEmitter
to lua. Bindings are identical toAEmitter
bindings, except that damage-related bindings don't exist forPEmitter
. -
FLAC
audio files can now be loaded through lua and ini. -
Added new lua
Vector
functions:GetRadRotated(angle)
andGetDegRotated(angle)
. They return a rotated copy of the vector without modifying it. -
Added
Enum
binding forSoundSet.SoundSelectionCycleMode
:RANDOM = 0, FORWARDS = 1, ALL = 2
. -
Added
Enum
binding forSoundContainer.SoundOverlapMode
:OVERLAP = 0, RESTART = 1, IGNORE_PLAY = 2
. -
New
SoundContainer
functionRestart
, which allows you to restart a playingSoundContainer
. Also anotherPlay
function, that lets you just specify the player to play the sound for. -
New
HDFirearm
INI propertyPreFireSound
, which allows you to specify a sound that will play exactly once before the weapon fires.
Note that this was designed primarily for things like flamethrowers, semi-auto weapons may wonky with it, and full-auto weapons may fire multiple shots in the first burst, if you don't also set anActivationDelay
. -
SoundSets
have been made a bit more fully featured, they can now have subSoundSets
and their ownSoundSelectionCycleMode
and they now have a Lua binding so you can create them in Lua withlocal mySoundSet = SoundSet()
.
They have the following INI and Lua properties:SoundSelectionCycleMode
(INI and Lua R/W) - Determines how sounds in thisSoundSet
will be selected each time it is played (or whenSelectNextSounds
is called).
Note that subSoundSets
can have differentSoundSelectionCycleModes
.SoundSets
with subSoundSets
and sounds whoseSoundSelectionCycleMode
isFORWARDS
will first go through their sounds, then each subSoundSet
.soundSet.SubSoundSets
(Lua R) - An iterator over the subSoundSets
of thisSoundSet
, allowing you to manipulate them as you would anySoundSet
.
soundSet:HasAnySounds(includeSubSoundSets)
(Lua) - Whether or not thisSoundSet
has any sounds, optionally including its subSoundSets
.
soundSet:SelectNextSounds()
(Lua) - Selects the next sounds for thisSoundSet
. Note that playing aSoundContainer
will always also do this, so this is only really useful to allow you to skip sounds whenSoundSelectionCycleMode
is set toFORWARDS
.
soundSet:AddSound("Path/to/sound.flac")
(Lua) - Adds the sound at the given path with no offset, 0 minimum audible distance, and default attenuation start distance.
soundSet:AddSound("Path/to/sound.flac", offset, minimumAudibleDistance, attenuationStartDistance)
(Lua) - Adds the sound at the given path with the given parameters.
soundSet:AddSoundSet(soundSetToAdd)
(Lua) - Adds the givenSoundSet
as a subSoundSet
of thisSoundSet
.
soundSet:RemoveSound("Path/to/sound.flac")
(Lua) - Removes any sounds with the given filepath from theSoundSet
, returning whether or not any where removed. Does not remove sounds from sub-SoundSet
s.
soundSet:RemoveSound("Path/to/sound.flac", removeFromSubSoundSets)
(Lua) - Removes any sounds with the given filepath from theSoundSet
, returning whether or not any where removed. Optionally removes matching sounds from any sub-SoundSet
s and their sub-SoundSet
s and so on.Additionally,
AddSound
andAddSoundSet
INI properties work forSoundSets
. They are exactly the same as they are forSoundContainers
. -
You can get the top level
SoundSet
of aSoundContainer
withsoundContainer:GetTopLevelSoundSet
and manipulate it as described above. You can also set it to fully overwrite it withsoundContainer:SetTopLevelSoundSet
. This allows you full interaction with all levels ofSoundSets
in aSoundContainer
.
Changed
-
Codebase now uses the C++17 standard.
-
Updated game framework from Allegro 4.2.3.1 to Allegro 4.4.3.1.
-
Major cleanup and reformatting in the
Managers
folder. -
Lua error reporting has been improved so script errors will always show filename and line number.
-
Ini error reporting has been improved so asset loading crash messages (image and audio files) will also display the ini file and line they are being referenced from and a better explanation why the crash occured. (Issue #161)
-
Settings.ini
will now fully populate with all available settings (now also broken into sections) when being created (first time or after delete) rather than with just a limited set of defaults. -
Temporarily removed
PreciseCollisions
fromSettings.ini
due to bad things happening when disabled by user. -
Settings.ini
propertyPlayIntro
renamed toSkipIntro
and functionality changed to actually skip the intro and load user directly into main menu, rather than into the set default activity. -
Lua calls for
GetParent
andGetRootParent
can now be called by anyMovableObject
rather than being limited toAttachable
only. (Issue #102)
In some cases a cast to the appropriate type (ToWhateverType
, e.gToMOSRotating
) will be needed when attempting to manipulate the object returned, because it will be returned asMovableObject
if it is the root parent.
In cases where you need to iterate over a parent's attachable list the parent must be cast to the appropriate type that actually has an attachable list to iterate over.
For example:for attachable in ToMOSRotating(self:GetParent()).Attachables do ... end
Or
local parent = ToMOSRotating(self:GetParent()); for attachable in parent.Attachables do ... end
-
Physics constants handling removed from
FrameMan
and now hardcoded inConstants
. Lua bindings moved toRTETools
and are now called without theFrameMan
prefix like so:
GetPPM()
,GetMPP()
,GetPPL()
,GetLPP()
. -
Removed hardcoded 10 second
LifeTime
restriction forMOPixel
andMOSParticle
. -
MOSParticle
animation can now be set withSpriteAnimMode
andSpriteAnimDuration
. If the property isn't defined it will default toSpriteAnimMode = 7
(OVERLIFETIME). -
Reworked crab bombing behavior. When enabled through
Settings.ini
and triggered will gib all living actors on scene except brains and doors. Devices and non-actor MOs will remain untouched. -
ADoor
propertiesDrawWhenOpen
andDrawWhenClosed
renamed toDrawMaterialLayerWhenOpen
andDrawMaterialLayerWhenClosed
so they are more clear on what they actually do. -
Specially handled Lua function
OnScriptRemoveOrDisable
has been changed toOnScriptDisable
, and no longer has a parameter saying whether it was removed or disabled, since you can no longer remove scripts. -
When pasting multiple lines of code into the console all of them will be executed instead of the last line being pasted into the textbox and all before it executing.
-
Input enums moved from
UInputMan
toConstants
and are no longer accessed with theUInputManager
prefix. These enums are now accessed with their own names as the prefix.
For example:UInputManager.DEVICE_KEYB_ONLY
is nowInputDevice.DEVICE_KEYB_ONLY
,UInputManager.INPUT_L_UP
is nowInputElements.INPUT_L_UP
and so on. -
CraftsOrbitAtTheEdge
corrected toCraftOrbitAtTheEdge
. Applies to both ini property and lua binding. -
Game will now Abort with an error message when trying to load a copy of a non-existent
AtomGroup
,Attachable
orAEmitter
preset. -
ComboBoxes (dropdown lists) can now also be closed by clicking on their top part.
-
Activity:IsPlayerTeam
renamed toActivity:IsHumanTeam
. -
Screenshot functionality changed: (Issue #162)
ThePrintScreen
button will now take a single screenshot on key release and will not take more until the key is pressed and released again.
TheCtrl+S
key combination is unchanged and will take a single screenshot every frame while the keys are held.
TheCtrl+W
andAlt+W
key combinations will now take a single WorldDump/ScenePreview onW
key release (whileCtrl/Alt
are still held) and will not take more until the key is pressed and released again.Additionally, all screenshots (excluding abortscreen) will now be saved into a
_Screenshots
folder (_
so it's on top and not hiding between module folders) to avoid polluting the root directory. (Issue #163)
This folder will be created automatically after modules are loaded if it is missing. -
ScreenDumps
andWorldDumps
are now saved as compressed PNGs. -
Controller deadzone setting ignores more input. Previously setting it to the maximum was just enough to eliminate stick drift.
-
Arm.HandPos
will now get/set the hand position as relative to the arm's joint position, instead of relative to the arm's center of mass. -
Resolution settings in options screen changed:
Resolution multiplier button changed toFullscreen
button - this will set the game window resolution to match the desktop resolution. When resolution matches the desktop, this button will change toWindowed
and will allow setting the game window resolution back to default (960x540).
AddedUpscaled Fullscreen
button - this will change the resolution to half of the desktop and the multiplier to 2. TheFullscreen
button will change toWindowed
in this mode to return to non-upscaled mode (960x540).
Selecting any resolution setting from the resolution combobox will immediately change to selected resolution. (Known bug: Clicking off the combobox without making a new selection while inUpscaled Fullscreen
mode will change resolution toFullscreen
. This will be addressed later.)Note: Changing the game window resolution while an Activity is active requires ending the Activity. A dialog box will appear asking to confirm the change.
-
Moved from C-style random number generation to C++ standard. This includes usage of a
mt19937
random number generator. -
Resolution validation changed to support multiple screens. Incompatible/bad resolution settings will be overridden at startup with messages explaining the issue.
Note: For multi-screen to work properly, the left-most screen MUST be set as primary. Screens having different resolutions does not actually matter but different heights will still be warned about and overridden due to the likeliness of GUI elementes being cropped on the shortest screen.
Resolution validation can be disabled for multi-screen setups withSettings.ini
propertyDisableMultiScreenResolutionValidation
. Bad settings are likely to crash, use at own risk.
For setups with more than 3 screensDisableMultiScreenResolutionValidation
must be set true. -
Damage to
Actors
from impulses is now relative to their max health instead of being on a scale from 0 to 100. -
Scenes
with aPresetName
containing the strings "Test", "Editor" and "Tutorial" are no longer excluded from the scenarios screen and from the MetaGame. -
SoundContainer
is now a concrete Lua entity. This means it can now be created withCreateSoundContainer("PresetName", "DataModule.rte")
and has all the standard functionality like cloning, etc.
To support these changes, a bunch of Lua functionality has been added and modified:soundContainer.Immobile
- Whether or not theSoundContainer
is immobile. Immobile sounds are generally used for GUI elements and will never be automatically panned, pitched or attenuated.
soundContainer.AttenuationStartDistance
- Formerly INI only, this property is now gettable and settable through Lua. See previous changelog entries for details on it.
soundContainer.Pos
- Rather than updating theSoundContainer's
position throughAudioMan
, you should now use thePos
property.
soundContainer.Volume
- In addition to attenuation based volume changes, it is now possible to set aSoundContainer's
overall volume. This works together with volume changes caused by attenuation.
soundContainer.Pitch
- Rather than updating theSoundContainer's
pitch throughAudioMan
, you should now use thePitch
property. Also note that this now works properly with the game's global pitch so no complicated handling is necessary. -
AddSound
andSelectNextSoundSet
Lua bindings have been moved fromSoundContainer
toSoundSet
. The latter has been renamed and the former have been trimmed down slightly since some complexity is no longer needed. Their speciifcs are mentioned in theAdded
section. -
Pressing escape at the options, mod manager, game editors and credits screens no longer quits the game.
Fixed
-
Fix crash when returning to
MetaGame
scenario screen after activity end. -
Control schemes will no longer get deleted when being configured. Resetting the control scheme will load a preset instead of leaving it blank. (Issue #121)
-
Fix glow effects being drawn one frame past
EffectStartTime
making objects that exist for a single frame not draw glows. (Issue #67) -
Time scale can no longer be lowered to 0 through the performance stats interface.
-
Actors now support their held devices identically while facing to either side. (Issue #31)
-
Fixed issue where clicking a ComboBox's scrollbar would release the mouse, thus causing unexpected behavior like not being able to close the list by clicking outside of it.
-
Fixed issue where ComboBoxes did not save the current selection, thus if the ComboBox was deselected without making a selection then the selection would revert to the default value instead of the last selected value.
-
Fixed issue with double clicks and missing clicks in menus (anything that uses AllegroInput).
-
Fixed issue where OnPieMenu function wasn't working for
AHuman
equipped items, and made it work forBGArm
equipped items as well asFGArm
ones. -
The "woosh" sound played when switching actors from a distance will now take scene wrapping into account. Additionally, attempting to switch to previous or next actor with only one actor will play the more correct "error" sound.
-
HDFirearm
INI propertyDeactivationSound
now works properly instead of constantly playing. -
Gold mining sound has been set to restart its playback everytime it's played, making it way less annoying. It's still pretty wonky, but it's better.
-
Sound panning should now work properly around scene seams. Additionally, sounds should be less stuttery (e.g. distant jetpacks) and generally sound better.
Removed
-
Removed the ability to remove scripts from objects with Lua. This is no longer needed cause of code efficiency increases.
-
Removed
Settings.ini
propertyPixelsPerMeter
. Now hardcoded and cannot be changed by the user. -
Removed
MOSParticle
propertyFramerate
and lua bindings.MOSParticle
animation is now handled withSpriteAnimMode
like everything else. -
Removed
ConsoleMan.ForceVisibility
andConsoleMan.ScreenSize
lua bindings. -
Removed
ActivityMan.PlayerCount
andActivityMan.TeamCount
setters lua bindings (obsolete and did nothing). -
Removed
Activity
propertiesTeamCount
andPlayerCount
. These are handled internally and do nothing when set in ini. -
Removed
Activity
propertyFundsOfTeam#
, useTeam#Funds
instead. -
Some functionality has been moved from
AudioMan
toSoundContainer
. As such, the followingAudioMan
Lua bindings are no longer available:
SetSoundPosition(soundContainer)
,SetSoundPitch(soundContainer
,PlaySound(filePath, position, player, loops, priority, pitchOrAffectedByGlobalPitch
,attenuationStartDistance, immobile)
The lengthy
PlaySound
function should be replaced by making aSoundContainer
in yourCreate
function and setting properties appropriately.
This can be done by creating one defined INI withsoundContainer = CreateSoundContainer(...)
, or by making an empty one withsoundContainer = SoundContainer()
.
0.1.0 pre-release 2 - 2020/05/08
Added
-
Lua binding for
Box::IntersectsBox(otherBox)
, that returns true if 2 boxes intersect. -
Command line arguments for launching directly into editors using
-editor "EditorName"
.
Valid editor names are:ActorEditor
,GibEditor
,SceneEditor
,AreaEditor
andAssemblyEditor
. -
Added handling for custom number and string values in INI.
AddCustomValue = NumberValue YourKeyName = YourNumberValue // Integer or floating point number. AddCustomValue = StringValue YourKeyName = YourStringValue
YourKeyName
is a string value and is not limited to just numbers. -
New
Settings.ini
propertyAdvancedPerformanceStats = 0/1
to disable/enable the performance counter graphs (enabled by default). -
Added
PassengerSlots
INI and Lua property to Actors. This determines how many spaces in the buy menu an actor will take up (1 by default). It must be a whole number but can theoretically be 0 or less. -
Added Lua bindings for
IsInsideX
andIsInsideY
toArea
. These act similarly to the pre-existingIsInside
, but allow you to check for the X and Y axes individually. -
Added the concept of
SoundSets
, which are collections of sounds inside aSoundContainer
. This allows you to, for example, put multiple sounds for a given gunshot inside aSoundSet
so they're played together. -
SoundContainers
have been overhauled to allow for a lot more customization, including per-sound customization. The following INI example shows all currently available capabilities with explanatory comments:AddSoundContainer = SoundContainer // Note that SoundContainers replace Sounds, so this can be used for things like FireSound = SoundContainer PresetName = Preset Name Here SoundSelectionCycleMode = RANDOM (default) | FORWARDS | ALL // How the SoundContainer will cycle through its `SoundSets` whenever it's told to select a new one. The first is prior behaviour of picking sounds at random, the second cycles through SoundSets in the order they were added, and the third plays all SoundSets at once. LoopSetting = -1 | 0 (default) | 1+ // How the SoundContainer loops its sounds. -1 means it loops forever, 0 means it plays once, any number > 0 means it plays once and loops that many times. Immobile = 0 (default) | 1 // Whether or not the SoundContainer's sounds should be treated as immobile. Immobile sounds are generally used for UI and system sounds; they will always play at full volume and will not be panned or affected by global pitch during game slowdown. AttenuationStartDistance = Number (default -1) // The distance at which the SoundContainer's sounds will start to attenuate out, any number < 0 set it to the game's default. Attenuation calculations follows FMOD's Inverse Rolloff model, which you can find linked below. Priority = 0 - 256 (default 128) // The priority at which the SoundContainer's sounds will be played, between 0 (highest priority) and 256 (lowest priority). Lower priority sounds are less likely to be played are a lot of sounds playing. AffectedByGlobalPitch = 0 | 1 (default) // Whether or not the SoundContainer's sounds will be affected by global pitch, or only change pitch when manually made to do so via Lua (note that pitch setting is done via AudioMan). AddSoundSet = SoundSet // This adds a SoundSet containing one or more sounds to the SoundContainer. AddSound = ContentFile // This adds a sound to the SoundSet, allowing it to be customized as shown. Filepath = "SomeRte.rte/Path/To/Sound.wav" Offset = Vector // This specifies where the sound plays with respect to its SoundContainer. This allows, for example, different sounds in a gun's reload to come from slightly different locations. X = Number Y = Number AttenuationStartDistance = Number // This functions identically to SoundContainer AttenuationStartDistance, allowing you to override it for specific sounds in the SoundContainer. MinimumAudibleDistance = Number (default 0) // This allows you to make a sound not play while the listener is within a certain distance, e.g. for gunshot echoes. It is automatically accounted for in sound attenuation. AddSound = "SomeRte.rte/Path/To/AnotherSound.wav" // This adds a sound to the SoundSet in oneline, allowing it to be compactly added (without customisation). AddSound = "SomeRte.rte/Path/To/YetAnotherSound.wav" // This adds a sound to the SoundContainer, creating a new SoundSet for it with just this sound.
NOTE: Here is a link to FMOD's Inverse Rolloff Model.
-
SoundContainer
Lua controls have been overhauled, allowing for more control in playing and replaying them. The following Lua bindings are available:soundContainer:HasAnySounds() -- Returns whether or not the SoundContainer has any sounds in it. Returns True or false.
soundContainer:IsBeingPlayed() -- Returns whether or not any sounds in the SoundContainer are currently being played. Returns True or False.
soundContainer:Play(optionalPosition, optionalPlayer) -- Plays the sounds belonging to the SoundContainer's currently selected SoundSet. The sound will play at the position and for the player specified, or at (0, 0) for all players if parameters aren't specified.
soundContainer:Stop(optionalPlayer) -- Stops any playing sounds belonging to the SoundContainer, optionally only stopping them for a specified player.
soundContainer:AddSound(filePath, optional soundSetToAddSoundTo, optionalSoundOffset, optionalAttenuationStartDistance, optionalAbortGameIfSoundIsInvalid) -- Adds the sound at the given filepath to the SoundContainer. If a SoundSet index is specified it'll add it to that SoundSet. If an offset or attenuation start distance are specified they'll be set, as mentioned in the INI section above. If set to abort for invalid sounds, the game will error out if it can't load the sound, otherwise it'll show a console error.
soundContainer:SetPosition(position) -- Sets the position at which the SoundContainer's sounds will play.
soundContainer:SelectNextSoundSet() -- Selects the next SoundSet to play when soundContainer:Play(...) is called, according to the INI defined CycleMode.
soundContainer.Loops -- Set or get the number of loops for the SoundContainer, as mentioned in the INI section above.
soundContainer.Priority -- Set or get the priority of the SoundContainer, as mentioned in the INI section above.
soundContainer.AffectedByGlobalPitch -- Set or get whether the SoundContainer is affected by global pitch, as mentioned in the INI section above.
-
MovableObjects
can now run multiple scripts by putting multipleAddScript = FilePath.lua
lines in the INI definition. (Issue #109)
Scripts will have their appropriate functions run in the order they were added. Note that all scripts share the sameself
, so care must be taken when naming self variables.
Scripts can be checked for withmovableObject:HasScript(filePath);
and added and removed withmovableObject:AddScript(filePath);
andmovableObject:RemoveScript(filePath);
. They can also be enabled and disabled in Lua (preserving their ordering) withmovableObject:EnableScript(filePath);
andmovableObject:DisableScript(filePath);
. -
Scripts on
MovableObjects
and anything that extends them (i.e. most things) now support the following new functions (in addition toCreate
,Update
,Destroy
andOnPieMenu
). They are added in the same way as the aforementioned scripts:OnScriptRemoveOrDisable(self, scriptWasRemoved) -- This is run when the script is removed or disabled. The scriptWasRemoved parameter will be True if the script was removed and False if it was disabled.
OnScriptEnable(self) -- This is run when the script was disabled and has been enabled.
OnCollideWithTerrain(self, terrainMaterial) -- This is run when the MovableObject this script on is in contact with terrain. The terrainMaterial parameter gives you the material ID for the terrain collided with. It is suggested to disable this script when not needed to save on overhead, as it will be run a lot!
OnCollideWithMO(self, collidedMO, collidedRootMO) -- This is run when the MovableObject this script is on is in contact with another MovableObject. The collidedMO parameter gives you the MovableObject that was collided with, and the collidedRootMO parameter gives you the root MovableObject of that MovableObject (note that they may be the same). Collisions with MovableObjects that share the same root MovableObject will not call this function.
-
Scripts on
Attachables
now support the following new functions:OnAttach(self, newParent) -- This is run when the Attachable this script is on is attached to a new parent object. The newParent parameter gives you the object the Attachable is now attached to.
OnDetach(self, exParent) -- This is run when the Attachable this script is on is detached from an object. The exParent gives you the object the Attachable was attached to.
Changed
-
Codebase now uses the C++14 standard.
-
Major cleanup and reformatting in the
System
folder. -
Upgraded to new, modern FMOD audio library. (Issue #72).
Sounds now play in 3D space, so they pan to the left and right, and attenuate automatically based on the player's viewpoint. -
Sounds
have been renamed toSoundContainers
, and are able to handle multiple sounds playing at once. INI definitions have changed accordingly.
They must be added using... = SoundContainer
, and individual sounds for them must be added usingAddSound = ContentFile...
. -
Various lua bindings around audio have been upgraded, changed or fixed, giving modders a lot more control over sounds. See documentation for more details.
-
Centered the loading splash screen image when
DisableLoadingScreen
is true. -
Box:WithinBox
lua bindings have been renamed:
Box:WithinBox
is nowBox:IsWithinBox
.
Box:WithinBoxX
is nowBox:IsWithinBoxX
.
Box:WithinBoxY
is nowBox:IsWithinBoxY
. -
Made
AHuman
show both weapon ammo states when 2 one-handed weapons are equipped. -
Added support for multiple lines in item descriptions (Issue#58). This is done as follows:
Description = MultiLineText AddLine = First line of text AddLine = Second line of text ...
-
FrameMan
broken down to 4 managers. New managers are:
PerformanceMan
to handle all performance stats and measurements.
PostProcessMan
to handle all post-processing (glows).
PrimitiveMan
to handle all lua primitive drawing. -
Post-processing (glow effects) is now enabled at all times with no option to disable.
-
All lua primitive draw calls are now called from
PrimitiveMan
.
For example:FrameMan:DrawLinePrimitive()
is nowPrimitiveMan:DrawLinePrimitive()
. -
Resolution multiplier properties (
NxWindowed
andNxFullscreen
) in settings merged into a single propertyResolutionMultiplier
. -
Incompatible/bad resolution settings will be overridden at startup with messages explaining the issue instead of multiple mode switches and eventually a reset to default VGA.
Reset to defaults (now 960x540) will happen only on horrible aspect ratio or if you managed to really destroy something. -
You can no longer toggle native fullscreen mode from the settings menu or ini. Instead, either select your desktop resolution at 1X mode or desktop resolution divided by 2 at 2X mode for borderless fullscreen windowed mode.
Due to limitations in Allegro 4, changing the actual resolution from within the game still requires a restart. -
If the current game resolution is half the desktop resolution or less, you will be able to instantly switch between 1X and 2X resolution multiplier modes in the settings without screen flicker or delay.
If the conditions are not met, the mode switch button will showUnavailable
. -
PieMenuActor
andOrbitedCraft
have now been removed. They are instead replaced with parameters in their respective functions, i.e.OnPieMenu(pieMenuActor);
andCraftEnteredOrbit(orbitedCraft);
. Their use is otherwise unchanged.
Fixed
-
Fixed LuaBind being all sorts of messed up. All lua bindings now work properly like they were before updating to the v141 toolset.
-
Explosives (and other thrown devices) will no longer reset their explosion triggering timer when they're picked up. (Issue #71)
-
Sprite Animation Mode
ALWAYSPINGPONG
now works properly. Sprite animation has also been moved toMOSprite
instead ofMOSRotating
, they they'll be able to properly animate now. (Issue#77) -
Fixed
BG Arm
flailing when reloading one-handed weapon, so shields are no longer so useless. -
Fixed crash when clearing an already empty preset list in the buy menu.
-
Temporary fix for low mass attachables/emitters being thrown at ridiculous speeds when their parent is gibbed.
-
The audio system now better supports splitscreen games, turning off sound panning for them and attenuating according to the nearest player.
-
The audio system now better supports wrapping maps so sounds handle the seam better. Additionally, the game should be able to function if the audio system fails to start up.
-
Scripts on attached attachables will only run if their parent exists in MovableMan. (Issue #83)
Removed
-
Removed all Gorilla Audio and SDL Mixer related code and files.
-
Removed all Steam Workshop and Achievement related code.
-
Removed a bunch of outdated/unused sources in the repo.
-
Removed all OSX/Linux related code and files because we don't care. See Liberated Cortex for working Linux port.
-
Removed a bunch of low-level
FrameMan
lua bindings:
FrameMan:ResetSplitScreens
,FrameMan:PPM
setter,FrameMan:ResX/Y
,FrameMan:HSplit/VSplit
,FrameMan:GetPlayerFrameBufferWidth/Height
,FrameMan:IsFullscreen
,FrameMan:ToggleFullScreen
,FrameMan:ClearBackbuffer8/32
,FrameMan:ClearPostEffects
,FrameMan:ResetFrameTimer
,FrameMan:ShowPerformanceStats
. -
Native fullscreen mode has been removed due to poor performance compared to windowed/borderless mode and various input device issues.
The version of Allegro we're running is pretty old now (released in 2007) and probably doesn't properly support/utilize newer features and APIs leading to these issues.
The minimal amount of hardware acceleration CC has is still retained through Windows' DWM and that evidently does a better job. -
Removed now obsolete
Settings.ini
properties:
Post-processing:TrueColorMode
,PostProcessing
,PostPixelGlow
.
Native fullscreen mode:Fullscreen
,NxWindowed
,NxFullscreen
,ForceSoftwareGfxDriver
,ForceSafeGfxDriver
.
0.1.0 pre-release 1 - 2020/01/27
Added
-
You can now run the game with command line parameters, including
-h
to see help and-c
to send ingame console input to cout. -
MOSprite
now has theFlipFactor
property that returns -1 if the sprite is flipped and 1 if it's not.
Using anynugNum
calculations based onHFlipped
is now considered criminal activity. -
TDExplosive
now has theIsAnimatedManually
property that lets modders set its frames manually through lua. -
You can now add
AEmitters
toMOSRotating
and have them function similarly to attachables.
Addition:parent:AddEmitter(emitterToAdd)
orparent:AddEmitter(emitterToAdd, parentOffsetVector)
Removal:parent:RemoveEmitter(emitterToRemove)
orparent:RemoveEmitter(uniqueIdOfEmitterToRemove)
-
Attachables can now collide with terrain when attached.
INI property:CollidesWithTerrainWhenAttached = 0/1
Check value:attachable.IsCollidingWithTerrainWhileAttached
Manipulate function:attachable:EnableTerrainCollisions(trueOrFalse)
Collisions can be manipulated only if the attachable was set toCollidesWithTerrainWhenAttached = 1
in ini. -
Actor.DeathSound
is now accessible to lua usingActor.DeathSound = "string pathToNewFile"
orActor.DeathSound = nil
for no DeathSound. -
AHuman
Feet are now accessible to lua usingAHuman.FGFoot
andAHuman.BGFoot
. Interaction with them may be wonky. -
Streamlined debug process and requirements so old Visual C++ Express edition is no longer needed for debugging.
-
Added minimal debug configuration for quicker debug builds without visualization.
Changed
-
ACrab
aim limits now adjust to crab body rotation. -
ACrab.AimRange
can now be split intoAimRangeUpperLimit
andAimRangeLowerLimit
, allowing asymmetric ranges. -
Objective arrows and Delivery arrows are now color coordinated to match their teams, instead of being only green or red.
-
BuyMenu
Bombs
tab will now show allThrownDevices
instead of justTDExplosives
. -
The list of
MOSRotating
attachables (mosr.Attachables
) now includes hardcoded attachables like dropship engines, legs, etc. -
Attachable lua manipulation has been significantly revamped. The old method of doing
attachable:Attach(parent)
has been replaced with the following:
Addition:parent:AddAttachable(attachableToAdd)
orparent:AddAttachable(attachableToAdd, parentOffsetVector)
Removal:parent:RemoveAttachable(attachableToRemove)
orparent:RemoveAttachable(uniqueIdOfAttachableToRemove)
-
Wounds have been separated internally from emitter attachables.
They can now be added withparent:AddWound(woundEmitterToAdd)
.
Removing wounds remains the same as before. -
Built-in Actor angular velocity reduction on death has been lessened.
Fixed
-
SFX slider now works properly.
-
BGM now loops properly.
-
Sound pitching now respects sounds that are not supposed to be affected by pitch.
-
Using
actor:Clone()
now works properly, there are no longer issues with controlling/selecting cloned actors. -
TDExplosive.ActivatesWhenReleased
now works properly. -
Various bug fixed related to all the Attachable and Emitter changes, so they can now me affected reliably and safely with lua.
-
Various minor other things that have gotten lost in the shuffle.
Removed
-
All licensing-related code has been removed since it's no longer needed.
-
Wounds can no longer be added via ini, as used to be doable buggily through ini
AddEmitter
. -
All usage of the outdated Slick Profiler has been removed.
-
TDExplosive.ParticleNumberToAdd
property has been removed.
Note: For a log of changes made prior to the commencement of the open source community project, look here.