Skip to content

[CPLUS plus ex] Skill Selection

DasKeifer edited this page Sep 30, 2026 · 6 revisions

Skill Selection

Functions for selecting skills for pilots.

Modders generally are not expected to use these but they may be helpful for testing changes and your skills. None of these need to be called manually.

Table of Contents


applySkillsToPilot

  • void cplus_plus_ex:applySkillsToPilot(pilot, fireHooks)
Argument name Type Description
pilot Pilot memhack Pilot struct
fireHooks bool If true, fires skillsSelected hook before applying skills (Default: false)

Applies level up skills to a pilot. If the pilot already has assigned skills, those are loaded and applied. Otherwise, random skills are selected based on configuration and constraints, then applied.

Example:

-- Apply skills to pod reward pilot
local podPilot = Game:GetPodRewardPilot()
if podPilot then
    cplus_plus_ex:applySkillsToPilot(podPilot, true)
end

applySkillIdsToPilot

  • void cplus_plus_ex:applySkillIdsToPilot(pilot, skillIds, fireHooks)
Argument name Type Description
pilot Pilot memhack Pilot struct
skillIds table Table with two skill IDs: {skill1Id, skill2Id}
fireHooks bool If true, fires skillsSelected hook before applying skills (Default: false)

Applies specific skills to a pilot by ID. Use this to manually assign skills instead of random selection.

Example:

local pilot = Game:GetSquadPilots()[1]

-- Force override pilot skills
cplus_plus_ex:applySkillIdsToPilot(pilot, {"Move", "Grid"})

applySkillsToAllPilots

  • void cplus_plus_ex:applySkillsToAllPilots()

Applies skills to all available pilots (squad + storage). Pilots that already have skills assigned will be skipped. New pilots will have skills applied/assigned.

Fires preAssigningLvlUpSkills and postAssigningLvlUpSkills hooks if any new pilots are found. Also fires skillsSelected hooks for each new pilot.

Example:

-- Manually trigger skill application
cplus_plus_ex:applySkillsToAllPilots()

selectRandomSkill

  • string|false cplus_plus_ex:selectRandomSkill(availableSkills, pilot, idx, selectedSkills)
Argument name Type Description
availableSkills table Array of skill ID strings (mutated: invalid candidates are removed). Prefer getAssignableSkillIds(). Do not pass getEnabledSkillsSet() (set has no array length for ipairs).
pilot Pilot memhack Pilot struct
idx int Index of skill to assign (1-2 normal, 3+ virtual)
selectedSkills table Array-like table of already selected skill IDs; written at idx on success

Selects a weighted random skill ID that passes constraints for idx. On success, sets selectedSkills[idx] and returns the skill id string. Returns false if none available.

Example:

local pool = cplus_plus_ex:getAssignableSkillIds()
local pilot = Game:GetSquadPilots()[1]
local skills = {"Reactor"}
local chosen = cplus_plus_ex:selectRandomSkill(pool, pilot, 2, skills)
if chosen then
   LOG("Selected second skill: " .. skills[2])
end

selectRandomSkills

  • table cplus_plus_ex:selectRandomSkills(availableSkills, pilot, count)
Argument name Type Description
availableSkills table Array like table of skills that can be chosen
pilot Pilot memhack Pilot struct
count int Number of skills to assign to the pilot. Can exceed 2 for virtual skills

Selects random level up skills based on count and configured constraints. The count parameter can exceed 2 to select virtual skills. Slots 1-2 are regular skills, slots 3+ are virtual skills.

Returns an array like table of the skill IDs selected.

Example:

local pool = cplus_plus_ex:getAssignableSkillIds()
local pilot = Game:GetSquadPilots()[1]
local skills = cplus_plus_ex:selectRandomSkills(pool, pilot, 2)
LOG("Selected skill " .. skills[1] .. " and skill " .. skills[2])

getAssignableSkillIds

  • table cplus_plus_ex:getAssignableSkillIds()

Returns an array of enabled skill IDs eligible for random assignment. Internal skills (internalSkill = true) are omitted; they can still be set via applySkillIdsToPilot.

Example:

local pool = cplus_plus_ex:getAssignableSkillIds()
for _, skillId in ipairs(pool) do
    LOG("Assignable: " .. skillId)
end

markPerRunSkillAsUsed

  • void cplus_plus_ex:markPerRunSkillAsUsed(skillId)
Argument name Type Description
skillId string Skill ID

Records a PER_RUN skill as assigned this run so it will not be selected again. No op for non per run skills. Call after a skill is applied, not during pool selection. CPLUS+ calls this automatically during normal assignment.

unmarkPerRunSkill

  • void cplus_plus_ex:unmarkPerRunSkill(skillId)
Argument name Type Description
skillId string Skill ID

Releases a per run claim so a pilot can keep or replace their own stored skill during revalidation. Used internally when validating existing skills. Rarely needed by mods.

canBeVirtualSkill

  • bool cplus_plus_ex:canBeVirtualSkill(skillId)
Argument name Type Description
skillId string Skill ID to check

Checks if a skill is allowed to be assigned as a virtual skill. Returns false for skills with hardcoded vanilla behavior that doesn't work correctly in virtual slots, or for skills that don't exist.

Returns true if the skill can be assigned as a virtual skill (slot 3+)

Vanilla skills that cannot be virtual:

  • Opener, Closer, Popular, Thick, Invulnerable, Adrenaline, Pain, Regen, Conservative

Example:

if cplus_plus_ex:canBeVirtualSkill("Reactor") then
    LOG("Reactor can be a virtual skill")
end
if not cplus_plus_ex:canBeVirtualSkill("Opener") then
    LOG("Opener has hardcoded behavior and cannot be virtual")
end

registerVirtualSkillSource

  • bool cplus_plus_ex:registerVirtualSkillSource(sourceId, callback)
Argument name Type Description
sourceId string Source id of the source granting virtual skills (e.g. "warbot")
callback fn function to call when a skill is no longer allowed

Registers a skill source for virtual skills and allows defining behavior when the skill not longer is valid.

This is OPTIONAL and not required for skill sources. If not specified, it will default to re-rolling the skill. Sources MUST register with this to implement different behavior

callback function signature: onSkillInvalidated(pilot, skillData, alreadyAssigned)

Argument name Type Description
pilot Pilot memhack Pilot struct
skillData table Virtual skill entry: { id = string, source = string }
alreadyAssigned table Skills already assigned to the pilot

The callback returns the same skill id to keep it, nil to remove it, or a different skill id to replace it.

Returns true if successfully registered

Example:

-- Forces nimble regardless
local function onSkillInvalidated(pilot, skillData, alreadyAssigned)
   return "RrNimble"
end
cplus_plus_ex:registerVirtualSkillSource("ForcedNimble", onSkillInvalidated)

addVirtualSkillToPilot

  • bool cplus_plus_ex:addVirtualSkillToPilot(pilot, skillId, source)
Argument name Type Description
pilot Pilot memhack Pilot struct
skillId string Skill ID to add as a virtual skill
source string Optional. Source of the virtual skill for tracking/invalidation behavior

Adds a single virtual skill to the pilot in the first available virtual slot (slot 3+). Validates constraints including:

  • Skill must be virtual-capable (canBeVirtualSkill)
  • Skill must be enabled in configuration
  • Must satisfy reusability constraints (PER_PILOT, PER_RUN)
  • Must satisfy slot restrictions and exclusions

Source is optional and can be used to track where it came from and define behavior if the skill no longer becomes valid for the run. See registerVirtualSkillSource for more info on source and behavior.

Returns true if the skill was successfully added

Example:

local pilot = Game:GetSquadPilots()[1]

-- Add a third skill
if cplus_plus_ex:addVirtualSkillToPilot(pilot, "Grid") then
    LOG("Successfully added Grid as slot 3")
else
    LOG("Failed - constraint violation or skill not virtual-capable")
end

addVirtualSkillsToPilot

  • int cplus_plus_ex:addVirtualSkillsToPilot(pilot, skillIds, source)
Argument name Type Description
pilot Pilot memhack Pilot struct
skillIds table Array of skill IDs to add: {"skill1", "skill2", ...}
source string Optional. Source of the virtual skill for tracking/invalidation behavior

Adds multiple virtual skills to the pilot in the order provided. Each skill is validated before adding. Returns the total count of skills that were successfully added.

Source is optional and can be used to track where it came from and define behavior if the skill no longer becomes valid for the run. See registerVirtualSkillSource for more info on source and behavior.

Returns count of skills successfully added

Example:

local pilot = Game:GetSquadPilots()[1]

-- Try to add 3 virtual skills
local skills = {"Move", "Grid", "Reactor"}
local count = cplus_plus_ex:addVirtualSkillsToPilot(pilot, skills)

LOG(string.format("Successfully added %d out of %d virtual skills", count, #skills))

addRandomVirtualSkillsToPilot

  • int cplus_plus_ex:addRandomVirtualSkillsToPilot(pilot, count, source)
Argument name Type Description
pilot Pilot memhack Pilot struct
count number Number of random virtual skills to add
source string Optional. Source of the virtual skill for tracking/invalidation behavior

Randomly selects and adds virtual skills to the pilot based on:

  • Configuration weights
  • Skill constraints (exclusions, reusability, slot restrictions)
  • Available enabled skills that can be virtual

Source is optional and can be used to track where it came from and define behavior if the skill no longer becomes valid for the run. See registerVirtualSkillSource for more info on source and behavior.

Returns the count of skills successfully added (may be less than requested if constraints are violated).

Example:

local pilot = Game:GetSquadPilots()[1]

-- Add 2 random virtual skills
local count = cplus_plus_ex:addRandomVirtualSkillsToPilot(pilot, 2)

if count > 0 then
    LOG(string.format("Added %d random virtual skills", count))
else
    LOG("Could not add any virtual skills (no valid options)")
end

removeVirtualSkillFromPilot

  • bool cplus_plus_ex:removeVirtualSkillFromPilot(pilot, skillId)
Argument name Type Description
pilot Pilot memhack Pilot struct
skillId string Skill ID to remove

Removes the first occurrence of the specified virtual skill from the pilot. If the pilot has the same skill multiple times as virtual skills, only one instance is removed. This only affects virtual skills (slot 3+) - It will NOT remove skills from slots 1-2

Returns true if a virtual skill was removed

Example:

local pilot = Game:GetSquadPilots()[1]
if cplus_plus_ex:removeVirtualSkillFromPilot(pilot, "Reactor") then
    LOG("Removed Reactor from virtual skills")
else
    LOG("Pilot doesn't have Reactor as a virtual skill")
end

clearVirtualSkillsFromPilot

  • bool cplus_plus_ex:clearVirtualSkillsFromPilot(pilot)
Argument name Type Description
pilot Pilot memhack Pilot struct

Removes all virtual skills from the pilot. This only affects virtual skills (slot 3+) - It will NOT remove skills from slots 1-2

Returns true if any virtual skills were cleared

Example:

local pilot = Game:GetSquadPilots()[1]
if cplus_plus_ex:clearVirtualSkillsFromPilot(pilot) then
    LOG("Cleared all virtual skills from " .. pilot:getNameStr())
else
    LOG(pilot:getNameStr() .. " had no virtual skills to clear")
end

Clone this wiki locally