Comment on page
Upgrade Guide
Key notes on upgrading existing mod for the CET 1.14+:
- Don't use
Game
object and any game types beforeonInit
. - Don't use
GetMod()
beforeonInit
. - Don't pass excessive params to game functions. If the max number of params is 3, then passing 4 params will result in an error.
- Update
Observe()
/Override()
handlers so they acceptself
as the first param. Previously, some observers lacked theself
param:
Observe("PlayerPuppet", "OnAction", function(self, action)
-- First param self is required now
end)
- If your mod stores player reference then unset it when game session ends.
- An unreleased reference can lead to bugs such as disappearing footsteps.
- Accessing
Game.GetPlayer()
inonUpdate
will not cause the issue. - This can be achieved using next snippet or with
GameSession
/GameUI
libs:
Observe("QuestTrackerGameController", "OnUninitialize", function()
if Game.GetPlayer() == nil then
Mod.Player = nil -- var containing a reference to the player
end
end)
- Use corresponding getters for game systems instead of
GetSingleton()
. For example,Game.GetTeleportationFacility()
instead ofGetSingleton('gameTeleportationFacility')
.
New scripting capabilities were introduced in CET 1.14 to make it more convenient and simple:
- All game classes are directly accessible by name. For example,
entEntityId
,PlayerPuppet
. - All game enums are directly accessible by name. For example,
gamedataStatType.BaseDamage
,gameGameVersion.Current
. - Classes can also be accessed by their aliases from redscript. For example,
WeaponObject
instead ofgameweaponObject
. - Classes have the conventional
.new()
constructor. For example,MappinData.new()
. - A constructor can take an array of properties to create and initialize an object in a single statement. For example,
EntityID.new({ hash = 12345 })
. - Static methods are accessible from classes using the dot. For example,
ScriptedPuppet.IsDefeated(npc)
. - A static method can be called from an instance if the first parameter is of the same type. For example,
vec4:Length()
instead ofVector4.Length(vec4)
. - The overloaded function is resolved based on passed parameters when called by its short name. For example,
StatusEffectHelper.HasStatusEffect(target, gamedataStatusEffectType.Overheat)
. - Partial
Variant
type support.ToVariant()
andFromVariant()
are only applicable to classes.
All new scripting features are optional. You're not required to rewrite an existing mod using these features.
The new API allows code that is also valid redscript or very close to its redscript counterpart. Thus, it simplifies the research and the transition to / from the redscript.
For example, this line looks exactly the same in Lua and in the redscript:
RPGManager.CreateStatModifier(gamedataStatType.BaseDamage, gameStatModifierType.Additive, 50)
Constructing objects
Old API:
local mappinData = NewObject("gamemappinsMappinData")
mappinData.mappinType = TweakDBID.new("Mappins.DefaultStaticMappin")
mappinData.variant = Enum.new("gamedataMappinVariant", "FastTravelVariant")
mappinData.visibleThroughWalls = true
New API:
local mappinData = MappinData.new()
mappinData.mappinType = "Mappins.DefaultStaticMappin"
mappinData.variant = gamedataMappinVariant.FastTravelVariant
mappinData.visibleThroughWalls = true
Constructor with initialization
Old API:
function getStash()
local stashId = NewObject("entEntityID")
stashId.hash = 16570246047455160070ULL
return Game.FindEntityByID(stashId)
end
New API:
function getStash()
return Game.FindEntityByID(EntityID.new({ hash = 16570246047455160070ULL }))
end
Scripted static call
Old API:
Game["PreventionSystem::ShowMessage;GameInstanceStringFloat"]("Message", 5.0)
New API:
PreventionSystem.ShowMessage("Message", 5.0)
Shorthand static call
Old API:
Observe("PlayerPuppet", "OnAction", function(action)
-- Option 1 --
print(GetSingleton("gameinputScriptListenerAction"):GetName(action))
-- Option 2 --
print(action:GetName(action))
end)
New API:
Observe("PlayerPuppet", "OnAction", function(action)
-- Option 1 --
print(ListenerAction.GetName(action))
-- Option 2 --
print(action:GetName())
end)
Working with enums
Old API:
print(Enum.new('gameGameVersion', 'Current') == Enum.new('gameGameVersion', 'CP77_GoldMaster'))
print(Enum.new('gameGameVersion', 'Current') == Enum.new('gameGameVersion', 'CP77_Patch_1_2_Hotfix2'))
New API:
print(gameGameVersion.Current == gameGameVersion.CP77_GoldMaster)
print(gameGameVersion.Current == gameGameVersion.CP77_Patch_1_2_Hotfix2)
Variants
local message = SimpleScreenMessage.new()
message.message = "Test"
message.isShown = true
local blackboardDefs = Game.GetAllBlackboardDefs()
local blackboardUI = Game.GetBlackboardSystem():Get(blackboardDefs.UI_Notifications)
blackboardUI:SetVariant(
blackboardDefs.UI_Notifications.OnscreenMessage,
ToVariant(message),
true
)
Last modified 1mo ago