Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotate code related to collision beam entities #6627

Merged
merged 14 commits into from
Jan 18, 2025
1 change: 1 addition & 0 deletions changelog/snippets/other.6627.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- (#6627) Annotate code related to collision beam entities.
4 changes: 4 additions & 0 deletions engine/Core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ end
function KillThread(thread)
end

---@class thread
local thread = {}
thread.Destroy = KillThread -- Set in /lua/system/config.lua

--- Rounds a number to the nearest integer using the half-round-even rounding (banker's rules)
--- This means that it returns the closest integer and tie-breaks towards even numbers
--- (since a bias towards even numbers is less detrimental than an upward bias).
Expand Down
3 changes: 1 addition & 2 deletions engine/Core/Blueprints/WeaponBlueprint.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@
---@field AutoInitiateAttackCommand? boolean
--- Ballistic arcs that should be used on the projectile
---@field BallisticArc? WeaponBallisticArc
--- every `X/10+1` game ticks, this beam will collide and do damage - using `0` will cause beams to
--- damage every tick
--- Interval in seconds between beam collision checks (which take 1 tick) - using `0` will cause beams to damage every tick
---@field BeamCollisionDelay number
--- the amount of time the beam exists
---@field BeamLifetime number
Expand Down
31 changes: 20 additions & 11 deletions engine/Sim/CollisionBeamEntity.lua
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
---@meta

---@class CollisionBeamSpec
---@field Weapon Weapon # Weapon to attach to
---@field BeamBone Bone # Bone of the weapon's unit which the beam is attached to
---@field OtherBone 0 # Which bone of the beam is attached to the unit. Use 0 for a functioning beam. 1 attaches it backwards, which is practically non-functional.
---@field CollisionCheckInterval number # Interval in ticks between collision check ticks

---@class moho.CollisionBeamEntity : moho.entity_methods
local CCollisionBeamEntity = {}

---
-- CollisionBeamEntity:Enable()
--- Enables beam collision checking, which calls `CCollisionBeamEntity:OnImpact` in Lua every check.
function CCollisionBeamEntity:Enable()
end

---
-- CCollisionBeamEntity:GetLauncher()
--- Disables beam collision checking.
function CCollisionBeamEntity:Disable()
end

--- Returns the unit that is responsible for creating this collision beam.
---@return Unit
function CCollisionBeamEntity:GetLauncher()
end

---
-- bool = CCollisionBeamEntity:IsEnabled()
---@return boolean
function CCollisionBeamEntity:IsEnabled()
end

---
-- CCollisionBeamEntity:SetBeamFx(beamEmitter, checkCollision) -- set an emitter to be controlled by this beam. Its length parameter will be set from the beam entity's collision distance.
--- Set an emitter to be controlled by this beam. Its length parameter will be set from the beam entity's collision distance.
---@param beamEmitter moho.IEffect # Beam type emitter
---@param checkCollision boolean
function CCollisionBeamEntity:SetBeamFx(beamEmitter, checkCollision)
end

---
-- beam = CreateCollisionBeam(spec)spec is a table with the following fields defined:
function CCollisionBeamEntity:__init()
---@param spec CollisionBeamSpec
---@return moho.CollisionBeamEntity
function CCollisionBeamEntity:__init(spec)
end

return CCollisionBeamEntity
2 changes: 1 addition & 1 deletion lua/aibrains/components/EnergyManagerBrainComponent.lua
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ EnergyManagerBrainComponent = ClassSimple {
end
end,

--- A continious thread that across the life span of the brain. Is the heart and sole of the enabling and disabling of units that are designed to eliminate excess energy.
--- A continuous thread that across the life span of the brain. Is the heart and sole of the enabling and disabling of units that are designed to eliminate excess energy.
---@param self AIBrain
ToggleEnergyExcessUnitsThread = function(self)

Expand Down
78 changes: 37 additions & 41 deletions lua/sim/CollisionBeam.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,17 @@ local GetTerrainType = GetTerrainType
local DefaultTerrainType = GetTerrainType(-1, -1)

---@class CollisionBeam : moho.CollisionBeamEntity
---@field unit Unit
---@field Weapon Weapon
---@field Army Army
---@field DamageTable WeaponDamageTable
---@field BeamEffectsBag moho.IEffect[]
---@field TerrainEffectsBag moho.IEffect[]
---@field FxImpactWater FileName[]?
---@field FxImpactUnderWater FileName[]?
---@field FxImpactUnit FileName[]?
---@field FxImpactAirUnit FileName[]?
---@field FxImpactLand FileName[]?
---@field Trash TrashBag
CollisionBeam = Class(moho.CollisionBeamEntity) {

Expand Down Expand Up @@ -103,7 +113,7 @@ CollisionBeam = Class(moho.CollisionBeamEntity) {
---@param self CollisionBeam
---@param instigator Unit
---@param damageData table
---@param targetEntity? Unit
---@param targetEntity Unit | Projectile | Prop | nil
DoDamage = function(self, instigator, damageData, targetEntity)
local damage = damageData.DamageAmount or 0
if damage <= 0 then return end
Expand Down Expand Up @@ -160,7 +170,7 @@ CollisionBeam = Class(moho.CollisionBeamEntity) {
AttachBeamToEntity(fxBeam, self, 0, self.Army)

-- collide on start if it's a continuous beam
local weaponBlueprint = self.Weapon:GetBlueprint()
local weaponBlueprint = self.Weapon.Blueprint
local bCollideOnStart = weaponBlueprint.BeamLifetime <= 0
self:SetBeamFx(fxBeam, bCollideOnStart)

Expand All @@ -180,9 +190,9 @@ CollisionBeam = Class(moho.CollisionBeamEntity) {
end,

---@param self CollisionBeam
---@param army number
---@param EffectTable string[]
---@param EffectScale number
---@param army Army
---@param EffectTable FileName[]?
---@param EffectScale number?
CreateImpactEffects = function(self, army, EffectTable, EffectScale)
local emit = nil
EffectTable = EffectTable or {}
Expand All @@ -196,8 +206,8 @@ CollisionBeam = Class(moho.CollisionBeamEntity) {
end,

---@param self CollisionBeam
---@param army number
---@param EffectTable string[]
---@param army Army
---@param EffectTable FileName[]
---@param EffectScale number
CreateTerrainEffects = function(self, army, EffectTable, EffectScale)
local emit = nil
Expand Down Expand Up @@ -271,35 +281,19 @@ CollisionBeam = Class(moho.CollisionBeamEntity) {
end
end,

-- This is called when the collision beam hits something new. Because the beam
-- is continuously detecting collisions it only executes this function when the
-- thing it is touching changes. Expect Impacts with non-physical things like
-- 'Air' (hitting nothing) and 'Underwater' (hitting nothing underwater).
--- Called by the engine while the beam is active every `CollisionCheckInterval + 1` ticks
--- or when `SetBeamFx(beamEmitter, checkCollision)` is called with `checkCollision = true`.
--- Expect Impacts with non-physical things like 'Air' (hitting nothing) and 'Underwater' (hitting nothing underwater).
---@param self CollisionBeam
---@param impactType ImpactType
---@param targetEntity? Unit | Prop
---@param targetEntity Unit | Projectile | Prop | nil
OnImpact = function(self, impactType, targetEntity)
-- LOG('*DEBUG: COLLISION BEAM ONIMPACT ', repr(self))
-- LOG('*DEBUG: COLLISION BEAM ONIMPACT, WEAPON = ', repr(self.Weapon), 'Type = ', impactType)
-- LOG('CollisionBeam impacted with: ' .. impactType)
-- Possible 'type' values are:
-- 'Unit'
-- 'Terrain'
-- 'Water'
-- 'Air'
-- 'UnitAir'
-- 'Underwater'
-- 'UnitUnderwater'
-- 'Projectile'
-- 'Prop'
-- 'Shield'

if impactType == 'Unit' or impactType == 'UnitAir' or impactType == 'UnitUnderwater' then
if not self:GetLauncher() then
return
end

self:ShowBeamSource(targetEntity)
self:ShowBeamSource(targetEntity --[[@as Unit]])
else
self:HideBeamSource()
end
Expand All @@ -312,7 +306,7 @@ CollisionBeam = Class(moho.CollisionBeamEntity) {

-- Buffs (Stun, etc)
if targetEntity and IsUnit(targetEntity) then
self:DoUnitImpactBuffs(targetEntity)
self:DoUnitImpactBuffs(targetEntity --[[@as Unit]])
end

-- Do Damage
Expand Down Expand Up @@ -362,18 +356,20 @@ CollisionBeam = Class(moho.CollisionBeamEntity) {
--- Creates a new `WeaponDamageTable` in `self.DamageTable` using the weapon blueprint
---@param self CollisionBeam
SetDamageTable = function(self)
local weaponBlueprint = self.Weapon:GetBlueprint()
---@type WeaponDamageTable
self.DamageTable = {}
self.DamageTable.DamageRadius = weaponBlueprint.DamageRadius
self.DamageTable.DamageAmount = weaponBlueprint.Damage
self.DamageTable.DamageType = weaponBlueprint.DamageType
self.DamageTable.DamageFriendly = weaponBlueprint.DamageFriendly
self.DamageTable.CollideFriendly = weaponBlueprint.CollideFriendly
self.DamageTable.DoTTime = weaponBlueprint.DoTTime
self.DamageTable.DoTPulses = weaponBlueprint.DoTPulses
self.DamageTable.Buffs = weaponBlueprint.Buffs
self.CollideFriendly = self.DamageData.CollideFriendly == true
local bp = self.Weapon:GetBlueprint()
local collideFriendly = bp.CollideFriendly
self.DamageTable = {
DamageRadius = bp.DamageRadius,
DamageAmount = bp.Damage,
DamageType = bp.DamageType,
DamageFriendly = bp.DamageFriendly,
CollideFriendly = collideFriendly,
DoTTime = bp.DoTTime,
DoTPulses = bp.DoTPulses,
Buffs = bp.Buffs,
}
-- Cache the table access for collision checks later
self.CollideFriendly = collideFriendly
end,

-- When this beam impacts with the target, do any buffs that have been passed to it.
Expand Down
2 changes: 1 addition & 1 deletion lua/sim/MatchState.lua
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function ObserverAfterDeath(armyIndex)
end
end

--- Continiously scans the game for brains being defeated or changes in alliances that can cause the game to end
--- Continuously scans the game for brains being defeated or changes in alliances that can cause the game to end
local function MatchStateThread()

-- determine game conditions
Expand Down
8 changes: 5 additions & 3 deletions lua/sim/Unit.lua
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ local cUnitGetBuildRate = cUnit.GetBuildRate
---@field PlatoonHandle? Platoon
---@field tickIssuedShieldRepair number? # Used by shields to keep track of when this unit's guards were ordered to start shield repair instantly
---@field Sync { id: string, army: Army } # Sync table replicated to the global sync table as to be copied to the user layer at sync time.
---@field ignoreDetectionFrom table<Army, true>? # Armies being given free vision to reveal beams hitting targets
---@field reallyDetectedBy table<Army, true>? # Armies that detected the unit without free vision and don't need intel flushed when beam weapons stop hitting
Unit = ClassUnit(moho.unit_methods, IntelComponent, VeterancyComponent, DebugUnitComponent) {

IsUnit = true,
Expand Down Expand Up @@ -4331,8 +4333,8 @@ Unit = ClassUnit(moho.unit_methods, IntelComponent, VeterancyComponent, DebugUni
-------------------------------------------------------------------------------------------
---@param self Unit
---@param buffTable BlueprintBuff[]
---@param PosEntity Vector
AddBuff = function(self, buffTable, PosEntity)
---@param stunOrigin? Vector # Defaults to position of `self`
AddBuff = function(self, buffTable, stunOrigin)
local bt = buffTable.BuffType
if not bt then
error('*ERROR: Tried to add a unit buff in unit.lua but got no buff table. Wierd.', 1)
Expand All @@ -4349,7 +4351,7 @@ Unit = ClassUnit(moho.unit_methods, IntelComponent, VeterancyComponent, DebugUni
local targets
if buffTable.Radius and buffTable.Radius > 0 then
-- If the radius is bigger than 0 then we will use the unit as the center of the stun blast
targets = utilities.GetTrueEnemyUnitsInSphere(self, PosEntity or self:GetPosition(), buffTable.Radius, category)
targets = utilities.GetTrueEnemyUnitsInSphere(self, stunOrigin or self:GetPosition(), buffTable.Radius, category)
else
-- The buff will be applied to the unit only
if EntityCategoryContains(category, self) then
Expand Down
1 change: 1 addition & 0 deletions lua/sim/weapon.lua
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ local WeaponMethods = moho.weapon_methods
---@field Brain AIBrain
---@field CollideFriendly boolean
---@field DamageMod number
---@field DamageModifiers number[] # Set of damage multipliers used by collision beams for the weapon
---@field DamageRadiusMod number
---@field damageTableCache WeaponDamageTable | false # Set to false when the weapon's damage is modified
---@field DisabledBuffs table
Expand Down
17 changes: 11 additions & 6 deletions lua/sim/weapons/DefaultBeamWeapon.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@

local DefaultProjectileWeapon = import("/lua/sim/defaultweapons.lua").DefaultProjectileWeapon
local CollisionBeam = import("/lua/sim/collisionbeam.lua").CollisionBeam

---@class DefaultBeamWeapon : DefaultProjectileWeapon
---@field DisableBeamThreadInstance? thread
---@field Beams { Beam: CollisionBeam, Muzzle: string, Destroyables: table}[]
---@field BeamStarted boolean
---@field HoldFireThread? thread # deprecated
---@field ContBeamOn? boolean
DefaultBeamWeapon = ClassWeapon(DefaultProjectileWeapon) {
BeamType = CollisionBeam,

Expand Down Expand Up @@ -33,12 +34,12 @@ DefaultBeamWeapon = ClassWeapon(DefaultProjectileWeapon) {
-- Create the beam
for _, rack in bp.RackBones do
for _, muzzle in rack.MuzzleBones do
local beam
beam = self.BeamType {
---@type CollisionBeam
local beam = self.BeamType {
Weapon = self,
BeamBone = 0,
OtherBone = muzzle,
CollisionCheckInterval = bp.BeamCollisionDelay * 10, -- Why is this multiplied by 10? IceDreamer
CollisionCheckInterval = bp.BeamCollisionDelay * 10, -- convert seconds to ticks
}
local beamTable = { Beam = beam, Muzzle = muzzle, Destroyables = {} }
table.insert(self.Beams, beamTable)
Expand Down Expand Up @@ -108,13 +109,14 @@ DefaultBeamWeapon = ClassWeapon(DefaultProjectileWeapon) {
-- enable the beam
beam:Enable()

-- non-continious beams that just end
-- non-continuous beams that just end
if bp.BeamLifetime > 0 then
self:ForkThread(self.BeamLifetimeThread, beam, bp.BeamLifetime or 1)
end

-- continious beams
-- continuous beams
if bp.BeamLifetime == 0 then
---@diagnostic disable-next-line: deprecated
self.HoldFireThread = self:ForkThread(self.WatchForHoldFire, beam)
end

Expand Down Expand Up @@ -243,6 +245,7 @@ DefaultBeamWeapon = ClassWeapon(DefaultProjectileWeapon) {
-- Weapon States Section

IdleState = State(DefaultProjectileWeapon.IdleState) {
---@param self DefaultBeamWeapon
Main = function(self)
DefaultProjectileWeapon.IdleState.Main(self)
self:PlayFxBeamEnd()
Expand All @@ -251,6 +254,7 @@ DefaultBeamWeapon = ClassWeapon(DefaultProjectileWeapon) {
},

WeaponPackingState = State(DefaultProjectileWeapon.WeaponPackingState) {
---@param self DefaultBeamWeapon
Main = function(self)
local bp = self.Blueprint
if bp.BeamLifetime > 0 then
Expand All @@ -269,6 +273,7 @@ DefaultBeamWeapon = ClassWeapon(DefaultProjectileWeapon) {
end,

RackSalvoFireReadyState = State(DefaultProjectileWeapon.RackSalvoFireReadyState) {
---@param self DefaultBeamWeapon
Main = function(self)
if not self:EconomySupportsBeam() then
self:PlayFxBeamEnd()
Expand Down
1 change: 1 addition & 0 deletions lua/sim/weapons/DefaultProjectileWeapon.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ local MathClamp = math.clamp
---@field DropBombShortRatio? number if the weapon blueprint requests a trajectory fix, this is set to the ratio of the distance to the target that the projectile is launched short to
---@field SalvoSpreadStart? number if the weapon blueprint requests a trajectory fix, this is set to the value that centers the projectile spread for `CurrentSalvoNumber` shot on the optimal target position
---@field WeaponPackState 'Packed' | 'Unpacked' | 'Unpacking' | 'Packing'
---@field EconDrain? moho.EconomyEvent
DefaultProjectileWeapon = ClassWeapon(Weapon) {

FxRackChargeMuzzleFlash = {},
Expand Down
4 changes: 4 additions & 0 deletions lua/system/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
--====================================================================================
-- Disable the LuaPlus bit where you can add attributes to nil, booleans, numbers, and strings.
--------------------------------------------------------------------------------------

local function metacleanup(obj)
local name = type(obj)
local mmt = {
Expand All @@ -28,6 +29,7 @@ metacleanup('')
--====================================================================================
-- Set up a metatable for coroutines (a.k.a. threads)
--------------------------------------------------------------------------------------

local thread_mt = {Destroy = KillThread}
thread_mt.__index = thread_mt
function thread_mt.__newindex(_, _, _)
Expand All @@ -40,6 +42,7 @@ setmetatable(getmetatable(coroutine.create(function()end)), thread_mt)
-- Replace math.random with our custom random. On the sim side, this is
-- a rng with consistent state across all clients.
--------------------------------------------------------------------------------------

if Random then
math.random = Random
end
Expand All @@ -49,6 +52,7 @@ end
-- Give globals an __index() with an error function. This causes an error message
-- when a nonexistent global is accessed, instead of just quietly returning nil.
--------------------------------------------------------------------------------------

local globalsmeta = {
__index = function(_, key)
error("access to nonexistent global variable " .. repr(key), 2)
Expand Down
2 changes: 1 addition & 1 deletion lua/ui/game/gamemain.lua
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ function DeselectSelens(selection)
return otherUnits, true
end

--- A cache used with ObserveSelection to prevent continious table allocations
--- A cache used with ObserveSelection to prevent continuous table allocations
local cachedSelection = {
oldSelection = { },
newSelection = { },
Expand Down
Loading
Loading