Skip to content

Commit

Permalink
Merge branch 'deploy/fafbeta' of https://github.com/FAForever/fa into…
Browse files Browse the repository at this point in the history
… develop
  • Loading branch information
Garanas committed Aug 20, 2023
2 parents a9f5fec + f2bdefb commit 0e6954b
Show file tree
Hide file tree
Showing 40 changed files with 778 additions and 110 deletions.
5 changes: 5 additions & 0 deletions engine/Core/Categories.lua
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ categories = {
NANOCOMBATPRESET = categoryValue,
NAVALCARRIER = categoryValue,
NAVAL = categoryValue,

-- Allows this unit to be build by engineers
NEEDMOBILEBUILD = categoryValue,
NOFORMATION = categoryValue,
--- Prevents splash damage being applied to the entity
Expand Down Expand Up @@ -237,6 +239,9 @@ categories = {
StealthGenerator = categoryValue,
Switchback = categoryValue,
SystemIntegrityCompensator = categoryValue,

-- Populates a dummy factory that can take over the factory aspect of the unit
EXTERNALFACTORY = categoryValue
}

---@alias CategoryName
Expand Down
20 changes: 8 additions & 12 deletions lua/aibrains/platoons/platoon-simple-raid.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

local AIPlatoon = import("/lua/aibrains/platoons/platoon-base.lua").AIPlatoon
local NavUtils = import("/lua/sim/navutils.lua")
local MarkerUtils = import("/lua/sim/markerutilities.lua")
Expand All @@ -14,7 +13,7 @@ local TableEmpty = table.empty
local NavigateDistanceThresholdSquared = 20 * 20

---@class AIPlatoonSimpleRaidBehavior : AIPlatoon
---@field RetreatCount number
---@field RetreatCount number
---@field ThreatToEvade Vector | nil
---@field LocationToRaid Vector | nil
---@field OpportunityToRaid Vector | nil
Expand Down Expand Up @@ -72,12 +71,12 @@ AIPlatoonSimpleRaidBehavior = Class(AIPlatoon) {
local label, error = NavUtils.GetLabel('Land', position)

if label then

-- TODO
-- this should be cached, part of the marker utilities
local expansions, count = MarkerUtils.GetMarkersByType('Expansion Area')
---@type MarkerData[]
local candidates = { }
local candidates = {}
local candidateCount = 0
for k = 1, count do
local expansion = expansions[k]
Expand Down Expand Up @@ -154,7 +153,7 @@ AIPlatoonSimpleRaidBehavior = Class(AIPlatoon) {
return
end

-- navigate towards waypoint
-- navigate towards waypoint
local dx = origin[1] - waypoint[1]
local dz = origin[3] - waypoint[3]
local d = math.sqrt(dx * dx + dz * dz)
Expand Down Expand Up @@ -289,15 +288,15 @@ AIPlatoonSimpleRaidBehavior = Class(AIPlatoon) {

-- tell attack units to attack
local attackCommand
local attackOffset, error = NavUtils.RandomDirectionFrom('Land', location, 32, 4) -- TODO: remove magic numbers'
local attackOffset, error = NavUtils.RandomDirectionFrom('Land', location, 32, 4) -- TODO: remove magic numbers'
if not attackOffset then
attackCommand = self:AggressiveMoveToLocation(location, 'Attack')
else
attackCommand = self:AggressiveMoveToLocation(attackOffset, 'Attack')
end

-- tell scout units to patrol for threats
local scoutOffsets, countOrError = NavUtils.DirectionsFrom('Land', location, 32, 4) -- TODO: remove magic numbers
local scoutOffsets, countOrError = NavUtils.DirectionsFrom('Land', location, 32, 4) -- TODO: remove magic numbers
if not scoutOffsets then
self:Patrol(location, 'Scout')
else
Expand Down Expand Up @@ -332,7 +331,7 @@ AIPlatoonSimpleRaidBehavior = Class(AIPlatoon) {
-- check if our command is still going
if not self:IsCommandsActive(attackCommand) then
-- setup attack units
local attackOffset, error = NavUtils.RandomDirectionFrom('Land', location, 10, 8) -- TODO: remove magic numbers
local attackOffset, error = NavUtils.RandomDirectionFrom('Land', location, 10, 8) -- TODO: remove magic numbers
if not attackOffset then
self:LogWarning(string.format('no alternative directions found to evade'))
self:ChangeState(self.Error)
Expand Down Expand Up @@ -441,7 +440,7 @@ AIPlatoonSimpleRaidBehavior = Class(AIPlatoon) {
end
end

for k, scout in units do
for k, scout in units do
scout:SetFireState(1)
end
end,
Expand Down Expand Up @@ -471,6 +470,3 @@ DebugAssignToUnits = function(data, units)
ChangeState(platoon, platoon.Start)
end
end



80 changes: 80 additions & 0 deletions lua/defaultcomponents.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local Buff = import("/lua/sim/buff.lua")
local Entity = import("/lua/sim/Entity.lua").Entity

---@class ShieldEffectsComponent : Unit
---@field Trash TrashBag
Expand Down Expand Up @@ -758,3 +759,82 @@ VeterancyComponent = ClassSimple {
return fractionComplete * unitMass * vetMult + cargoMass
end,
}

---@class ExternalFactoryComponent
---@field ExternalFactory ExternalFactoryUnit
ExternalFactoryComponent = ClassSimple {

FactoryAttachBone = false,

---@param self Unit | ExternalFactoryComponent
OnStopBeingBuilt = function(self, builder, layer)
local blueprint = self.Blueprint
if not self.FactoryAttachBone then
error(string.format("%s is not setup for an external factory: the unit does not have a field 'FactoryAttachBone'", blueprint.BlueprintId))
end

if not blueprint.CategoriesHash['EXTERNALFACTORY'] then
error(string.format("%s is not setup for an external factory: the unit does not have a 'EXTERNALFACTORY' category", blueprint.BlueprintId))
end

local blueprintIdExternalFactory = blueprint.BlueprintId .. 'ef'
if not __blueprints[blueprintIdExternalFactory] then
error(string.format("%s is not setup for an external factory: the external factory blueprint is not setup", blueprint.BlueprintId))
end

-- create the factory somewhere completely unrelated
local position = self:GetPosition(self.FactoryAttachBone)

-- we need to put an entity in between so that we can always click-select the
-- factory. The 'CARRIER' category can prevent us from clicking on attached units
local entity = Entity({Owner = self})
self.Trash:Add(entity)
entity:AttachTo(self, self.FactoryAttachBone)

self.ExternalFactory = CreateUnitHPR(blueprintIdExternalFactory, self.Army, position[1], position[2], position[3], 0, 0, 0) --[[@as ExternalFactoryUnit]]
self.ExternalFactory:AttachTo(entity, -1)
self.ExternalFactory:SetCreator(self)
self.ExternalFactory:SetParent(self)
self.Trash:Add(self.ExternalFactory)
end,

---@param self Unit | ExternalFactoryComponent
OnPaused = function(self)
if self.ExternalFactory then
self.ExternalFactory:SetPaused(true)
end
end,

---@param self Unit | ExternalFactoryComponent
OnUnpaused = function(self)
if self.ExternalFactory then
self.ExternalFactory:SetPaused(false)
end
end,

---@param self Unit | ExternalFactoryComponent
OnIdle = function(self)
if self.ExternalFactory then
self.ExternalFactory:SetBusy(false)
self.ExternalFactory:SetBlockCommandQueue(false)
end
end,

---@param self Unit | ExternalFactoryComponent
---@param new Layer
---@param old Layer
OnLayerChange = function(self, new, old)
if self.ExternalFactory then
if new == 'Land' then
self.ExternalFactory:RestoreBuildRestrictions()
self.ExternalFactory:RequestRefreshUI()
elseif new == 'Seabed' then
self.ExternalFactory:AddBuildRestriction(categories.ALLUNITS)
self.ExternalFactory:RequestRefreshUI()

IssueClearCommands({self.ExternalFactory})
end
end
end,

}
126 changes: 125 additions & 1 deletion lua/defaultunits.lua
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ StructureUnit = ClassUnit(Unit) {
end,

---@param self StructureUnit
---@param builder Builder
---@param builder Unit
---@param layer Layer
OnStopBeingBuilt = function(self, builder, layer)
Unit.OnStopBeingBuilt(self, builder, layer)
Expand Down Expand Up @@ -3229,3 +3229,127 @@ ShieldLandUnit = ClassUnit(LandUnit) {}
-- SHIELD SEA UNITS
---@class ShieldSeaUnit : SeaUnit
ShieldSeaUnit = ClassUnit(SeaUnit) {}

---@class ExternalFactoryUnit : Unit
---@field Parent Unit
---@field UpdateParentProgressThread? thread
ExternalFactoryUnit = ClassUnit(Unit) {

UpdateProgressOfParent = true,

---@param self ExternalFactoryUnit
OnCreate = function(self)
Unit.OnCreate(self)
self:HideBone(0, true)
end,

---@param self ExternalFactoryUnit
---@param parent Unit
SetParent = function(self, parent)
self.Parent = parent
end,

---@param self ExternalFactoryUnit
UpdateParentProgress = function(self)

-- This thread runs instead of using:
-- - `OnBuildProgress = function(self, unit, oldProg, newProg)`
--
-- The former is only called in intervals of 25%, which is not what users expect

local parent = self.Parent
while self.UnitBeingBuilt do
parent:SetWorkProgress(self:GetWorkProgress())
WaitTicks(2)
end
end,

---@param self ExternalFactoryUnit
---@param unitbuilding Unit
---@param order Layer
OnStartBuild = function(self, unitbuilding, order)
Unit.OnStartBuild(self, unitbuilding, order)
self.Parent:OnStartBuild(unitbuilding, order)
self.UnitBeingBuilt = unitbuilding

if self.UpdateProgressOfParent then
self.UpdateParentProgressThread = self.Trash:Add(
ForkThread(
self.UpdateParentProgress, self
)
)
end
end,

---@param self ExternalFactoryUnit
---@param unitBeingBuilt Unit
OnStopBuild = function(self, unitBeingBuilt)
Unit.OnStopBuild(self, unitBeingBuilt)
self.Parent:OnStopBuild(unitBeingBuilt)
self.UnitBeingBuilt = nil

if self.UpdateParentProgressThread then
KillThread(self.UpdateParentProgressThread)
self.Parent:SetWorkProgress(0)
end

-- block building until our creator tells us to continue
self:SetBusy(true)
self:SetBlockCommandQueue(true)
end,

---@param self ExternalFactoryUnit
OnFailedToBuild = function(self)
Unit.OnFailedToBuild(self)
self.Parent:OnFailedToBuild()
self.UnitBeingBuilt = nil

if self.UpdateParentProgressThread then
KillThread(self.UpdateParentProgressThread)
self.Parent:SetWorkProgress(0)
end

-- block building until our creator tells us to continue
self:SetBusy(true)
self:SetBlockCommandQueue(true)
end,

---@param self ExternalFactoryUnit
CalculateRollOffPoint = function(self)
return self.Parent:CalculateRollOffPoint()
end,

---@param self ExternalFactoryUnit
RolloffBody = function(self)
self.Parent:RolloffBody()
end,

---@param self ExternalFactoryUnit
RollOffUnit = function(self)
self.Parent:RollOffUnit()
end,

---@param self ExternalFactoryUnit
StartBuildFx = function(self, unitBeingBuilt)
self.Parent:StartBuildFx(unitBeingBuilt)
end,

---@param self ExternalFactoryUnit
StopBuildFx = function(self)
self.Parent:StopBuildFx()
end,

---@param self ExternalFactoryUnit
PlayFxRollOff = function(self)
self.Parent:StopBuPlayFxRollOffildFx()
end,

---@param self ExternalFactoryUnit
PlayFxRollOffEnd = function(self)
self.Parent:PlayFxRollOffEnd()
end,

IdleState = FactoryUnit.IdleState,
BuildingState = FactoryUnit.BuildingState,
RollingOffState = FactoryUnit.RollingOffState,
}
4 changes: 4 additions & 0 deletions lua/keymap/debugKeyActions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ local keyActionsDebug = {
action = 'UI_Lua import("/lua/ui/game/maputilities.lua").OpenWindow()',
category = 'debug',
},
['test'] = {
action = 'UI_Lua import("/lua/keymap/misckeyactions.lua").SelectExternalFactory()',
category = 'debug',
},
['toggle_ai_screen'] = {
action = 'UI_Lua import("/lua/ui/dialogs/aiutilitiesview.lua").OpenWindow()',
category = 'debug'
Expand Down
8 changes: 8 additions & 0 deletions lua/keymap/keyactions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,14 @@ local keyActionsSelectionQuickSelect = {
action = 'UI_SelectByCategory +nearest FACTORY',
category = 'selection',
},
['select_all_mobile_factory_onscreen'] = {
action = 'UI_SelectByCategory +inview EXTERNALFACTORYUNIT',
category = 'selection',
},
['select_nearest_mobile_factory'] = {
action = 'UI_SelectByCategory +nearest EXTERNALFACTORYUNIT',
category = 'selection',
},
['select_nearest_land_factory'] = {
action = 'UI_SelectByCategory +nearest LAND FACTORY',
category = 'selection',
Expand Down
2 changes: 2 additions & 0 deletions lua/keymap/keydescriptions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ keyDescriptions = {
['select_all_eng_onscreen'] = '<LOC key_desc_0073>Select all Engineers on the screen',
['select_all_factory_onscreen'] = '<LOC key_desc_0074>Select all Factories on the screen',
['select_nearest_factory'] = '<LOC key_desc_0075>Select the nearest Factory',
['select_all_mobile_factory_onscreen'] = '<LOC select_all_mobile_factory_onscreen>Select all Mobile Factories on the screen',
['select_nearest_mobile_factory'] = '<LOC select_nearest_mobile_factory>Select the nearest Mobile Factory',
['select_nearest_land_factory'] = '<LOC key_desc_0076>Select the nearest Land Factory',
['select_nearest_air_factory'] = '<LOC key_desc_0077>Select the nearest Air Factory',
['select_nearest_naval_factory'] = '<LOC key_desc_0078>Select the nearest Naval Factory',
Expand Down
11 changes: 10 additions & 1 deletion lua/keymap/misckeyactions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -609,4 +609,13 @@ SurfaceAll = function()
if not table.empty(submergedUnits) then
IssueUnitCommand(submergedUnits, "UNITCOMMAND_Dive")
end
end
end

SelectExternalFactory = function()
local selection = GetSelectedUnits()
if selection then
local unit = selection[1]
reprsl(GetAssistingUnitsList(selection))
SelectUnits(GetAssistingUnitsList(selection))
end
end
8 changes: 4 additions & 4 deletions lua/sim/Unit.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1088,8 +1088,8 @@ Unit = ClassUnit(moho.unit_methods, IntelComponent, VeterancyComponent) {
if focus:IsUnitState('SiloBuildingAmmo') then
local siloBuildRate = focus:GetBuildRate() or 1
time, energy, mass = focus:GetBuildCosts(focus.SiloProjectile)
energy = (energy / siloBuildRate) * (self:GetBuildRate() or 1)
mass = (mass / siloBuildRate) * (self:GetBuildRate() or 1)
energy = (energy / siloBuildRate) * (self:GetBuildRate() or 0)
mass = (mass / siloBuildRate) * (self:GetBuildRate() or 0)
else
time, energy, mass = self:GetBuildCosts(focus:GetBlueprint())
if self:IsUnitState('Repairing') and focus.isFinishedUnit then
Expand All @@ -1099,8 +1099,8 @@ Unit = ClassUnit(moho.unit_methods, IntelComponent, VeterancyComponent) {
end
end

energy = math.max(1, energy * (self.EnergyBuildAdjMod or 1))
mass = math.max(1, mass * (self.MassBuildAdjMod or 1))
energy = math.max(0, energy * (self.EnergyBuildAdjMod or 1))
mass = math.max(0, mass * (self.MassBuildAdjMod or 1))
energy_rate = energy / time
mass_rate = mass / time
end
Expand Down
Loading

0 comments on commit 0e6954b

Please sign in to comment.