Variable drones number based on enhancement

Everything about mods can be found here.

Moderator: Morax

Variable drones number based on enhancement

Postby DDDX » 30 Oct 2018, 22:31

Hi all.

Need your help again.
So my issue is this. I want to make the number of drones dependent on enhancements - for example, unit starts with 2 drones, but gets +2 if it has an enhancement for it. Drone script is taken from that of the Goliath from BO:Unleashed.

PROBLEM: The drones do not rebuild when killed.
CODE: -new unit has enhancement that gives more drones
(accomplished by making a new DroneData table inside the unit's .bp file, referrenced when the enhancement is obtained
Code: Select all
        --Guardian protocol
        if enh =='GuardianProtocol' then            --my enhancement, under CreateEnhancement function
       
        if next(self.DroneTable) then
                    for name, drone in self.DroneTable do
                        IssueClearCommands({drone})          --getting rid of the 2 existing drones from the starting DroneData table inside the units .bp file, because they just sit idely doing nothing AFTER the enhancement is obtained.
                        IssueKillSelf({drone})
                    end
                end
        self:DroneSetup2()  -calling my own DroneSetup code, copy/paste of the existing one, the entire function, in which i use my DroneData2 table instead of DroneData, that has 4 drones in it instead of 2
-

Now, this all works nicely, I start with 2 drones that attack and get rebuilt, but as soon as I upgrade the enhancement - i get 4 drones that behave as they should EXCEPT for rebuilding.
I suspect that is because the 2 previous drones are still in a table or...dunno.
The original DroneSetup is called from OnStopBeingBuilt.

Anyone who is better versed in drones perhaps has a clue what is lacking? I would really like to solve this without having to copy the whole code for drones, modified for the second data table...
Check out my 2 maps: "Survival_Mayhem&BO_3d_v1" "Survival_Mayhem&BO_3d_RPG"
as well as my mod: "Survival Mayhem&BO balance"
-- let me know of any bugs or issues regarding those 3.
DDDX
Avatar-of-War
 
Posts: 170
Joined: 21 Mar 2016, 16:13
Has liked: 18 times
Been liked: 16 times
FAF User Name: DDDX

Re: Variable drones number based on enhancement

Postby Franck83 » 01 Nov 2018, 10:57

Hi DDDX,

Can you post more of your code (bp table, functions...), so we can help you.
Alliance of Heroes Mod is out ! Try it ! It's in the Mod Vault !
User avatar
Franck83
Evaluator
 
Posts: 538
Joined: 30 Dec 2016, 11:59
Location: France
Has liked: 114 times
Been liked: 122 times
FAF User Name: Franck83

Re: Variable drones number based on enhancement

Postby Uveso » 01 Nov 2018, 17:09

DDDX wrote:because they just sit idely doing nothing AFTER the enhancement is obtained.


Maybe the drones "parent" is still the old unit not the new one ?
(just a guess, we need the full working code to debug)
User avatar
Uveso
Supreme Commander
 
Posts: 1788
Joined: 11 Dec 2015, 20:56
Location: Germany
Has liked: 70 times
Been liked: 291 times
FAF User Name: Uveso

Re: Variable drones number based on enhancement

Postby DDDX » 03 Nov 2018, 10:06

Ty for your reply.
I have c/p the entire .script file for the unit, while marking with ----- the parts concerning drones (or lambda emmitter stuff)

As for the .bp file, it simply has 2 DroneData tables, one with 2 drones (Drone1 and Drone2) and one called DroneData2 with 8 drones (Drone1-Drone8) (along with the rest of the code that is the same for every carrier unit in all mods)


Now...all that will give me 2 drones that rebuild when klilled, and having the enhancement get made will give me more drones, but they dont rebuild when made.
I am calling the DroneSetup2 from my enhancement, whereas the original DroneSetup is called from OnStopBeingBuilt (together with some other functions and I guess therein lies the problem i have. I should be calling those functions from my enhancement as well I guess, when I start the alternative DroneSetup. But which should be duplicated, or how do I link them to the new DroneSetup2 if not duplicated?).
Code: Select all
local AAirUnit = import('/lua/aeonunits.lua').AAirUnit
local explosion = import('/lua/defaultexplosions.lua')
local util = import('/lua/utilities.lua')
local aWeapons = import('/lua/aeonweapons.lua')

local WeaponsFile = import('/lua/aeonweapons.lua')
local ADFCannonOblivionWeapon = WeaponsFile.ADFCannonOblivionWeapon02
local TMWeaponsFile = import('/mods/TotalMayhem/lua/TMAeonWeapons.lua')
local TMAmizurabluelaserweapon = TMWeaponsFile.TMAmizurabluelaserweapon
local AWeapons = import('/lua/aeonweapons.lua')
local ADFOverchargeWeapon = AWeapons.ADFOverchargeWeapon

local MassKilled = 0
local BlackOpsEffectTemplate = import('/mods/BlackOpsFAF-Unleashed/lua/BlackOpsEffectTemplates.lua')
local Buff = import('/lua/sim/Buff.lua')
local AIUtils = import('/lua/AI/aiutilities.lua')

local ADFPhasonLaser = WeaponsFile.ADFPhasonLaser
local TMEffectTemplate = import('/mods/TotalMayhem/lua/TMEffectTemplates.lua')
local EffectTemplate = import('/lua/EffectTemplates.lua')
local WeaponsFileT = import('/lua/terranweapons.lua')
local TDFGaussCannonWeapon = WeaponsFileT.TDFLandGaussCannonWeapon
local nukeFiredOnGotTarget = false
local SeraphimWeapons = import('/lua/seraphimweapons.lua')
local SIFHuAntiNukeWeapon = import('/lua/seraphimweapons.lua').SIFHuAntiNukeWeapon
local WeaponsFile2 = import('/lua/terranweapons.lua')
local TDFGaussCannonWeapon = WeaponsFile2.TDFLandGaussCannonWeapon
local AAATemporalFizzWeapon = import('/lua/aeonweapons.lua').AAATemporalFizzWeapon

XAA9904 = Class(AAirUnit) {
    AmbientEffects = 'ST2PowerAmbient',
    ShieldEffects = {
        '/effects/emitters/seraphim_regenerative_aura_01_emit.bp',
    },

--    LambdaEffects = {
--       '/effects/emitters/seraphim_t3power_ambient_01_emit.bp',
--       '/effects/emitters/seraphim_t3power_ambient_02_emit.bp',
--       '/effects/emitters/seraphim_t3power_ambient_04_emit.bp',
--   },

Weapons = {
     laserblue3 = Class(TMAmizurabluelaserweapon) {
    },
     laserblue4 = Class(TMAmizurabluelaserweapon) {
    },
     laserblue5 = Class(TMAmizurabluelaserweapon) {
    },
     laserblue6 = Class(TMAmizurabluelaserweapon) {
    },
    MainGun = Class(ADFCannonOblivionWeapon) {},             
    MainGun01 = Class(ADFCannonOblivionWeapon) {},
     MainGun1 = Class(ADFCannonOblivionWeapon) {},     --att left 01  naprijed desni
    MainGun2 = Class(ADFCannonOblivionWeapon) {},         ---left 12   otraga lijevi
   MainGun3 = Class(ADFCannonOblivionWeapon) {},            -- right 01   mid lijevi
   MainGun4 = Class(ADFCannonOblivionWeapon) {},            -- med 07     mid desni
   MainGun5 = Class(ADFCannonOblivionWeapon) {},            --right 06   otraga desni
    MainGun6 = Class(ADFCannonOblivionWeapon) {},         -- med 06     naprijed lijevi
    BeamL = Class(ADFPhasonLaser) {},                     -- left 06     otraga desni
    BeamR = Class(ADFPhasonLaser) {},                   -- right 06     otragad lijevi
    BeamM = Class(ADFPhasonLaser) {},
    bigGun = Class(TDFGaussCannonWeapon) {},           --rockets
    TorpedoTurrets01 = Class(import('/lua/seraphimweapons.lua').SANHeavyCavitationTorpedo) {
    },                 
    SMD = Class(SIFHuAntiNukeWeapon) {
                IdleState = State(SIFHuAntiNukeWeapon.IdleState) {
                    OnGotTarget = function(self)
                        local bp = self:GetBlueprint()
                        if (bp.WeaponUnpackLockMotion ~= true or (bp.WeaponUnpackLocksMotion == true and not self.unit:IsUnitState('Moving'))) then
                            if (bp.CountedProjectile == false) or self:CanFire() then
                                 nukeFiredOnGotTarget = true
                            end
                        end
                        SIFHuAntiNukeWeapon.IdleState.OnGotTarget(self)
                    end,
                   
                    OnFire = function(self)
                        if not nukeFiredOnGotTarget then
                            SIFHuAntiNukeWeapon.IdleState.OnFire(self)
                        end
                        nukeFiredOnGotTarget = false
                       
                        self:ForkThread(function()
                            self.unit:SetBusy(true)
                            WaitSeconds(1/self.unit:GetBlueprint().Weapon[1].RateOfFire + .2)
                            self.unit:SetBusy(false)
                        end)
                    end,
                },       
    },   
    EMPgun = Class(TDFGaussCannonWeapon) {
            FxMuzzleFlash = BlackOpsEffectTemplate.LambdaRedirector,
                        FxMuzzleFlashScale = 2.7,
    },   
    AntiMissile = Class(AAATemporalFizzWeapon) {
    },
    OverCharge = Class(ADFOverchargeWeapon) {

            OnCreate = function(self)
                ADFOverchargeWeapon.OnCreate(self)
                self:SetWeaponEnabled(false)
              --  self.AimControl:SetEnabled(false)
              --  self.AimControl:SetPrecedence(0)
                self.unit:SetOverchargePaused(false)
            end,

            OnEnableWeapon = function(self)
                if self:BeenDestroyed() then return end
                ADFOverchargeWeapon.OnEnableWeapon(self)
                self:SetWeaponEnabled(true)
                self.unit:SetWeaponEnabledByLabel('BeamL', false)
                self.unit:BuildManipulatorSetEnabled(false)
            --   self.AimControl:SetEnabled(true)
            --   self.AimControl:SetPrecedence(20)
            --  self.unit.BuildArmManipulator:SetPrecedence(0)
              self.AimControl:SetHeadingPitch( self.unit:GetWeaponManipulatorByLabel('BeamL'):GetHeadingPitch() )
            end,

            OnWeaponFired = function(self)
                ADFOverchargeWeapon.OnWeaponFired(self)
                self:OnDisableWeapon()
                self:ForkThread(self.PauseOvercharge)
            end,
           
            OnDisableWeapon = function(self)
                if self.unit:BeenDestroyed() then return end
                self:SetWeaponEnabled(false)
                self.unit:SetWeaponEnabledByLabel('BeamL', true)
           --     self.unit:BuildManipulatorSetEnabled(false)
           --    self.AimControl:SetEnabled(false)
          --    self.AimControl:SetPrecedence(0)
           --    self.unit.BuildArmManipulator:SetPrecedence(0)
                self.unit:GetWeaponManipulatorByLabel('BeamL'):SetHeadingPitch( self.AimControl:GetHeadingPitch() )
            end,
           
            PauseOvercharge = function(self)
                if not self.unit:IsOverchargePaused() then
                    self.unit:SetOverchargePaused(true)
                    if self.unit:HasEnhancement('OverchargeAmplifierA') then
                        WaitSeconds(18)
                        self.unit:SetOverchargePaused(false)
                    else
                        WaitSeconds(33)
                        self.unit:SetOverchargePaused(false)
                    end
                end
            end,
           
            OnFire = function(self)
                if not self.unit:IsOverchargePaused() then
                    ADFOverchargeWeapon.OnFire(self)
                end
            end,
            IdleState = State(ADFOverchargeWeapon.IdleState) {
                OnGotTarget = function(self)
                    if not self.unit:IsOverchargePaused() then
                        ADFOverchargeWeapon.IdleState.OnGotTarget(self)
                    end
                end,           
                OnFire = function(self)
                    if not self.unit:IsOverchargePaused() then
                        ChangeState(self, self.RackSalvoFiringState)
                    end
                end,
            },
            RackSalvoFireReadyState = State(ADFOverchargeWeapon.RackSalvoFireReadyState) {
                OnFire = function(self)
                    if not self.unit:IsOverchargePaused() then
                        ADFOverchargeWeapon.RackSalvoFireReadyState.OnFire(self)
                    end
                end,
            },             
        },   
},


OnStopBeingBuilt = function(self,builder,layer)   
        AAirUnit.OnStopBeingBuilt(self,builder,layer)       
         self:CreatTheEffects()
       
       local army =  self:GetArmy()
            for k, v in BlackOpsEffectTemplate['LambdaRedirector'] do
                        --WaitSeconds(2)
                        self.Trash:Add(CreateAttachedEmitter(self, 'Attachpoint_Lrg_01', army, v):ScaleEmitter(4.5))
                       -- WaitSeconds(1)
                    end

        self:AddBuildRestriction( categories.AEON * (categories.BUILTBYALPHAA1 + categories.BUILTBYALPHAA2 + categories.BUILTBYALPHAA3 + categories.BUILTBYALPHAA4 + categories.BUILTBYTIER1ENGINEER + categories.BUILTBYTIER2ENGINEER + categories.BUILTBYTIER3ENGINEER - categories.uab1105 - categories.uab1106 - categories.bab1106) )        --restrict everything except mass and energy storage                             
       
       -- self:SetWeaponEnabledByLabel('Depthcharge', false)
        self:SetWeaponEnabledByLabel('laserblue3', false)
        self:SetWeaponEnabledByLabel('laserblue5', false)
        self:SetWeaponEnabledByLabel('BeamR', false)
        self:SetWeaponEnabledByLabel('BeamM', false)
        self:SetWeaponEnabledByLabel('EMPgun', false)
        self:SetWeaponEnabledByLabel('TorpedoTurrets01', false) 
       -- self:SetWeaponEnabledByLabel('Arty', false)
      --  self:SetWeaponEnabledByLabel('rocket', false)


           --regen stuff
        self.RegenFieldFXBag = {}
        self:SetMaintenanceConsumptionActive()
        self:DisableUnitIntel('unitScript', 'CloakField') -- Used to show restoration range

        self.lambdaEmitterTable = {}
      --  self:ForkThread(self.LambdaEmitter)
------------------------------------------------
        self.slots = {}
        self.transData = {}
        self.weaponCounter = 0 

        if self.AnimationManipulator then
            self:SetUnSelectable(true)
            self.AnimationManipulator:SetRate(1)           
            self:ForkThread(function()
                WaitSeconds(self.AnimationManipulator:GetAnimationDuration()*self.AnimationManipulator:GetRate())
                self:SetUnSelectable(false)
                self.AnimationManipulator:Destroy()
            end)
        end

    --    -- Button status toggles
        self.DroneMaintenance = true
        self.DroneAssist = true 

        -- Assist management globals
        self.MyAttacker = nil
        self.MyTarget = nil

        -- Drone construction/repair buildrate
        self.BuildRate = self:GetBlueprint().Economy.BuildRate or 500

        -- Drone setup (load globals/tables & create drones)
        self:DroneSetup()
        self:SetScriptBit('RULEUTC_IntelToggle', true)
     --   self.FlamerEffectsBag = {}
       
        self.spoof = false
        self.gettingBuilt = false
        self:ForkThread(self.CheckAIThread) 
    end,

CheckAIThread = function(self)
        if self:GetAIBrain().BrainType ~= 'Human' then
            self:SetScriptBit('RULEUTC_IntelToggle', false)
        end
    end,

    -- Places the Goliath's first drone-targetable attacker into a global
    OnDamage = function(self, instigator, amount, vector, damagetype)
        if not self:IsDead()
       -- and self.MyAttacker == nil
        and self:IsValidDroneTarget(instigator) then
            self.MyAttacker = instigator
        end
        AAirUnit.OnDamage(self, instigator, amount, vector, damagetype)
    end,
       
    -- Drone control buttons
    OnScriptBitSet = function(self, bit)
        -- Drone assist toggle, on
        if bit == 1 then
            self.DroneAssist = false
        -- Drone recall button
        elseif bit == 7 then
            self:RecallDrones()
            -- Pop button back up, as it's not actually a toggle
            self:SetScriptBit('RULEUTC_SpecialToggle', false)
        else
            AAirUnit.OnScriptBitSet(self, bit)
        end
    end,
   
    OnScriptBitClear = function(self, bit)
        -- Drone assist toggle, off
        if bit == 1 then
            self.DroneAssist = true
        -- Recall button reset, do nothing
        elseif bit == 7 then
            return
        else
            AAirUnit.OnScriptBitClear(self, bit)
        end
    end,
   
    -- Handles drone docking
    OnTransportAttach = function(self, bone, unit)
        self.DroneData[unit.Name].Docked = bone
        unit:SetDoNotTarget(true)
        BaseTransport.OnTransportAttach(self, bone, unit)
    end,
   
    -- Handles drone undocking, also called when docked drones die
    OnTransportDetach = function(self, bone, unit)
        self.DroneData[unit.Name].Docked = false
        unit:SetDoNotTarget(false)
        if unit.Name == self.BuildingDrone then
            self:CleanupDroneMaintenance(self.BuildingDrone)
        end
        BaseTransport.OnTransportDetach(self, bone, unit)
    end,
----------------------------------------
--buff aura
GetUnitsToBuff = function(self, bp)
        local unitCat = categories.ALLUNITS - categories.ALPHA
        local brain = self:GetAIBrain()
        local all = brain:GetUnitsAroundPoint(unitCat, self:GetPosition(), bp.Radius, 'Ally')
        local units = {}

        for _, u in all do
            if not u.Dead and not u:IsBeingBuilt() then
                table.insert(units, u)
            end
        end

        return units
    end,

    RegenBuffThread = function(self, enh)
        local bp = self:GetBlueprint().Enhancements[enh]
        local buff

        if enh == 'ScavengerProtocol' then
            buff = 'SeraphimACURegenAura'
        elseif enh == 'SurvivalProtocol' then
            buff = 'SeraphimACUAdvancedRegenAura'       
        elseif enh == 'ScavengerProtocol' then
            buff = 'SeraphimACURegenAura'
        end

        while not self.Dead do
            local units = self:GetUnitsToBuff(bp)
            for _,unit in units do
                Buff.ApplyBuff(unit, buff)
                unit:RequestRefreshUI()
            end
            WaitSeconds(5)
        end
    end,
------------------------------------------------------
CreatTheEffects = function(self)
    local army =  self:GetArmy()
    for k, v in EffectTemplate['AResourceGenAmbient'] do
        self.Trash:Add(CreateAttachedEmitter(self, 'Attachpoint_Lrg_01', army, v):ScaleEmitter(2.5))
    end
    for k, v in EffectTemplate['AResourceGenAmbient'] do
        self.Trash:Add(CreateAttachedEmitter(self, 'Attachpoint_Lrg_01', army, v):ScaleEmitter(2.3))
    end
    for k, v in EffectTemplate['AResourceGenAmbient'] do
        self.Trash:Add(CreateAttachedEmitter(self, 'Attachpoint_Lrg_01', army, v):ScaleEmitter(2.3))
    end
    for k, v in EffectTemplate['GenericTeleportCharge01'] do
            self.Trash:Add(CreateAttachedEmitter(self, 'Attachpoint_Lrg_06', army, v):ScaleEmitter(7.8))   
    end 
    for k, v in EffectTemplate['GenericTeleportCharge01'] do
            self.Trash:Add(CreateAttachedEmitter(self, 'Attachpoint_Lrg_01', army, v):ScaleEmitter(7.8))   
    end 
    for k, v in EffectTemplate['GenericTeleportCharge01'] do
            self.Trash:Add(CreateAttachedEmitter(self, 'Attachpoint_Lrg_03', army, v):ScaleEmitter(2.8))   
    end 
    for k, v in EffectTemplate['GenericTeleportCharge01'] do
            self.Trash:Add(CreateAttachedEmitter(self, 'Attachpoint_Lrg_04', army, v):ScaleEmitter(2.8))   
    end
end,
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CreateEnhancement = function(self, enh, removal)
        AAirUnit.CreateEnhancement(self, enh)
        local bp = self:GetBlueprint().Enhancements[enh]
        if not bp then return end

        --Guardian protocol
        if enh =='GuardianProtocol' then   
          self:RemoveBuildRestriction(categories.sbab2306)
            self:updateBuildRestrictions()

         if Buffs['aaAeonTorpHealth1'] then                --needed to fix the hp stacking when switching between enhancements
                Buff.RemoveBuff(self, 'aaAeonTorpHealth1')
            end
            if Buffs['aaAeonTorpHealth2'] then
                Buff.RemoveBuff(self, 'aaAeonTorpHealth2')
            end
            if Buffs['aaAeonTorpHealth3'] then
                Buff.RemoveBuff(self, 'aaAeonTorpHealth3')
            end
          --  self:AddBuildRestriction( categories.AEON * (categories.BUILTBYTIER2ENGINEER + categories.BUILTBYTIER3ENGINEER - categories.SBROT1EXPD) )
            if not Buffs['aaAeonACUT2BuildRate'] then
                BuffBlueprint {
                    Name = 'aaAeonACUT2BuildRate',
                    DisplayName = 'aaALPHAT2BuildRate',
                    BuffType = 'ACUBUILDRATE',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                        BuildRate = {
                            Add =  bp.NewBuildRate,
                            Mult = 1.0,
                        },
                        MaxHealth = {
                            Add = bp.NewHealth,
                            Mult = 1.0,
                        },
                        Regen = {
                            Add = bp.NewRegenRate,
                            Mult = 1.0,
                        },
                    },
                }
            end
            Buff.ApplyBuff(self, 'aaAeonACUT2BuildRate')
            self:updateBuildRestrictions()
        elseif enh =='GuardianProtocolRemove' then
            local bp = self:GetBlueprint().Economy.BuildRate
            if not bp then return end
            self:AddBuildRestriction(categories.sbab2306)                                     
            if Buff.HasBuff( self, 'aaAeonACUT2BuildRate' ) then
                Buff.RemoveBuff( self, 'aaAeonACUT2BuildRate' )
            end
       --     self:updateBuildRestrictions()

        --Guardian protocol 2
        elseif enh =='GuardianProtocol2' then
          --  local cat = ParseEntityCategory(bp.BuildableCategoryAdds)
          --  self:RemoveBuildRestriction(cat)
            --self:updateBuildRestrictions()
           --self:AddBuildRestriction( categories.AEON * (categories.BUILTBYTIER2ENGINEER + categories.BUILTBYTIER3ENGINEER - - categories.BUILTBYALPHAA1 - categories.SBROT1EXPD - categories.brot2epd)  )  --functionality
          self:RemoveBuildRestriction(categories.sbrot3shpd) 
            self:updateBuildRestrictions()
         if Buffs['aaAeonTorpHealth1'] then                --needed to fix the hp stacking when switching between enhancements
                Buff.RemoveBuff(self, 'aaAeonTorpHealth1')
            end
            if Buffs['aaAeonTorpHealth2'] then
                Buff.RemoveBuff(self, 'aaAeonTorpHealth2')
            end
            if Buffs['aaAeonTorpHealth3'] then
                Buff.RemoveBuff(self, 'aaAeonTorpHealth3')
            end
            if not Buffs['aaAeonACUT3BuildRate'] then     
                BuffBlueprint {
                    Name = 'aaAeonACUT3BuildRate',
                    DisplayName = 'aaALPHAT3BuildRate',
                    BuffType = 'ACUBUILDRATE',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                        BuildRate = {
                            Add =  bp.NewBuildRate,
                            Mult = 1.0,
                        },
                        MaxHealth = {
                            Add = bp.NewHealth,
                            Mult = 1.0,
                        },
                        Regen = {
                            Add = bp.NewRegenRate,
                            Mult = 1.0,
                        },
                    },
                }
            end
            Buff.ApplyBuff(self, 'aaAeonACUT3BuildRate')
        elseif enh =='GuardianProtocol2Remove' then
            local bp = self:GetBlueprint().Economy.BuildRate
            if not bp then return end
            self:AddBuildRestriction(categories.sbab2306)
            self:AddBuildRestriction(categories.sbrot3shpd)
                Buff.RemoveBuff( self, 'aaAeonACUT3BuildRate' )
        --    self:updateBuildRestrictions()

        elseif enh == 'ApocalypticEngineering' then
         if Buffs['aaAeonTorpHealth1'] then                --needed to fix the hp stacking when switching between enhancements
                Buff.RemoveBuff(self, 'aaAeonTorpHealth1')
            end
            if Buffs['aaAeonTorpHealth2'] then
                Buff.RemoveBuff(self, 'aaAeonTorpHealth2')
            end
            if Buffs['aaAeonTorpHealth3'] then
                Buff.RemoveBuff(self, 'aaAeonTorpHealth3')
            end

            if not Buffs['aaAEONACUT4BuildCombat'] then
                BuffBlueprint {
                    Name = 'aaAEONACUT4BuildCombat',
                    DisplayName = 'aaAEONACUT4BuildCombat',
                    BuffType = 'ACUBUILDRATE',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                        MaxHealth = {
                            Add = bp.NewHealth,
                            Mult = 1.0,
                        },
                        Regen = {
                            Add = bp.NewRegenRate,
                            Mult = 1.0,
                        },
                    },
                }
            end
            Buff.ApplyBuff(self, 'aaAEONACUT4BuildCombat')
        elseif enh == 'ApocalypticEngineeringRemove' then
            local bp = self:GetBlueprint().Economy.BuildRate
            if not bp then return end
            self:AddBuildRestriction(categories.sbab2306)
            self:AddBuildRestriction(categories.sbrot3shpd)
            if Buff.HasBuff(self, 'aaAEONACUT4BuildCombat') then
                Buff.RemoveBuff(self, 'aaAEONACUT4BuildCombat')
            end

-- Torpedoes           
        elseif enh == 'TorpedoLauncher' then
          --   if not Buffs['AeonTorpHealth1'] then
            --self:RemoveBuildRestriction( categories.BUILTBYTIER3ENGINEER)           
            self:RemoveBuildRestriction(categories.sbrot1advnavygun)
         if Buffs['aaAeonACUT2BuildRate'] then                --needed to fix the hp stacking when switching between enhancements
                Buff.RemoveBuff(self, 'aaAeonACUT2BuildRate')
            end
            if Buffs['aaAeonACUT3BuildRate'] then
                Buff.RemoveBuff(self, 'aaAeonACUT3BuildRate')
            end
            if Buffs['aaAeonACUT4BuildRate'] then
                Buff.RemoveBuff(self, 'aaAeonACUT4BuildRate')
            end                                   
           
                BuffBlueprint {
                    Name = 'aaAeonTorpHealth1',
                    DisplayName = 'Seaworth Protocol',
                    BuffType = 'ACUBUILDRATE',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                        MaxHealth = {
                            Add = bp.NewHealth,
                            Mult = 1.0,
                        },
                        Regen = {
                            Add = bp.NewRegenRate,
                            Mult = 1.0,
                        },
                    },
                }
         --   end
            Buff.ApplyBuff(self, 'aaAeonTorpHealth1')
           
            local torp = self:GetWeaponByLabel('TorpedoTurrets01')
            self:SetWeaponEnabledByLabel('TorpedoTurrets01', true) 
           -- local antiTorp = self:SetWeaponEnabledByLabel('AntiTorpedo', true)
        elseif enh == 'TorpedoLauncherRemove' then
            if Buff.HasBuff(self, 'aaAeonTorpHealth1') then
                Buff.RemoveBuff(self, 'aaAeonTorpHealth1')
            end
           
            self:SetWeaponEnabledByLabel('TorpedoTurrets01', false)
           -- local antiTorp = self:SetWeaponEnabledByLabel('AntiTorpedo', false)
            self:AddBuildRestriction(categories.sbrot1advnavygun)
       
        elseif enh == 'ImprovedTorpLoader' then --brot1advnavygun'           
            self:RemoveBuildRestriction(categories.sbrot1advnavygun)
            self:updateBuildRestrictions()
            if not Buffs['aaAeonTorpHealth2'] then
                BuffBlueprint {
                    Name = 'aaAeonTorpHealth2',
                    DisplayName = 'aaAeonTorpHealth2',
                    BuffType = 'ACUBUILDRATE',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                        MaxHealth = {
                            Add = bp.NewHealth,
                            Mult = 1.0,
                        },
                        Regen = {
                            Add = bp.NewRegenRate,
                            Mult = 1.0,
                        },
                    },
                }
            end
            Buff.ApplyBuff(self, 'aaAeonTorpHealth2')
            local torp = self:GetWeaponByLabel('TorpedoTurrets01')         
            torp:ChangeRateOfFire(bp.TorpRoF)
            self:updateBuildRestrictions()

        elseif enh == 'ImprovedTorpLoaderRemove' then
            if Buff.HasBuff(self, 'aaAeonTorpHealth2') then
                Buff.RemoveBuff(self, 'aaAeonTorpHealth2')
                local torp = self:GetWeaponByLabel('TorpedoTurrets01')
                torp:ChangeRateOfFire(torp:GetBlueprint().RateOfFire)
            end
            self:AddBuildRestriction(categories.sbrot1advnavygun)
          --  self:updateBuildRestrictions()

        elseif enh == 'AdvancedWarheads' then         
            self:RemoveBuildRestriction(categories.sbrot1advnavygun)
            self:updateBuildRestrictions()
            if not Buffs['aaAeonTorpHealth3'] then
                BuffBlueprint {
                    Name = 'aaAeonTorpHealth3',
                    DisplayName = 'aaAeonTorpHealth3',
                    BuffType = 'ACUBUILDRATE',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                        MaxHealth = {
                            Add = bp.NewHealth,
                            Mult = 1.0,
                        },
                        Regen = {
                            Add = bp.NewRegenRate,
                            Mult = 1.0,
                        },
                    },
                }
            end
            Buff.ApplyBuff(self, 'aaAeonTorpHealth3')
           
            local torp = self:GetWeaponByLabel('TorpedoTurrets01')
            torp:AddDamageMod(bp.TorpDamage)

        elseif enh == 'AdvancedWarheadsRemove' then
            if Buff.HasBuff(self, 'aaAeonTorpHealth3') then
                Buff.RemoveBuff(self, 'aaAeonTorpHealth3')
            end
           
            local torp = self:GetWeaponByLabel('TorpedoTurrets01')
            torp:AddDamageMod(bp.TorpDamage)
            self:AddBuildRestriction(categories.sbrot1advnavygun)
            --self:updateBuildRestrictions()

-- Shielding
           
        elseif enh == 'ShieldBattery4' then
            --self:AddToggleCap('RULEUTC_ShieldToggle')
            self:CreateShield(bp)
            self:SetEnergyMaintenanceConsumptionOverride(bp.MaintenanceConsumptionPerSecondEnergy or 0)
          --  self:SetMaintenanceConsumptionActive()
           
           -- self:SpecialBones()
        elseif enh == 'ShieldBattery4Remove' then
            self:DestroyShield()
          --  self:SetMaintenanceConsumptionInactive()
            self:RemoveToggleCap('RULEUTC_ShieldToggle')

        elseif enh == 'ExpandedShieldBubble4' then
            self:DestroyShield()
            ForkThread(function()
                WaitTicks(1)
                self:CreateShield(bp)
            end)
          --  self:SetEnergyMaintenanceConsumptionOverride(bp.MaintenanceConsumptionPerSecondEnergy or 0)
          --  self:SetMaintenanceConsumptionActive()
        elseif enh == 'ExpandedShieldBubble4Remove' then
            self:DestroyShield()
            RemoveUnitEnhancement(self, 'ExpandedShieldBubble4Remove')
          --  self:SetMaintenanceConsumptionInactive()
        --    self:RemoveToggleCap('RULEUTC_ShieldToggle')
        elseif enh == 'ImprovedShieldBattery4' then
            self:DestroyShield()
            ForkThread(function()
                WaitTicks(1)
                self:CreateShield(bp)
            end)
            self:SetEnergyMaintenanceConsumptionOverride(bp.MaintenanceConsumptionPerSecondEnergy or 0)
            self:SetMaintenanceConsumptionActive()
        elseif enh == 'ImprovedShieldBattery4Remove' then
            self:DestroyShield()
        --    self:SetMaintenanceConsumptionInactive()
         --   self:RemoveToggleCap('RULEUTC_ShieldToggle')

--offense protocol
         elseif enh == 'PhasonBeamCannon4' then
            if not Buffs['AeonBeamHealth4'] then
                BuffBlueprint {
                    Name = 'AeonBeamHealth4',
                    DisplayName = 'AeonOffense4',
                    BuffType = 'AeonBeamHealth',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                    },
                }
            end
            Buff.ApplyBuff(self, 'AeonBeamHealth4')

           -- self:SetWeaponEnabledByLabel('PhasonBeam01', true)
            local MainGun1 = self:GetWeaponByLabel('MainGun1')
            local MainGun2 = self:GetWeaponByLabel('MainGun2')
            local MainGun3 = self:GetWeaponByLabel('MainGun3')
            local MainGun4 = self:GetWeaponByLabel('MainGun4')
            local MainGun5 = self:GetWeaponByLabel('MainGun5')
            local MainGun6 = self:GetWeaponByLabel('MainGun6')
            local bigGun = self:GetWeaponByLabel('bigGun')
            MainGun1:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun1:AddDamageMod(bp.OblivionPDDamage)
            MainGun2:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun2:AddDamageMod(bp.OblivionPDDamage)
            MainGun3:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun3:AddDamageMod(bp.OblivionPDDamage)
            MainGun4:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun4:AddDamageMod(bp.OblivionPDDamage)
            MainGun5:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun5:AddDamageMod(bp.OblivionPDDamage)
            MainGun6:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun6:AddDamageMod(bp.OblivionPDDamage)
            bigGun:ChangeRateOfFire(bp.bigGunRoF)
            bigGun:AddDamageMod(bp.bigGunDamage)
        elseif enh == 'PhasonBeamCannon4Remove' then
            if Buff.HasBuff(self, 'AeonBeamHealth4') then
                Buff.RemoveBuff(self, 'AeonBeamHealth4')
            end           
            local MainGun1 = self:GetWeaponByLabel('MainGun1')
            local MainGun2 = self:GetWeaponByLabel('MainGun2')
            local MainGun3 = self:GetWeaponByLabel('MainGun3')
            local MainGun4 = self:GetWeaponByLabel('MainGun4')
            local MainGun5 = self:GetWeaponByLabel('MainGun5')
            local MainGun6 = self:GetWeaponByLabel('MainGun6')
            local bigGun = self:GetWeaponByLabel('bigGun')
            MainGun1:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun1:AddDamageMod(bp.OblivionPDDamage)
            MainGun2:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun2:AddDamageMod(bp.OblivionPDDamage)
            MainGun3:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun3:AddDamageMod(bp.OblivionPDDamage)
            MainGun4:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun4:AddDamageMod(bp.OblivionPDDamage)
            MainGun5:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun5:AddDamageMod(bp.OblivionPDDamage)
            MainGun6:ChangeRateOfFire(bp.OblivionPDRoF)
            MainGun6:AddDamageMod(bp.OblivionPDDamage)
            bigGun:ChangeRateOfFire(bp.bigGunRoF)
            bigGun:AddDamageMod(bp.bigGunDamage)
  -- Phasors
        elseif enh == 'DualMiasmaArtillery4' then
            if not Buffs['AeonArtilleryHealth4'] then
                BuffBlueprint {
                    Name = 'AeonArtilleryHealth4',
                    DisplayName = 'AeonArtilleryHealth4',
                    BuffType = 'AeonOffense4',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                    },
                }
            end
            Buff.ApplyBuff(self, 'AeonArtilleryHealth4')

            self:SetWeaponEnabledByLabel('BeamR', true)
            self:SetWeaponEnabledByLabel('BeamM', true)

        elseif enh == 'DualMiasmaArtillery4Remove' then
            if Buff.HasBuff(self, 'AeonArtilleryHealth4') then
                Buff.RemoveBuff(self, 'AeonArtilleryHealth4')
            end

            self:SetWeaponEnabledByLabel('BeamR', false)
            self:SetWeaponEnabledByLabel('BeamM', false)
    --overcharge
        elseif enh == 'OverchargeAmplifierA' then
            if not Buffs['SeraphimCombatHealthA'] then
                BuffBlueprint {
                    Name = 'SeraphimCombatHealthA',
                    DisplayName = 'SeraphimCombatHealthA',
                    BuffType = 'AeonOffense4',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                    },
                }
            end
            local OverCharge = self:GetWeaponByLabel('OverCharge')
           -- OverCharge:ChangeMaxRadius(bp.OverChargeMaxRange)
            OverCharge:ChangeRateOfFire(bp.OverChargeRoF)  --look under OnPaused on top in weapons script, this didn't change anything

           Buff.ApplyBuff(self, 'SeraphimCombatHealthA')
        elseif enh == 'OverchargeAmplifierARemove' then
            if Buff.HasBuff(self, 'SeraphimCombatHealthA') then
                Buff.RemoveBuff(self, 'SeraphimCombatHealthA')
            end

--Scavenger protocol
        elseif enh =='ScavengerProtocol' then   
          self:RemoveBuildRestriction(categories.suac1201u) 
            self:updateBuildRestrictions()

            if Buffs['SummonerProtocol'] then               
                Buff.RemoveBuff(self, 'SeraphimACURegenAura')
            end

            if not Buffs['SeraphimACURegenAura'] then
                BuffBlueprint {
                    Name = 'SeraphimACURegenAura',
                    DisplayName = 'SeraphimACURegenAura',
                    BuffType = 'COMMANDERAURA_RegenAura',
                    Stacks = 'REPLACE',
                    Duration = 5,
                    Affects = {
                        Regen = {
                            Add = 0,
                            Mult = bp.RegenPerSecond,
                            Ceil = bp.RegenCeiling,
                        },
                        MaxHealth = {
                            Add = 0,
                            Mult = bp.MaxHealthFactor,
                            DoNoFill = true,
                        }
                    },
                }
            end

          --  self:AddBuildRestriction( categories.AEON * (categories.BUILTBYTIER2ENGINEER + categories.BUILTBYTIER3ENGINEER - categories.SBROT1EXPD) )
            if not Buffs['AeonScavenge'] then
                BuffBlueprint {
                    Name = 'AeonScavenge',
                    DisplayName = 'AeonScavenge',
                    BuffType = 'AeonScavenge',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                        BuildRate = {
                            Add =  bp.NewBuildRate,
                            Mult = 1.0,
                        },
                        MaxHealth = {
                            Add = bp.NewHealth,
                            Mult = 1.0,
                        },
                        Regen = {
                            Add = bp.NewRegenRate,
                            Mult = 1.0,
                        },
                    },
                }
            end

            -- Remove existing threads, then re-apply
            if self.RegenFieldFXBag then
                for k, v in self.RegenFieldFXBag do
                    v:Destroy()
                end
                self.RegenFieldFXBag = {}
            end

            if self.RegenThreadHandler then
                KillThread(self.RegenThreadHandler)
                self.RegenThreadHandler = nil
            end
            self.RegenThreadHandler = self:ForkThread(self.RegenBuffThread, enh)
            table.insert(self.RegenFieldFXBag, CreateAttachedEmitter(self, 'Attachpoint_Lrg_04', self:GetArmy(), '/effects/emitters/seraphim_regenerative_aura_01_emit.bp'))

            Buff.ApplyBuff(self, 'AeonScavenge')
            self:updateBuildRestrictions()
        elseif enh =='ScavengerProtocolRemove' then
            local bp = self:GetBlueprint().Economy.BuildRate
            if not bp then return end
            self:AddBuildRestriction(categories.suac1201u)                                     
            if Buff.HasBuff( self, 'AeonScavenge' ) then
                Buff.RemoveBuff( self, 'AeonScavenge' )
            end
       --     self:updateBuildRestrictions()

        --Sky tracker
        elseif enh =='SkyTrackerProtocol' then
          --  local cat = ParseEntityCategory(bp.BuildableCategoryAdds)
          --  self:RemoveBuildRestriction(cat)
            --self:updateBuildRestrictions()
           --self:AddBuildRestriction( categories.AEON * (categories.BUILTBYTIER2ENGINEER + categories.BUILTBYTIER3ENGINEER - - categories.BUILTBYALPHAA1 - categories.SBROT1EXPD - categories.brot2epd)  )  --functionality
          self:RemoveBuildRestriction(categories.sbrot3shpdu) 
            self:updateBuildRestrictions()
            if not Buffs['AeonAir'] then     
                BuffBlueprint {
                    Name = 'AeonAir',
                    DisplayName = 'AeonAir',
                    BuffType = 'AeonScavenge',
                    Stacks = 'STACKS',
                    Duration = -1,
                    Affects = {
                    },
                }
            end
            Buff.ApplyBuff(self, 'AeonAir')

            self:SetWeaponEnabledByLabel('laserblue3', true)
            self:SetWeaponEnabledByLabel('laserblue5', true)
        elseif enh =='SkyTrackerProtocolRemove' then
            self:AddBuildRestriction(categories.sbrot3shpdu)
            self:SetWeaponEnabledByLabel('laserblue3', false)
            self:SetWeaponEnabledByLabel('laserblue5', false)
                Buff.RemoveBuff( self, 'AeonAir' )
            self:updateBuildRestrictions()

        elseif enh == 'SurvivalProtocol' then
--regen 2         -- Build buff tables
            if not Buffs['SeraphimACUAdvancedRegenAura'] then
                BuffBlueprint {
                    Name = 'SeraphimACUAdvancedRegenAura',
                    DisplayName = 'SeraphimACUAdvancedRegenAura',
                    BuffType = 'COMMANDERAURA_AdvancedRegenAura',
                    Stacks = 'REPLACE',
                    Duration = 5,
                    Affects = {
                        Regen = {
                            Add = 0,
                            Mult = bp.RegenPerSecond,
                            Ceil = bp.RegenCeiling,
                        },
                        MaxHealth = {
                            Add = 0,
                            Mult = bp.MaxHealthFactor,
                            DoNoFill = true,
                        }
                    },
                }
            end

             -- Remove existing threads, then re-apply
            if self.RegenFieldFXBag then
                for k, v in self.RegenFieldFXBag do
                    v:Destroy()
                end
                self.RegenFieldFXBag = {}
            end
           
            if self.RegenThreadHandler then
                KillThread(self.RegenThreadHandler)
                self.RegenThreadHandler = nil
            end
            self.RegenThreadHandler = self:ForkThread(self.RegenBuffThread, enh)
            table.insert(self.RegenFieldFXBag, CreateAttachedEmitter(self, 'Attachpoint_Lrg_04', self:GetArmy(), '/effects/emitters/seraphim_regenerative_aura_01_emit.bp'))


        elseif enh == 'SurvivalProtocolRemove' then
            local bp = self:GetBlueprint().Economy.BuildRate
            if not bp then return end
            self:AddBuildRestriction(categories.sbab2306)
            self:AddBuildRestriction(categories.sbrot3shpd)
            if Buff.HasBuff(self, 'SeraphimACUAdvancedRegenAura') then
                Buff.RemoveBuff(self, 'SeraphimACUAdvancedRegenAura')
            end
--Summoner protocol
        elseif enh =='SummonerProtocol' then   
          self:RemoveBuildRestriction(categories.suac1201u) 
            self:updateBuildRestrictions()

            if Buffs['ScavengerProtocol'] then                --needed to fix the hp stacking when switching between enhancements
                Buff.RemoveBuff(self, 'SeraphimACURegenAura')
            end
            if Buffs['SurvivalProtocol'] then               
                Buff.RemoveBuff(self, 'SeraphimACUAdvancedRegenAura')
            end

            if not Buffs['SeraphimACURegenAura'] then
                BuffBlueprint {
                    Name = 'SeraphimACURegenAura',
                    DisplayName = 'SeraphimACURegenAura',
                    BuffType = 'COMMANDERAURA_RegenAura',
                    Stacks = 'REPLACE',
                    Duration = 5,
                    Affects = {
                        Regen = {
                            Add = 0,
                            Mult = bp.RegenPerSecond,
                            Ceil = bp.RegenCeiling,
                        },
                        MaxHealth = {
                            Add = 0,
                            Mult = bp.MaxHealthFactor,
                            DoNoFill = true,
                        }
                    },
                }
            end

            -- Remove existing threads, then re-apply
            if self.RegenFieldFXBag then
                for k, v in self.RegenFieldFXBag do
                    v:Destroy()
                end
                self.RegenFieldFXBag = {}
            end

            if self.RegenThreadHandler then
                KillThread(self.RegenThreadHandler)
                self.RegenThreadHandler = nil
            end
            self.RegenThreadHandler = self:ForkThread(self.RegenBuffThread, enh)


        self:DroneSetup2()  --calling my own DroneSetup code, copy/paste of the existing one, the entire function, in which i use my DroneData2 table instead of DroneData, that has 4 drones in it instead of 2

        elseif enh =='SummonerProtocolRemove' then
            local bp = self:GetBlueprint().Economy.BuildRate
            if not bp then return end
            self:AddBuildRestriction(categories.suac1201u)                                     
            if Buff.HasBuff( self, 'SummonerProtocol' ) then
                Buff.RemoveBuff( self, 'SummonerProtocol' )
            end
       --     self:updateBuildRestrictions()



        end

          -- Remove prerequisites
        if not removal then
            if bp.RemoveEnhancements then
                for k, v in bp.RemoveEnhancements do               
                    if string.sub(v, -6) ~= 'Remove' and v ~= string.sub(enh, 0, -7) then
                        self:CreateEnhancement(v .. 'Remove', true)
                    end
                end
            end
        end   


    end,

    -- Override air destruction effects so we can do something custom here
    CreateUnitAirDestructionEffects = function( self, scale )
        self:ForkThread(self.AirDestructionEffectsThread, self )
    end,

    AirDestructionEffectsThread = function( self )
        local numExplosions = math.floor( table.getn( self.AirDestructionEffectBones ) * 1.5 )
        for i = 0, numExplosions do
            explosion.CreateDefaultHitExplosionAtBone( self, self.AirDestructionEffectBones[util.GetRandomInt( 1, numExplosions )], 0.5 )
            WaitSeconds( util.GetRandomFloat( 0.2, 0.9 ))
        end
    end,

    OnKilledUnit = function(self, unitKilled, massKilled)
        -- add the mass of this kill to our mass counter
        MassKilled = MassKilled + massKilled
        local army = self:GetArmy()
        -- if we killed over 1,000,000 mass then...
       
        if MassKilled > 40500 then
            List = GetArmyBrain(army):GetListOfUnits(categories.ALPHA, false, true)
                for k, unit in List do     
                    if (unit:GetUnitId() == 'alphaa5') then return
                    else
                  --      BroadcastMSG("--- 'ALPHA unit final form achieved!!!!' --- ", 3);
                    --do stuff here like creating new unit etc.
                    self:Destroy();
                    local BP = self:GetBlueprint();
                        BP.Wreckage = nil;

                    -- Spawn thesecondary unit
                    --WaitSeconds(4)           
                    local position = self:GetPosition()
                    local spiritUnit = CreateUnitHPR('ALPHAA5', self:GetArmy(), position[1], position[2], position[3], 0, 9.3, 0)
                    end
                end
        end
        -- call the original function, so we don't break it.
        AAirUnit.OnKilledUnit(self, unitKilled, massKilled)
    end,



OnKilled = function(self, instigator, damagetype, overkillRatio)
        AAirUnit.OnKilled(self, instigator, damagetype, overkillRatio)
        self:CreatTheEffectsDeath()
-----------------------------------
         if self.gettingBuilt == false then
            -- Kill our heartbeat thread
            KillThread(self.HeartBeatThread)
            -- Clean up any in-progress construction
            ChangeState(self, self.DeadState)
            -- Immediately kill existing drones
            if next(self.DroneTable) then
                for name, drone in self.DroneTable do
                    IssueClearCommands({drone})
                    IssueKillSelf({drone})
                end
            end
            if self.spoof == true then
                self.landChildUnit:Destroy()
            end
        end
--------------------------------------------------------------------------
    end,

OnDestroy = function(self)
        AAirUnit.OnDestroy(self)

        -- Don't make the energy being if not built
        if self:GetFractionComplete() ~= 1 then return end
        local army = self:GetArmy()              --dont spawn if we are evolving
            List = GetArmyBrain(army):GetListOfUnits(categories.ALPHA, false, true)
                for k, unit in List do     
                    if not (unit:GetUnitId() == 'alphaa5') then     
                        -- Spawn the nuke effect end energy beings
                        local position = self:GetPosition()
                        local spiritUnit2 = CreateUnitHPR('UEL0001', self:GetArmy(), position[1], position[2], position[3], 0, 0, 0)
                            if (spiritUnit2 != nil) then
                            spiritUnit2:Kill();
                            end
                    else
                    end
                end
    end,

    CreatTheEffectsDeath = function(self)
        local army =  self:GetArmy()
        for k, v in EffectTemplate['SZthuthaamArtilleryHit'] do
            self.Trash:Add(CreateAttachedEmitter(self, 'Turret_Front01', army, v):ScaleEmitter(3.95))
        end
        for k, v in TMEffectTemplate['AeonUnitDeathRing03'] do
            self.Trash:Add(CreateAttachedEmitter(self, 'Turret_Front01', army, v):ScaleEmitter(3.95))
        end
        for k, v in TMEffectTemplate['UEFDeath01'] do
            self.Trash:Add(CreateAttachedEmitter(self, 'Turret_Front01', army, v):ScaleEmitter(3.25))
        end
    end,

-----------------------
       LambdaEmitter = function(self)
        -- Are we dead yet, if not then wait 0.5 second
        if not self:IsDead() then
            WaitSeconds(0.5)
            -- Are we dead yet, if not spawn lambdaEmitter
            if not self:IsDead() then

                -- Gets the platforms current orientation
                local platOrient = self:GetOrientation()
               
                -- Gets the current position of the platform in the game world
                local location = self:GetPosition('Turret_Front01')

                -- Creates our lambdaEmitter over the platform with a randomly generated Orientation
                local lambdaEmitter = CreateUnit('bsb0005', self:GetArmy(), location[1], location[2], location[3], platOrient[1], platOrient[2], platOrient[3], platOrient[4], 'Air')

                -- Adds the newly created lambdaEmitter to the parent platforms lambdaEmitter table
                table.insert (self.lambdaEmitterTable, lambdaEmitter)
               
                lambdaEmitter:AttachTo(self, 'Wing_Right')

                 local lambdaEmitter1 = CreateUnit('bsb0005', self:GetArmy(), location[1], location[2], location[3], platOrient[1], platOrient[2], platOrient[3], platOrient[4], 'Air')

                -- Adds the newly created lambdaEmitter to the parent platforms lambdaEmitter table
                table.insert (self.lambdaEmitterTable, lambdaEmitter1)
               
                lambdaEmitter1:AttachTo(self, 'Wing_Left')

                 local lambdaEmitter2 = CreateUnit('bsb0005', self:GetArmy(), location[1], location[2], location[3], platOrient[1], platOrient[2], platOrient[3], platOrient[4], 'Air')

                -- Adds the newly created lambdaEmitter to the parent platforms lambdaEmitter table
                table.insert (self.lambdaEmitterTable, lambdaEmitter2)
               
                lambdaEmitter2:AttachTo(self, 'Turret_Front') 

                local lambdaEmitter3 = CreateUnit('bsb0005', self:GetArmy(), location[1], location[2], location[3], platOrient[1], platOrient[2], platOrient[3], platOrient[4], 'Air')

                -- Adds the newly created lambdaEmitter to the parent platforms lambdaEmitter table
                table.insert (self.lambdaEmitterTable, lambdaEmitter3)
               
                lambdaEmitter3:AttachTo(self, 'Turret_Front01')

                -- Sets the platform unit as the lambdaEmitter parent
                lambdaEmitter:SetParent(self, 'xaa9904')
                lambdaEmitter:SetCreator(self)
                self.Trash:Add(lambdaEmitter)
            end
        end
    end,

    OnScriptBitSet = function(self, bit)
        AAirUnit.OnScriptBitSet(self, bit)
        local army =  self:GetArmy()
        if bit == 0 then
        self:SetMaintenanceConsumptionActive()
        self:ForkThread(self.LambdaEmitter)
        end
    end,
   
    OnScriptBitClear = function(self, bit)
        AAirUnit.OnScriptBitClear(self, bit)
        if bit == 0 then
        self:ForkThread(self.KillLambdaEmitter)
        self:SetMaintenanceConsumptionInactive()
        end
    end,

    KillLambdaEmitter = function(self, instigator, type, overkillRatio)
        -- Small bit of table manipulation to sort thru all of the avalible rebulder bots and remove them after the platform is dead
        if table.getn({self.lambdaEmitterTable}) > 0 then
            for k, v in self.lambdaEmitterTable do
                IssueClearCommands({self.lambdaEmitterTable[k]})
                IssueKillSelf({self.lambdaEmitterTable[k]})
            end
        end
    end,

Check out my 2 maps: "Survival_Mayhem&BO_3d_v1" "Survival_Mayhem&BO_3d_RPG"
as well as my mod: "Survival Mayhem&BO balance"
-- let me know of any bugs or issues regarding those 3.
DDDX
Avatar-of-War
 
Posts: 170
Joined: 21 Mar 2016, 16:13
Has liked: 18 times
Been liked: 16 times
FAF User Name: DDDX

Re: Variable drones number based on enhancement

Postby DDDX » 03 Nov 2018, 10:07

sorry, did not fit in the 60000 symbols limit

Code: Select all
------------------------------------------
-- Initial drone setup - loads globals, DroneData table, and creates drones
    DroneSetup = function(self)
        -- Drone handle table, used to issue orders to all drones at once
        self.DroneTable = {}
       
        -- Drone construction globals
        self.BuildingDrone = false
        self.ControlRange = self:GetBlueprint().AI.DroneControlRange or 70
        self.ReturnRange = self:GetBlueprint().AI.DroneReturnRange or (ControlRange / 2)
        self.AssistRange = self.ControlRange + 10
        self.AirMonitorRange = self:GetBlueprint().AI.AirMonitorRange or (self.AssistRange / 2)
        self.HeartBeatInterval = self:GetBlueprint().AI.AssistHeartbeatInterval or 1

        self.DroneData = table.deepcopy(self:GetBlueprint().DroneData)
       
        -- Load other data from drone BP and spawn drones
        for droneName, droneData in self.DroneData do
            -- Set drone name variable
            if not droneData.Name then
                droneData.Name = droneName
            end
            droneData.Blueprint = table.deepcopy(GetUnitBlueprintByName(droneData.UnitID))
            droneData.Economy = droneData.Blueprint.Economy
            droneData.BuildProgress = 1

            -- Create this drone
            self:ForkThread(self.CreateDrone, droneName)
        end
           
        -- Assist/monitor heartbeat thread
        self.HeartBeatThread = self:ForkThread(self.AssistHeartBeat)
       
        -- Begin drone maintenance monitoring
        ChangeState(self, self.DroneMaintenanceState)
    end,
   
    -- Initial drone setup - loads globals, DroneData table, and creates drones
    DroneSetup2 = function(self)
        -- Drone handle table, used to issue orders to all drones at once
        self.DroneTable = {}
       
        -- Drone construction globals
        self.BuildingDrone = false
        self.ControlRange = self:GetBlueprint().AI.DroneControlRange or 70
        self.ReturnRange = self:GetBlueprint().AI.DroneReturnRange or (ControlRange / 2)
        self.AssistRange = self.ControlRange + 10
        self.AirMonitorRange = self:GetBlueprint().AI.AirMonitorRange or (self.AssistRange / 2)
        self.HeartBeatInterval = self:GetBlueprint().AI.AssistHeartbeatInterval or 1

        self.DroneData = table.deepcopy(self:GetBlueprint().DroneData2)
       
        -- Load other data from drone BP and spawn drones
        for droneName, droneData in self.DroneData do
            -- Set drone name variable
            if not droneData.Name then
                droneData.Name = droneName
            end
            droneData.Blueprint = table.deepcopy(GetUnitBlueprintByName(droneData.UnitID))
            droneData.Economy = droneData.Blueprint.Economy
            droneData.BuildProgress = 1

            -- Create this drone
            self:ForkThread(self.CreateDrone, droneName)
        end
           
        -- Assist/monitor heartbeat thread
        self.HeartBeatThread = self:ForkThread(self.AssistHeartBeat)
       
        -- Begin drone maintenance monitoring
        ChangeState(self, self.DroneMaintenanceState)
    end,
    -- Creates specified drone from its entry in DroneData and creates handles
    CreateDrone = function(self, droneName)
        if not self:IsDead() and not self.DroneTable[droneName] and not self.DroneData[droneName].Active then
            if not self:IsValidBone(self.DroneData[droneName].Attachpoint) then
                error("*ERROR: Attachpoint '" .. self.DroneData[droneName].Attachpoint .. "' not a valid bone!", 2)
                return
            end
            local location = self:GetPosition(self.DroneData[droneName].Attachpoint)
            local pos = Random(0,30)
            local pos2 = Random(-10,10)
            local newdrone = CreateUnitHPR(self.DroneData[droneName].UnitID, self:GetArmy(), location[1] + pos2, location[2], location[3] + pos, 0, 0, 0)
            local army =  self:GetArmy()
                    for k, v in BlackOpsEffectTemplate['LambdaRedirector'] do
                        self.Trash:Add(CreateAttachedEmitter(self, 'Attachpoint_Lrg_01', army, v):ScaleEmitter(4.2))
                    end
            newdrone:SetParent(self, self.DroneData[droneName].Name)
            newdrone:SetCreator(self)
            self.DroneTable[droneName] = newdrone
            self.DroneData[droneName].Active = newdrone
            self.DroneData[droneName].Docked = false
            self.DroneData[droneName].Damaged = false
            self.DroneData[droneName].BuildProgress = 1
            self.Trash:Add(newdrone)
            self:RequestRefreshUI()

        end
    end,
   
    -- Clears all handles and active DroneData variables for the calling drone.
    NotifyOfDroneDeath = function(self,droneName)
        self.DroneTable[droneName] = nil
        self.DroneData[droneName].Active = false
        self.DroneData[droneName].Docked = false
        self.DroneData[droneName].Damaged = false
        self.DroneData[droneName].BuildProgress = 0
    end,

    DroneMaintenanceState = State {
        Main = function(self)
            self.DroneMaintenance = true           
            -- Resume any interrupted drone rebuilds
            if self.BuildingDrone then
                ChangeState(self, self.DroneRebuildingState)
            end           
            -- Check for dead or damaged drones
            while self and not self:IsDead() and not self.BuildingDrone do
                for droneName, droneData in self.DroneData do
                    if not droneData.Active or (droneData.Active and droneData.Damaged and droneData.Docked) then
                        self.BuildingDrone = droneName
                        ChangeState(self, self.DroneRebuildingState)
                    end
                end
                WaitTicks(2)
            end
        end,

        OnPaused = function(self)
            ChangeState(self, self.PausedState)
        end,
    },
   
    -- Active construction/repair state - consumes resources and advances progress
    DroneRebuildingState = State {
        Main = function(self)
            -- Flag as repair if drone is alive and damaged
            local isRepair = self.DroneData[self.BuildingDrone].Active and self.DroneData[self.BuildingDrone].Damaged
            -- Calculate build time from buildrate
            local buildTimeSeconds = self.DroneData[self.BuildingDrone].Economy.BuildTime / self.BuildRate
            -- Enable econ consumption
            self:EnableResourceConsumption(self.DroneData[self.BuildingDrone].Economy)
           
            -- Begin or resume construction if not repair
            if not isRepair then
                -- Set progress bar/variable to 0 for fresh drone construction
                if not self.DroneData[self.BuildingDrone].BuildProgress then
                    self:SetWorkProgress(0.01)
                end
                -- Construction runs until buildprogress >= 1
                while self and not self:IsDead()
                and self.DroneData[self.BuildingDrone].BuildProgress < 1 do
                    WaitTicks(1)
                    local tickprogress = (self:GetResourceConsumed() * 0.1) / buildTimeSeconds
                    self.DroneData[self.BuildingDrone].BuildProgress = self.DroneData[self.BuildingDrone].BuildProgress + tickprogress
                    self:SetWorkProgress(self.DroneData[self.BuildingDrone].BuildProgress)
                end
                self:CreateDrone(self.BuildingDrone)
            elseif isRepair then
                local repairingDrone = self.DroneData[self.BuildingDrone].Active
                local maxhealth = repairingDrone:GetMaxHealth()
                -- Repair runs while drone is alive, damaged, and docked
                while self and not self:IsDead()
                and self.DroneData[self.BuildingDrone].Damaged
                and self.DroneData[self.BuildingDrone].Docked
                and repairingDrone and not repairingDrone:IsDead() do
                    WaitTicks(1)
                    local restorehealth = ((self:GetResourceConsumed() * 0.1) / buildTimeSeconds) * maxhealth
                    repairingDrone:AdjustHealth(self, restorehealth)
                    -- Repair progress = drone health percent, and the progressbar reflects this
                    local totalprogress = repairingDrone:GetHealth() / maxhealth
                    self:SetWorkProgress(totalprogress)
                    if self.DroneData[self.BuildingDrone] and totalprogress >= 1 then
                        self.DroneData[self.BuildingDrone].Damaged = false
                    end
                end
            end
            -- Return to Maintenance State to check/wait for other jobs
            self:CleanupDroneMaintenance(self.BuildingDrone)
            ChangeState(self, self.DroneMaintenanceState)
        end,
       
        OnPaused = function(self)
            ChangeState(self, self.PausedState)
        end,
    },
   
    -- Paused state, econ and construction progress halted
    PausedState = State {
        Main = function(self)
            self:DisableResourceConsumption()
            self.DroneMaintenance = false
        end,

        OnUnpaused = function(self)
            ChangeState(self, self.DroneMaintenanceState)
        end,       
    },
   
    -- Set on unit death, ends production and consumption immediately
    DeadState = State {
        Main = function(self)
            if self.gettingBuilt == false then
                self:CleanupDroneMaintenance(nil, true)
            end
        end,       
    },

    -- Enables economy drain
    EnableResourceConsumption = function(self, econdata)
        local energy_rate = econdata.BuildCostEnergy / (econdata.BuildTime / self.BuildRate)
        local mass_rate = econdata.BuildCostMass / (econdata.BuildTime / self.BuildRate)
        self:SetConsumptionPerSecondEnergy(energy_rate)
        self:SetConsumptionPerSecondMass(mass_rate)
        self:SetConsumptionActive(true)
    end,

    -- Disables economy drain
    DisableResourceConsumption = function(self)
        self:SetConsumptionPerSecondEnergy(0)
        self:SetConsumptionPerSecondMass(0)
        self:SetConsumptionActive(false)
    end,
   
    -- Resets resume/progress data, clears effects
    -- Used to clean up finished construction and repair, and to interrupt repairs when undocking
    CleanupDroneMaintenance = function(self, droneName, deadState)
        if deadState or (droneName and droneName == self.BuildingDrone) then
            self:SetWorkProgress(0)
            self.BuildingDrone = false
            self:DisableResourceConsumption()
        end
    end,
   
    -- Manages drone assistance and firestate propagation
    AssistHeartBeat = function(self)
        local SuspendAssist = 0
        local LastFireState
        local LastDroneTarget
        -- The Goliath's current weapon target is now used for better, earlier drone deployment
        -- Best results achieved so far have been with the missile launcher, due to range
        local TargetWeapon = self:GetWeaponByLabel('MainGun')
       
        while not self:IsDead() do
            -- Refresh current firestate and check for holdfire
            local MyFireState = self:GetFireState()
            local HoldFire = MyFireState == 1
            -- De-blip our weapon target, nil MyTarget if none
            local TargetBlip = TargetWeapon:GetCurrentTarget()
            if TargetBlip ~= nil then
                self.MyTarget = self:GetRealTarget(TargetBlip)
            else
                self.MyTarget = nil
            end
           
            -- Propagate the Goliath's fire state to the drones, to keep them from retaliating when the Goliath is on hold-fire
            -- This also allows you to set both drones to target-ground, although I'm not sure how that'd be useful
            if LastFireState ~= MyFireState then
                LastFireState = MyFireState
                self:SetDroneFirestate(MyFireState)
            end

            if self.DroneAssist and not HoldFire and SuspendAssist <= 0 then
                local NewDroneTarget
               
                local GunshipTarget = self:SearchForGunshipTarget(self.AirMonitorRange)
                if GunshipTarget and not GunshipTarget:IsDead() then
                    if GunshipTarget ~= LastDroneTarget then
                        NewDroneTarget = GunshipTarget
                    end
                elseif self.MyAttacker ~= nil and not self.MyAttacker:IsDead() and self:IsTargetInRange(self.MyAttacker) then
                    if self.MyAttacker ~= LastDroneTarget then
                        NewDroneTarget = self.MyAttacker
                    end
                -- If our previous attacker is no longer valid, clear MyAttacker to re-enable the OnDamage check
                elseif self.MyAttacker ~= nil then
                    self.MyAttacker = nil
                end
               
                -- Assign chosen target, if valid
                if NewDroneTarget and self:IsValidDroneTarget(NewDroneTarget) then
                    if NewDroneTarget == GunshipTarget then
                        -- Suspend the assist targeting for 7 heartbeats if we have a gunship target, to keep them at top priority
                        SuspendAssist = 7
                    end
                    LastDroneTarget = NewDroneTarget
                    self:AssignDroneTarget(NewDroneTarget)
                -- Otherwise re-check our existing target:
                else
                    if LastDroneTarget and self:IsValidDroneTarget(LastDroneTarget)
                    and self:IsTargetInRange(LastDroneTarget) then
                        -- Dispatch any docked (usually newly-built) drones, if it's still valid
                        if self:GetDronesDocked() then
                            self:AssignDroneTarget(LastDroneTarget)
                        end
                    else
                        -- Clear last target if no longer valid, forcing re-acquisition on the next beat
                        LastDroneTarget = nil
                    end
                end
               
            -- Otherwise, tick down the assistance suspension timer (if set)
            elseif SuspendAssist > 0 then
                SuspendAssist = SuspendAssist - 1
            end
           
            WaitSeconds(self.HeartBeatInterval)
        end
    end,
           
    -- Recalls all drones to the carrier at 2x speed under temp command lockdown
    RecallDrones = function(self)
        if next(self.DroneTable) then
            for id, drone in self.DroneTable do
                drone:DroneRecall()
            end
        end       
    end,
   
    -- Issues an attack order for all drones
    AssignDroneTarget = function(self, dronetarget)
        if next(self.DroneTable) then
            for id, drone in self.DroneTable do
                if drone.AwayFromCarrier == false then
                    local targetblip = dronetarget:GetBlip(self:GetArmy())
                    if targetblip ~= nil then
                        IssueClearCommands({drone})
                        IssueAttack({drone}, targetblip)
                    end
                end
            end
        end
    end,
   
    -- Sets a firestate for all drones
    SetDroneFirestate = function(self, firestate)
        if next(self.DroneTable) then
            for id, drone in self.DroneTable do
                if drone and not drone:IsDead() then
                    drone:SetFireState(firestate)
                end
            end
        end
    end,
   
    -- Checks whether any drones are docked.  Used by AssistHeartBeat.
    -- Returns a table of dronenames that are currently docked, or false if none
    GetDronesDocked = function(self)
        local docked = {}
        if next(self.DroneTable) then
            for id, drone in self.DroneTable do
                if drone and not drone:IsDead() and self.DroneData[id].Docked then
                    table.insert(docked, id)
                end
            end
        end
        if next(docked) then
            return docked
        else
            return false
        end
    end,

    -- Returns a hostile gunship/transport in range for drone targeting, or nil if none
    SearchForGunshipTarget = function(self, radius)
        local targetindex, target
        local units = self:GetAIBrain():GetUnitsAroundPoint(categories.ALLUNITS - (categories.UNTARGETABLE), self:GetPosition(), radius, 'Enemy')
        if next(units) then
            targetindex, target = next(units)
        end
        return target
    end,
   
    -- De-blip a weapon target - stolen from the GC tractorclaw script
    GetRealTarget = function(self, target)
        if target and not IsUnit(target) then
            local unitTarget = target:GetSource()
            local unitPos = unitTarget:GetPosition()
            local reconPos = target:GetPosition()
            local dist = VDist2(unitPos[1], unitPos[3], reconPos[1], reconPos[3])
            if dist < 5 then
                return unitTarget
            end
        end
        return target     
    end,
   
    -- Runs a potential target through filters to insure that drones can attack it; checks are as simple and efficient as possible
    IsValidDroneTarget = function(self, target)
        local ivdt
        if target ~= nil
        and target.Dead ~= nil
        and not target:IsDead()
        and IsEnemy(self:GetArmy(), target:GetArmy())
        and not EntityCategoryContains(categories.UNTARGETABLE, target)
        and target:GetCurrentLayer() ~= 'Sub'
        and target:GetBlip(self:GetArmy()) ~= nil then
            ivdt = true
        end
        return ivdt
    end,
   
    -- Insures that potential retaliation targets are within drone control range
    IsTargetInRange = function(self, target)
        local tpos = target:GetPosition()
        local mpos = self:GetPosition()
        local dist = VDist2(mpos[1], mpos[3], tpos[1], tpos[3])
        local itir
        if dist <= self.AssistRange then
            itir = true
        end
        return itir
    end,

       OnScriptBitClear = function(self, bit)
        AAirUnit.OnScriptBitClear(self, bit)
        if bit == 3 then
            self.spoof = true
            self:SetMaintenanceConsumptionActive()
            self:EnableUnitIntel('Radar')
            self:EnableUnitIntel('RadarStealth')
            self:ForkThread(self.SpoofingThread)
        end
    end,
   
    OnScriptBitSet = function(self, bit)
        AAirUnit.OnScriptBitSet(self, bit)
        if bit == 3 then
            self.spoof = false
            self:SetMaintenanceConsumptionInactive()
            self:DisableUnitIntel('Radar')
            self:DisableUnitIntel('RadarStealth')
        end
    end,


    SpoofingThread = function(self)
        local position = self:GetPosition()

        while self.spoof == true do
            local pos = Random(-70,70)
            self.landChildUnit = CreateUnitHPR('BEL9010', self:GetArmy(), position[1] + pos, position[2], position[3] + pos, 0, 0, 0)
            self.landChildUnit.parentCrystal = self

            WaitSeconds(Random(3,13))

            self.landChildUnit:Destroy()
            self.landChildUnit = nil
        end
    end,

}

TypeClass = XAA9904
Check out my 2 maps: "Survival_Mayhem&BO_3d_v1" "Survival_Mayhem&BO_3d_RPG"
as well as my mod: "Survival Mayhem&BO balance"
-- let me know of any bugs or issues regarding those 3.
DDDX
Avatar-of-War
 
Posts: 170
Joined: 21 Mar 2016, 16:13
Has liked: 18 times
Been liked: 16 times
FAF User Name: DDDX

Re: Variable drones number based on enhancement

Postby DDDX » 03 Nov 2018, 10:17

just a heads up, because of the number of abilities (overcharge, teleport, antinuke build) i had to remove the 'PODSTAGINGPLATFORM' (to lose the buttons for recalling drones - which I do not need anyways), however I do not think that harmed my script seeing how my drones worked perfectly well and got rebuilt with or without it (provided they were the original drones, not the drones from the secondary drone table which, like I said, do not get rebuilt).

A side thought, if we get this code to behave like it should, it could I guess give the ability to have several different units as drones, provided which enhancement you obtain and which DroneData table is called. Imagine a Blackops acu that can have builder drones OR fighter drones, depending what you pick (a suggestion perhaps for future BO:ACUs update ;)
Check out my 2 maps: "Survival_Mayhem&BO_3d_v1" "Survival_Mayhem&BO_3d_RPG"
as well as my mod: "Survival Mayhem&BO balance"
-- let me know of any bugs or issues regarding those 3.
DDDX
Avatar-of-War
 
Posts: 170
Joined: 21 Mar 2016, 16:13
Has liked: 18 times
Been liked: 16 times
FAF User Name: DDDX

Re: Variable drones number based on enhancement

Postby Franck83 » 04 Nov 2018, 15:19

After a rapid look, since i don't have your unit bp and i can't test changes, you may check theses parts :

Code: Select all
DroneSetup2 = function(self)
        -- Drone handle table, used to issue orders to all drones at once
        self.DroneTable = {}

When you call your code part at the enhancement, you clear the current DroneTable to be replaced with your own. But what about the 2 existing BO drones ?
You call again some maintenance existing thread, and that not quite good for code stability.

Here is the tread that orders drone repairs then rebuild. If your drones don't rebuild, there is something that should be wrong in the rebuild conditions.
Code: Select all
    DroneMaintenanceState = State {
        Main = function(self)
            self.DroneMaintenance = true           
            -- Resume any interrupted drone rebuilds
            if self.BuildingDrone then
                ChangeState(self, self.DroneRebuildingState)
            end           
            -- Check for dead or damaged drones
            while self and not self:IsDead() and not self.BuildingDrone do
                for droneName, droneData in self.DroneData do
                    if not droneData.Active or (droneData.Active and droneData.Damaged and droneData.Docked) then
                        self.BuildingDrone = droneName
                        ChangeState(self, self.DroneRebuildingState)
                    end
                end
                WaitTicks(2)
            end
        end,

        OnPaused = function(self)
            ChangeState(self, self.PausedState)
        end,
    },


So Im not sure that theses conditions are valid after your setup2 :
Code: Select all
if not droneData.Active or (droneData.Active and droneData.Damaged and droneData.Docked) then


So a simple fix maybe use the table.insert function instead a clear and deepcopy

So your setup2 (you should change the name of setup2 by a more reco name) should be modified

So your setup2 code part :
Code: Select all
    -- Initial drone setup - loads globals, DroneData table, and creates drones
    DroneSetup2 = function(self)
        -- Drone handle table, used to issue orders to all drones at once
        self.DroneTable = {}
       
        -- Drone construction globals
        self.BuildingDrone = false
        self.ControlRange = self:GetBlueprint().AI.DroneControlRange or 70
        self.ReturnRange = self:GetBlueprint().AI.DroneReturnRange or (ControlRange / 2)
        self.AssistRange = self.ControlRange + 10
        self.AirMonitorRange = self:GetBlueprint().AI.AirMonitorRange or (self.AssistRange / 2)
        self.HeartBeatInterval = self:GetBlueprint().AI.AssistHeartbeatInterval or 1

        self.DroneData = table.deepcopy(self:GetBlueprint().DroneData2)
       
        -- Load other data from drone BP and spawn drones
        for droneName, droneData in self.DroneData do
            -- Set drone name variable
            if not droneData.Name then
                droneData.Name = droneName
            end
            droneData.Blueprint = table.deepcopy(GetUnitBlueprintByName(droneData.UnitID))
            droneData.Economy = droneData.Blueprint.Economy
            droneData.BuildProgress = 1

            -- Create this drone
            self:ForkThread(self.CreateDrone, droneName)
        end
           
        -- Assist/monitor heartbeat thread
        self.HeartBeatThread = self:ForkThread(self.AssistHeartBeat)
       
        -- Begin drone maintenance monitoring
        ChangeState(self, self.DroneMaintenanceState)
    end,
   


Should be more like this one :
Code: Select all
   
   -- Enh new drone setup - creates 2 new drones from enh
    AddingEnhDronesSetup = function(self)
   
      local NewdronesFromEnh = table.deepcopy(self:GetBlueprint().DroneData2)
      table.insert(self.DroneTable, NewdronesFromEnh)
 
        -- Load other data from drone BP and spawn drones from enh
        for droneName, droneData in NewdronesFromEnh do
            -- Set drone name variable
            if not droneData.Name then
                droneData.Name = droneName
            end
            droneData.Blueprint = table.deepcopy(GetUnitBlueprintByName(droneData.UnitID))
            droneData.Economy = droneData.Blueprint.Economy
            droneData.BuildProgress = 1

            -- Create this drone
            self:ForkThread(self.CreateDrone, droneName)
        end
    end,


I can't test this code, but it should give you some help and direction for fixing your code.
Alliance of Heroes Mod is out ! Try it ! It's in the Mod Vault !
User avatar
Franck83
Evaluator
 
Posts: 538
Joined: 30 Dec 2016, 11:59
Location: France
Has liked: 114 times
Been liked: 122 times
FAF User Name: Franck83

Re: Variable drones number based on enhancement

Postby DDDX » 05 Nov 2018, 14:34

Thank you for trying to make this work.

the unit's .bp file is the same as is for any carrier unit, be it Tempest, Goliath or Yenzotha ;) Plus a secondary DroneData, that is.
I have removed most of the weapons from the blueprint cause the post otherwise excedes 60 000 symbols.

Your code, when implemented, gives me the following error upon using that enhancement:
Code: Select all
WARNING: Error running lua script: Invalid bone identifier; must be a string, integer, or nil
         stack traceback:
            [C]: in function `IsValidBone'
            ...l mayhem&bo balance\units\xaa9904\xaa9904_script.lua(1288): in function <...l mayhem&bo balance\units\xaa9904\xaa9904_script.lua:1286>

Which is strange considering that DroneData and DroneData2 use the same attachpoints for drones and the same bone for an effect when a drone spawns.


Code: Select all
UnitBlueprint {
    AI = {
        TargetBones = {
            'Hatch_Left',
            'Hatch_Right',
            'Attachpoint_Lrg_01',
            'Attachpoint_Med_03',
            'Exhaust01',
            'Turret_Front01',
            'Turret_Front',     
            'Left_Attachpoint02',
            'Right_Attachpoint05',
            'Left_Attachpoint12',
            'Right_Attachpoint06',
        },
        GuardScanRadius = 110,
        AssistHeartbeatInterval = 0.5,
        DroneControlRange = 120,
        DroneReturnRange = 70,
        AirMonitorRange = 160,
    },
    Air = {
        AutoLandTime = 50,
        BankFactor = 0.1,
        BankForward = false,
        CanFly = true,
        CirclingDirChangeFrequencySec = 1,
        CirclingElevationChangeRatio = 0.25,
        CirclingRadiusChangeMaxRatio = 0.9,
        CirclingRadiusChangeMinRatio = 0.6,
        CirclingRadiusVsAirMult = 0.66,
        CirclingTurnMult = 3,
        KLift = 1.5,
        KLiftDamping = 3,
        KMove = 0.45,
        KMoveDamping = 2,
        KRoll = 1,
        KRollDamping = 1,
        KTurn = 0.5,
        KTurnDamping = 2,
        LiftFactor = 1,
        MaxAirspeed = 4.5,
        StartTurnDistance = 10,
        TransportHoverHeight = 22,
    },
    Audio = {
        AirUnitWaterImpact = Sound {
            Bank = 'Explosions',
            Cue = 'Expl_Water_Lrg_01',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        AmbientMove = Sound {
            Bank = 'UAA',
            Cue = 'UAA0104_Move_Loop',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        DeathExplosion = Sound {
            Bank = 'UAADestroy',
            Cue = 'UAA_Destroy_Air_Killed',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        Destroyed = Sound {
            Bank = 'UAADestroy',
            Cue = 'UAA_Destroy_Air',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        Killed = Sound {
            Bank = 'UAADestroy',
            Cue = 'UAA_Destroy_Air_Killed',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        Landing = Sound {
            Bank = 'UAA',
            Cue = 'UAA0104_Move_Land',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        Load = Sound {
            Bank = 'UAA',
            Cue = 'UAA0104_Unit_Load',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        StartMove = Sound {
            Bank = 'UAA',
            Cue = 'UAA0104_Move_Start',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        StopMove = Sound {
            Bank = 'UAA',
            Cue = 'UAA0104_Move_Stop',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        Thruster = Sound {
            Bank = 'UAA',
            Cue = 'UAA0104_Move_Thruster',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        UISelection = Sound {
            Bank = 'Interface',
            Cue = 'Aeon_Select_Air',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        Unload = Sound {
            Bank = 'UAA',
            Cue = 'UAA0104_Unit_Unload',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        CaptureLoop = Sound {
            Bank = 'UAL',
            Cue = 'UAL0001_Capture_Loop',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        Construct = Sound {
            Bank = 'UAL',
            Cue = 'UAL0001_Construct_Start',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        ConstructLoop = Sound {
            Bank = 'UAL',
            Cue = 'UAL0001_Construct_Loop',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        EnhanceEnd = Sound {
            Bank = 'UnitsGlobal',
            Cue = 'GLB_Enhance_Stop',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        EnhanceFail = Sound {
            Bank = 'UnitsGlobal',
            Cue = 'GLB_Enhance_Fail',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        EnhanceLoop = Sound {
            Bank = 'UnitsGlobal',
            Cue = 'GLB_Enhance_Loop',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        EnhanceStart = Sound {
            Bank = 'UnitsGlobal',
            Cue = 'GLB_Enhance_Start',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        ReclaimLoop = Sound {
            Bank = 'UAL',
            Cue = 'UAL0001_Reclaim_Loop',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        StartCapture = Sound {
            Bank = 'UAL',
            Cue = 'UAL0001_Capture_Start',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        StartReclaim = Sound {
            Bank = 'UAL',
            Cue = 'UAL0001_Reclaim_Start',
            LodCutoff = 'UnitMove_LodCutoff',
        },
        UISelection = Sound {
            Bank = 'Interface',
            Cue = 'Aeon_Select_Commander',
            LodCutoff = 'UnitMove_LodCutoff',
        },
    },
    AverageDensity = 1,
    Buffs = {
        Regen = {
            Level1 = 150,
            Level2 = 190,
            Level3 = 230,
            Level4 = 270,
            Level5 = 310,
        },
    },
    BuildIconSortPriority = 60,
    Categories = {
        'PRODUCTSC1',
        'BUILTBYTIER3COMMANDER',     
        'NEEDMOBILEBUILD',
        'DRAGBUILD',
        'SELECTABLE',
        'AEON',
        'MOBILE',
        'AIR',
        'ANTIAIR',
        'GROUNDATTACK',
        'EXPERIMENTAL',
        'VISIBLETORECON',
        'RECLAIMABLE',
        'OVERLAYANTIAIR',
        'OVERLAYDIRECTFIRE',
        'ALPHA',
        'ALPHA_4',
        'ECONOMIC',
        'COMMAND',
        'MASSPRODUCTION',
        'ENERGYPRODUCTION',
        'REPAIR',
        'ENGINEER',
        'CONSTRUCTION',
        'RECLAIM',
        'CAPTURE',
        'PATROLHELPER',
        'OVERLAYRADAR',
        'INTELLIGENCE',
        'OVERLAYSONAR',
        'OVERLAYINDIRECTFIRE',
        'COUNTERINTELLIGENCE',
        'OVERLAYCOUNTERINTEL',
        'CANNOTUSEAIRSTAGING',
        'ANTIMISSILE',
        'SILO',
        'OVERLAYDEFENSE',
        'TELEPORT',
        'DEFENSE',
        'TIER3',
        --'PODSTAGINGPLATFORM',   --not enough room for commands, that's why this is neutralized, however it does not affect my issue active or not
    },
    CollisionOffsetX = 0,
    CollisionOffsetZ = -1.5,
    CollisionOffsetY = -1,
    Defense = {
        AirThreatLevel = 329,
       -- LambdaField = {
        --    AttachBone = 'baa0309',
         --   Radius = 65,
        --    Probability = 90,
       -- },
        ArmorType = 'Commander',
        EconomyThreatLevel = 0,
        Health = 20000,
        MaxHealth = 20000,
        RegenRate = 110,
        SubThreatLevel = 0,
        SurfaceThreatLevel = 8,
        MaxTeleRange = 100,
    },   
    Description = '<LOC xaa9904_desc>Level 4 hero',
    Display = {
        Abilities = {
            '<LOC ability_aa>Anti-Air',
            '<LOC ability_customizable>Customizable',
            '<LOC ability_engineeringsuite>Engineering Suite',
            '<LOC ability_notcap>Not Capturable',
            '<LOC ability_radar>Radar',
            '<LOC ability_sonar>Sonar',
            '<LOC ability_depthcharge>Depth Charges',           
            '<LOC ability_stun>Restoration Field',
            '<LOC ability_deathaoe>Volatile',
            '<LOC ability_massive>Massive',
            '<LOC ability_aadrones>Drones',
            '<LOC ability_teleport>Teleport',
            '<LOC ability_stun>EMP Weapon',
            --'<LOC ability_lambdafield>Lambda Field',
            '<LOC ability_stratmissiledef>Strategic Missile Defense',
            '<LOC ability_tacmissiledef>Tactical Missile Defense',
            --'<LOC ability_torpedo>Torpedoes',
        },
        AnimationPermOpen = '/mods/BlackOpsFAF-Unleashed/units/BAA0309/BAA0309_aopen01.sca',
        ForcedBuildSpin = 90,
        LayerChangeEffects = {
            AirLand = {
                Effects = {
                    {
                        Bones = {
                            'UAA0104',
                        },
                        Type = 'Landing01',
                    },
                },
            },
            LandAir = {
                Effects = {
                    {
                        Bones = {
                            'UAA0104',
                        },
                        Type = 'TakeOff01',
                    },
                },
            },
        },
        Mesh = {
            IconFadeInZoom = 130,
            LODs = {
                {
                    MeshName = '/mods/BlackOpsFAF-Unleashed/units/BAA0309/BAA0309_LOD0.scm',
                    AlbedoName = '/mods/BlackOpsFAF-Unleashed/units/BAA0309/BAA0309_Albedo.dds',
                    NormalsName = '/mods/BlackOpsFAF-Unleashed/units/BAA0309/BAA0309_NormalsTS.DDS',
                    SpecularName = '/mods/BlackOpsFAF-Unleashed/units/BAA0309/BAA0309_SpecTeam.dds',
                    LODCutoff = 300,
                    Scrolling = true,
                    ShaderName = 'Aeon',
                },
            },
        },
        PlaceholderMeshName = 'UXB0000',
        SpawnRandomRotation = false,
        UniformScale = 0.10,
    },
    DroneData = {                     --default 2 drones when you spawn
        Drone1 = {
            Attachpoint = 'Attachpoint_Lrg_01',
            UnitID = 'SUAL0105',
        },
        Drone2 = {
            Attachpoint = 'Attachpoint_Lrg_01',
            UnitID = 'SUAL0105',
        },
    },
    DroneData2 = {   --more drones if you choose the enhancement in question (Swarm Protocol). You will lack icons for enhancements, but they work blank so...who cares ;)
        Drone3 = {
            Attachpoint = 'Attachpoint_Lrg_01',
            UnitID = 'SUAL0105',
        },
        Drone4 = {
            Attachpoint = 'Attachpoint_Lrg_01',
            UnitID = 'SUAL0105',
        },
        Drone5 = {
            Attachpoint = 'Attachpoint_Lrg_01',
            UnitID = 'SUAL0105',
        },
        Drone6 = {
            Attachpoint = 'Attachpoint_Lrg_01',
            UnitID = 'SUAL0105',
        },
    },
    Economy = {
        BuildCostEnergy = 5000,
        BuildCostMass = 600,
        BuildTime = 300,
        BuildRate = 45,
        BuildableCategory = {
            'BUILTBYTIER1ENGINEER AEON',
            'BUILTBYTIER2ENGINEER AEON',
            'BUILTBYTIER3ENGINEER AEON',
            'BUILTBYALPHAA1',
            'BUILTBYALPHAA2',
            'BUILTBYALPHAA4',
            'uab1105',
            'uab1106',
        },
        MaintenanceConsumptionPerSecondEnergy = 1,
        MaxBuildDistance = 33,
        NaturalProducer = true,
        NeedToFaceTargetToBuild = false,
        ProductionPerSecondEnergy = 1000,
        ProductionPerSecondMass = 10,
        StorageEnergy = 2000,
        StorageMass = 800,
        TeleportBurstEnergyCost = 5,
        TeleportEnergyMod = 7.273,
        TeleportMassMod = 33.33,
        TeleportTimeMod = 0.0000667,
    },----------------------------------------------------------------------------------------------------------------------------------------------------------
    Enhancements = {
        Slots = {
            Back = {
                name = '<LOC _Back>',
                x = -2,
                y = -5,
            },
            LCH = {
                name = '<LOC _LCH>',
                x = 50,
                y = -10,
            },
            RCH = {
                name = '<LOC _RCH>',
                x = -12,
                y = -10,
            },
        },
        GuardianProtocol = {
            BuildCostEnergy = 25000,
            BuildCostMass = 1280,
            BuildTime = 1000,
            BuildableCategoryAdds = 'BUILTBYALPHAA3',
            Icon = 'turret',
            Name = 'Guardian protocol I',
            NewBuildRate = 30,
            NewHealth = 4000,             --20000 total
            NewRegenRate = 35,
            Slot = 'Back',
        },
        GuardianProtocolRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'turret',
            Name = 'Remove Guardian protocol I',
            Prerequisite = 'GuardianProtocol',
            RemoveEnhancements = {
                'GuardianProtocol',
                'GuardianProtocolRemove',
            },
            Slot = 'Back',
        },
        GuardianProtocol2 = {
            BuildCostEnergy = 39000,
            BuildCostMass = 2920,
            BuildTime = 2200,
            BuildableCategoryAdds = 'BUILTBYALPHAA4',
            Icon = 'turret2',
            Name = 'Guardian protocol II',
            NewBuildRate = 40,
            NewHealth = 4000,
            NewRegenRate = 50,
            Prerequisite = 'GuardianProtocol',
            Slot = 'Back',
        },
        GuardianProtocol2Remove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'turret2',
            Name = 'Remove Guardian protocol II',
            Prerequisite = 'GuardianProtocol2',
            RemoveEnhancements = {
                'GuardianProtocol',
                'GuardianProtocol2',
                'GuardianProtocol2Remove',
            },
            Slot = 'Back',
        }, 
        ApocalypticEngineering = {
            BuildCostEnergy = 50000,
            BuildCostMass = 5600,
            BuildTime = 6600,
            Icon = 'health',
            Name = 'Structural integrity protocol',
            Prerequisite = 'GuardianProtocol2',
            NewHealth = 5000,
            Slot = 'Back',
            NewRegenRate = 70,
        },
        ApocalypticEngineeringRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'health',
            Name = 'Remove Structural integrity protocol',
            Prerequisite = 'ApocalypticEngineering',
            RemoveEnhancements = {
                'GuardianProtocol',
                'GuardianProtocol2',
                'ApocalypticEngineering',
                'ApocalypticEngineeringRemove',
            },
            Slot = 'Back',
        },     
        TorpedoLauncher = {
            BuildCostEnergy = 22000,
            BuildCostMass = 1040,
            BuildTime = 960,
            Icon = 'exrtorp1',
            Name = 'Seaworth protocol I',
            NewHealth = 2500,
            NewRegenRate = 25,
            Slot = 'Back',
        },
        TorpedoLauncherRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'exrtorp1',
            Name = 'Remove Seaworth protocol I',
            Prerequisite = 'TorpedoLauncher',
            RemoveEnhancements = {
                'TorpedoLauncher',
                'TorpedoLauncherRemove',
            },
            Slot = 'Back',
        },
        ImprovedTorpLoader = {
            BuildCostEnergy = 38000,
            BuildCostMass = 3300,
            BuildTime = 1800,
            Icon = 'exrtorp2',
            Name = 'Seaworth protocol II',
            Prerequisite = 'TorpedoLauncher',
            NewHealth = 3500,
            NewRegenRate = 40,           
            TorpRoF = 0.6,
            Slot = 'Back',
        },
        ImprovedTorpLoaderRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'exrtorp2',
            Name = 'Remove Seaworth protocol II',
            Prerequisite = 'ImprovedTorpLoader',
            RemoveEnhancements = {
                'TorpedoLauncher',
                'ImprovedTorpLoader',
                'ImprovedTorpLoaderRemove',
            },
            Slot = 'Back',
        },
        AdvancedWarheads = {
            BuildCostEnergy = 35000,
            BuildCostMass = 2800,
            BuildTime = 1300,
            Icon = 'exrtorp3',
            Name = 'Sea Guardian protocol',
            Prerequisite = 'ImprovedTorpLoader',
            NewHealth = 3000,
            NewRegenRate = 25,
            TorpDamage = 400,
            Slot = 'Back',
        },
        AdvancedWarheadsRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'exrtorp3',
            Name = 'Remove Sea Guardian protocol',
            Prerequisite = 'AdvancedWarheads',
            TorpDamage = -400,
            RemoveEnhancements = {
                'TorpedoLauncher',
                'ImprovedTorpLoader',
                'AdvancedWarheads',
                'AdvancedWarheadsRemove',
            },
            Slot = 'Back',
        },
        ShieldBattery4 = {
            BuildCostEnergy = 37000,
            BuildCostMass = 2440,
            BuildTime = 1500,
            Icon = 'S1',
            ImpactEffects = 'AeonShieldHit01',
            Name = 'Defense protocol I',
            OwnerShieldMesh = '/mods/Survival Mayhem&BO balance/units/XAA9904/XAA9904_personalshield_mesh',
            PersonalShield = true,
            RegenAssistMult = 10,
            MaintenanceConsumptionPerSecondEnergy = 100,
            ShieldEnergyDrainRechargeTime = 2,
            ShieldMaxHealth = 5000,
            ShieldRechargeTime = 34,
            ShieldRegenRate = 300,
            ShieldRegenStartTime = 0,
            ShieldSize = 3,
            ShieldVerticalOffset = 0,
            Slot = 'RCH',
        },
        ShieldBattery4Remove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'S1',
            Name = 'Remove Defense Protocol',
            Prerequisite = 'ShieldBattery4',
            RemoveEnhancements = {
                'ShieldBattery4',
                'ShieldBattery4Remove',
            },
            Slot = 'RCH',
        },
        ExpandedShieldBubble4 = {
            BuildCostEnergy = 43000,
            BuildCostMass = 3300,
            BuildTime = 2100,
            Icon = 'S3',
            ImpactEffects = 'AeonShieldHit01',
            ImpactMesh = '/effects/entities/ShieldSection01/ShieldSection01_mesh',
            Mesh = '/effects/entities/Shield01/Shield01_mesh',
            MeshZ = '/effects/entities/Shield01/Shield01z_mesh',
            Name = 'Defense protocol II',
            Prerequisite = 'ShieldBattery4',
            MaintenanceConsumptionPerSecondEnergy = 150,
            ShieldEnergyDrainRechargeTime = 5,
            ShieldEnhancementNumber = 5,
            ShieldMaxHealth = 11000,
            ShieldRechargeTime = 31,
            ShieldRegenRate = 300,
            ShieldRegenStartTime = 0,
            ShieldSize = 23,
            ShieldVerticalOffset = -12,
            Slot = 'RCH',
        },
        ExpandedShieldBubble4Remove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'S3',
            Name = 'Remove Defense protocol II',
            Prerequisite = 'ExpandedShieldBubble4',
            RemoveEnhancements = {
                'ShieldBattery4',
                'ExpandedShieldBubble4',
                'ExpandedShieldBubble4Remove',
            },
            Slot = 'RCH',
        },
        ImprovedShieldBattery4 = {
            BuildCostEnergy = 50000,
            BuildCostMass = 4500,
            BuildTime = 2600,
            Icon = 'S2',
            ImpactEffects = 'AeonShieldHit01',
            ImpactMesh = '/effects/entities/ShieldSection01/ShieldSection01_mesh',
            Mesh = '/effects/entities/Shield01/Shield01_mesh',
            MeshZ = '/effects/entities/Shield01/Shield01z_mesh',
            Name = 'Defense protocol III',
            Prerequisite = 'ExpandedShieldBubble4',
            MaintenanceConsumptionPerSecondEnergy = 200,
            ShieldEnergyDrainRechargeTime = 5,
            ShieldMaxHealth = 18000,
            ShieldRechargeTime = 30,
            ShieldRegenRate = 350,
            ShieldRegenStartTime = 0,
            ShieldSize = 25,
            ShieldVerticalOffset = -14,
            Slot = 'RCH',
        },
        ImprovedShieldBattery4Remove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'S2',
            Name = 'Remove Defense protocol III',
            Prerequisite = 'ImprovedShieldBattery4',
            RemoveEnhancements = {
                'ShieldBattery',
                'ExpandedShieldBubble4',
                'ImprovedShieldBattery4',
                'ImprovedShieldBattery4Remove',
            },
            Slot = 'RCH',
        },
        PhasonBeamCannon4 = {
            BuildCostEnergy = 40000,
            BuildCostMass = 3140,
            BuildTime = 1800,
            Icon = 'exrgec1',
            Name = 'Offense protocol',
            OblivionPDRoF = 0.75,            --0.55
            OblivionPDDamage = 100,          --600
            bigGunRoF = 0.075,            --0.045
            bigGunDamage = 200,              --400
            Slot = 'RCH',
        },
        PhasonBeamCannon4Remove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'exrgec1',
            Name = 'Remove Offense protocol',
            Prerequisite = 'PhasonBeamCannon',
            OblivionPDRoF = 0.55,
            OblivionPDDamage = -100,          --600
            bigGunRoF = 0.045,
            bigGunDamage = -200,
            RemoveEnhancements = {
                'PhasonBeamCannon4',
                'PhasonBeamCannon4Remove',
            },
            Slot = 'RCH',
        },
        DualMiasmaArtillery4 = {
            BuildCostEnergy = 50000,
            BuildCostMass = 4990,
            BuildTime = 2300,
            Icon = 'exrzb2',
            Name = 'Energy beam focus',
            Prerequisite = 'PhasonBeamCannon4',
            Slot = 'RCH',
        },
        DualMiasmaArtillery4Remove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'exrzb2',
            Name = 'Remove Energy beam focus',
            Prerequisite = 'DualMiasmaArtillery4',
            RemoveEnhancements = {
                'PhasonBeamCannon4',
                'DualMiasmaArtillery4',
                'DualMiasmaArtillery4Remove',
            },
            Slot = 'RCH',
        },
        OverchargeAmplifierA = {
            BuildCostEnergy = 60000,
            BuildCostMass = 5400,
            BuildTime = 2600,
            Icon = 'overcharge',
            Name = 'Overcharge protocol',
            Prerequisite = 'DualMiasmaArtillery4',
            NewProjectileBlueprint = '/mods/BlackOpsFAF-ACUs/projectiles/OmegaOverCharge01/OmegaOverCharge01_proj.bp',
            OverChargeRoF = 0.06,            --0.03
           -- OverChargeMaxRange = 40,
            Slot = 'RCH',
        },
        OverchargeAmplifierARemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            NewProjectileBlueprint = '/projectiles/SDFChronatronCannon02/SDFChronatronCannon02_proj.bp',
            Icon = 'overcharge',
            Name = 'Remove Overcharge protocol',
            Prerequisite = 'OverchargeAmplifierA',
            RemoveEnhancements = {
                'PhasonBeamCannon4',
                'DualMiasmaArtillery4',
                'OverchargeAmplifierA',
                'OverchargeAmplifierARemove',
            },
            Slot = 'RCH',
        },
        ScavengerProtocol = {
            BuildCostEnergy = 45000,
            BuildCostMass = 4280,
            BuildTime = 2000,
            BuildableCategoryAdds = 'BUILTBYALPHAA4',
            Icon = 'rec',
            Name = 'Scavenger protocol',
            NewBuildRate = 50,
            NewHealth = 3000,             --20000 total
            NewRegenRate = 50,           
            Radius = 25,
            RegenCeiling = 300,  --300
            RegenPerSecond = 0.02,  --0.032
            MaxHealthFactor = 1.2,
           -- UnitCategory = 'BUILTBYTIER3FACTORY, BUILTBYQUANTUMGATE, NEEDMOBILEBUILD',
            Slot = 'LCH',
        },
        ScavengerProtocolRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'rec',
            Name = 'Remove Scavenger protocol I',
            Prerequisite = 'ScavengerProtocol',
            RemoveEnhancements = {
                'ScavengerProtocol',
                'ScavengerProtocolRemove',
            },
            Slot = 'LCH',
        },
        SkyTrackerProtocol = {
            BuildCostEnergy = 40000,
            BuildCostMass = 3900,
            BuildTime = 2000,
            Icon = 'sky',
            Name = 'SkyTracker Protocol',
            Prerequisite = 'ScavengerProtocol',
            Slot = 'LCH',
        },
        SkyTrackerProtocolRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'sky',
            Name = 'Remove SkyTracker Protocol',
            Prerequisite = 'SkyTrackerProtocol',
            RemoveEnhancements = {
                'ScavengerProtocol',
                'SkyTrackerProtocol',
                'SkyTrackerProtocolRemove',
            },
            Slot = 'LCH',
        },
        SurvivalProtocol = {
            BuildCostEnergy = 60000,
            BuildCostMass = 6600,
            BuildTime = 2600,
            Icon = 'hfield',
            Name = 'Survival protocol',           
            Radius = 30,
            RegenCeiling = 400,  --300
            RegenPerSecond = 0.03,  --0.032
            MaxHealthFactor = 1.3,
            Prerequisite = 'SkyTrackerProtocol',
            Slot = 'LCH',
        },
        SurvivalProtocolRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'hfield',
            Name = 'Remove Survival protocol',
            Prerequisite = 'SurvivalProtocol',
            RemoveEnhancements = {
                'ScavengerProtocol',
                'SkyTrackerProtocol',
                'SurvivalProtocol',
                'SurvivalProtocolRemove',
            },
            Slot = 'LCH',
        },       
        SummonerProtocol = {               --this should give me  +4 drones, from the starting 2
            BuildCostEnergy = 60000,
            BuildCostMass = 6600,
            BuildTime = 2600,
            Icon = 'summon',
            Name = 'Summoner protocol',
            Radius = 25,
            RegenCeiling = 300,  --300
            RegenPerSecond = 0.02,  --0.032
            MaxHealthFactor = 1.2,
            Slot = 'LCH',
        },
        SummonerProtocolRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'summon',
            Name = 'Remove Summoner protocol',
            Prerequisite = 'SummonerProtocol',
            RemoveEnhancements = {
                'SummonerProtocol',
                'SummonerProtocolRemove',
            },
            Slot = 'LCH',
        }, 
        Summoner2Protocol = {
            BuildCostEnergy = 40000,
            BuildCostMass = 3900,
            BuildTime = 2000,
            Icon = 'arta',
            Name = 'Summoner Advanced Protocol',
            Prerequisite = 'SummonerProtocol',
            Slot = 'LCH',
        },
        Summoner2ProtocolRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'arta',
            Name = 'Remove Summoner Advanced Protocol',
            Prerequisite = 'Summoner2Protocol',
            RemoveEnhancements = {
                'SummonerProtocol',
                'Summoner2Protocol',
                'Summoner2ProtocolRemove',
            },
            Slot = 'LCH',
        },
        ALVSTProtocol = {
            BuildCostEnergy = 60000,
            BuildCostMass = 6600,
            BuildTime = 2600,
            Icon = 'artemis',
            Name = 'ALVST protocol',           
            Radius = 30,
            RegenCeiling = 400,  --300
            RegenPerSecond = 0.03,  --0.032
            MaxHealthFactor = 1.3,
            Prerequisite = 'Summoner2Protocol',
            Slot = 'LCH',
        },
        ALVSTProtocolRemove = {
            BuildCostEnergy = 1,
            BuildCostMass = 1,
            BuildTime = 0.1,
            Icon = 'artemis',
            Name = 'Remove ALVST protocol',
            Prerequisite = 'ALVSTProtocol',
            RemoveEnhancements = {
                'SummonerProtocol',
                'Summoner2Protocol',
                'ALVSTProtocol',
                'ALVSTProtocolRemove',
            },
            Slot = 'LCH',
        },     
    },
        -----------------------------------------------------------------------------------------------------------------------------------------------------------------
        ----------------------------------------------------------------------------------------------------------------------------------------------------------------
    Footprint = {
        MaxSlope = 0.25,
        SizeX = 10,
        SizeZ = 13,
    },
    General = {       
        BuildBones = {
            AimBone = 'Left_Attachpoint01',
            BuildEffectBones = {
                'Left_Attachpoint01',
            },
            PitchBone = 'Left_Attachpoint01',
            YawBone = 'Left_Attachpoint01',
        },
        Category = 'Gunship',
        Classification = 'RULEUC_MilitaryAircraft',
        CommandCaps = {
            RULEUCC_Attack = true,
            RULEUCC_CallTransport = true,
            RULEUCC_Capture = true,
            RULEUCC_Ferry = false,
            RULEUCC_Guard = true,
            RULEUCC_Move = true,
            RULEUCC_Nuke = false,
            RULEUCC_Patrol = true,
            RULEUCC_Reclaim = true,
            RULEUCC_Repair = true,
            RULEUCC_RetaliateToggle = true,
            RULEUCC_Stop = true,
            RULEUCC_SiloBuildNuke = false,
            RULEUCC_SiloBuildTactical = true,
            RULEUCC_Teleport = true,
            RULEUCC_Transport = false,
            RULEUCC_Overcharge = true,
        },
        --ConstructionBar = true,
        FactionName = 'Aeon',
        Icon = 'air',   
        SelectionPriority = 2,
        TechLevel = 'RULEUTL_Secret',
        UnitName = 'ALPHA',
        UnitWeight = 1,
    },
    Intel = {
        VisionRadius = 70,
        CloakFieldRadius = 25,    -- Used only to show teleport range
        SonarRadius = 60,
        RadarRadius = 120,
        OmniRadius = 40,
    },
    Interface = {
        HelpText = 'Level 4 flying, evolving, upgradeable hero unit. Be careful not to lose it.',
    },
    LifeBarHeight = 0.105,
    LifeBarOffset = 4.8,
    LifeBarSize = 10,
    Physics = {
        BuildOnLayerCaps = {
            LAYER_Air = true,
            LAYER_Land = false,
            LAYER_Orbit = false,
            LAYER_Seabed = false,
            LAYER_Sub = false,
            LAYER_Water = false,
        },
        --AttackElevation    = 16.0,
        Elevation = 16.0,
        GroundCollisionOffset = 1.6,
        FuelRechargeRate = 70,
        FuelUseTime = 2000,
        MaxSpeed = 0.5,
        MeshExtentsX = 6.5,
        MeshExtentsY = 4,
        MeshExtentsZ = 6.5,
        MotionType = 'RULEUMT_Air',
    },
    SelectionSizeX = 6.8,
    SelectionSizeZ = 8,
    SelectionThickness = 0.42,
    SizeX = 5.8,
    SizeY = 3.7,
    SizeZ = 9,
    StrategicIconName = 'icon_experimental_generic',
    StrategicIconSortPriority = 65,
    Transport = {
        AirClass = false,
        Class2AttachSize = 2,
        Class3AttachSize = 4,
        TransportClass = 10,
    },
    UseOOBTestZoom = 200,
    Veteran = {
        Level1 = 30,
        Level2 = 60,
        Level3 = 90,
        Level4 = 120,
        Level5 = 150,
    },
    Weapon = {
        {
            AboveWaterTargetsOnly = true,
            Audio = {
                BarrelLoop = Sound {
                    Bank = 'UAS',
                    Cue = 'UAS_Turret_Lrg_Loop',
                    LodCutoff = 'WeaponBig_LodCutoff',
                },
                BarrelStart = Sound {
                    Bank = 'UAS',
                    Cue = 'UAS_Turret_Lrg_Start',
                    LodCutoff = 'WeaponBig_LodCutoff',
                },
                Fire = Sound {
                    Bank = 'UASWeapon',
                    Cue = 'UAS0401_Cannon_Oblivion',
                    LodCutoff = 'WeaponBig_LodCutoff',
                },
                MuzzleChargeStart = Sound {
                    Bank = 'UASWeapon',
                    Cue = 'UAS0401_Cannon_Oblv_Charge',
                    LodCutoff = 'WeaponBig_LodCutoff',
                },
            },
            BallisticArc = 'RULEUBA_LowArc',
            CollideFriendly = false,
            Damage = 5000,
            DamageRadius = 7,
            DamageType = 'Normal',
            DisplayName = 'Oblivion Cannon',
            FireTargetLayerCapsTable = {
                Land = 'Land|Water|Seabed',
                Water = 'Land|Water|Seabed',
                Air = 'Land|Water|Seabed',
            },
            FiringRandomness = 2.6,
            FiringTolerance = 0,
            Label = 'MainGun',                                                                  -- Oblivion right
            MaxRadius = 40,
            MuzzleChargeDelay = 0.6,
            MuzzleSalvoDelay = 0,
            MuzzleSalvoSize = 1,
            MuzzleVelocity = 30,
            MuzzleVelocityReduceDistance = 130,
            NotExclusive = true,
            ProjectileId = '/projectiles/ADFOblivionCannon04/ADFOblivionCannon04_proj.bp',
            ProjectileLifetime = 10,
            RackBones = {
                {
                    MuzzleBones = {
                        'Muzzle_R01',
                    },
                    RackBone = 'Turret_Right01',
                },
            },
            RackFireTogether = false,
            RackRecoilDistance = 0,
            RackReloadTimeout = 10,
            RackSalvoChargeTime = 0,
            RackSalvoReloadTime = 0,
            RackSalvoSize = 1,
            RackSlavedToTurret = false,
            RangeCategory = 'UWRC_DirectFire',
            RateOfFire = 0.2,
            SlavedToBody = false,
            TargetCheckInterval = 5,
            TargetPriorities = {
                'SPECIALHIGHPRI',
                'EXPERIMENTAL',
                'DEFENSE',
                'TECH3 MOBILE',
                'TECH2 MOBILE',
                'TECH1 MOBILE',
                'SPECIALLOWPRI',
                'ALLUNITS',
            },
            TargetRestrictDisallow = 'UNTARGETABLE',
            TrackingRadius = 1.15,
            TurretBoneMuzzle = 'Muzzle_R01',
            TurretBonePitch = 'Turret_Right01',
            TurretBoneYaw = 'Turret_Right01',
            TurretDualManipulators = false,
            TurretPitch = 40,
            TurretPitchRange = 50,
            TurretPitchSpeed = 30,
            TurretYaw = 0,
            TurretYawRange = 180,
            TurretYawSpeed = 10,
            Turreted = true,
            WeaponCategory = 'Direct Fire Naval',
        },
        {
            AboveWaterTargetsOnly = true,
            Audio = {
                BarrelLoop = Sound {
                    Bank = 'UAS',
                    Cue = 'UAS_Turret_Lrg_Loop',
                    LodCutoff = 'WeaponBig_LodCutoff',
                },
                BarrelStart = Sound {
                    Bank = 'UAS',
                    Cue = 'UAS_Turret_Lrg_Start',
                    LodCutoff = 'WeaponBig_LodCutoff',
                },
                Fire = Sound {
                    Bank = 'UASWeapon',
                    Cue = 'UAS0401_Cannon_Oblivion',
                    LodCutoff = 'WeaponBig_LodCutoff',
                },
                MuzzleChargeStart = Sound {
                    Bank = 'UASWeapon',
                    Cue = 'UAS0401_Cannon_Oblv_Charge',
                    LodCutoff = 'WeaponBig_LodCutoff',
                },
            },
            BallisticArc = 'RULEUBA_LowArc',
            CollideFriendly = false,
            Damage = 6000,
            DamageRadius = 6,
            DamageType = 'Normal',
            DisplayName = 'Oblivion Cannon',
            FireTargetLayerCapsTable = {
                Land = 'Land|Water|Seabed',
                Water = 'Land|Water|Seabed',
                Air = 'Land|Water|Seabed',
            },
            FiringRandomness = 3.3,
            FiringTolerance = 0,
            Label = 'MainGun01',                                                  -- Oblivion left
            MaxRadius = 40,
            MuzzleChargeDelay = 0.5,
            MuzzleSalvoDelay = 0,
            MuzzleSalvoSize = 1,
            MuzzleVelocity = 30,
            MuzzleVelocityReduceDistance = 130,
            NotExclusive = true,
            ProjectileId = '/projectiles/ADFOblivionCannon04/ADFOblivionCannon04_proj.bp',
            ProjectileLifetime = 10,
            RackBones = {
                {
                    MuzzleBones = {
                        'Muzzle_L',
                    },
                    RackBone = 'Turret_Left',
                },
            },
            RackFireTogether = false,
            RackRecoilDistance = 0,
            RackReloadTimeout = 10,
            RackSalvoChargeTime = 0,
            RackSalvoReloadTime = 0,
            RackSalvoSize = 1,
            RackSlavedToTurret = false,
            RangeCategory = 'UWRC_DirectFire',
            RateOfFire = 0.2,
            SlavedToBody = false,
            TargetCheckInterval = 5,
            TargetPriorities = {
                'SPECIALHIGHPRI',
                'DEFENSE',
                'TECH3 MOBILE',
                'TECH2 MOBILE',
                'TECH1 MOBILE',
                'SPECIALLOWPRI',
                'ALLUNITS',
            },
            TargetRestrictDisallow = 'UNTARGETABLE',
            TrackingRadius = 1.15,
            TurretBoneMuzzle = 'Muzzle_L',
            TurretBonePitch = 'Turret_Left',
            TurretBoneYaw = 'Turret_Left',
            TurretDualManipulators = false,
            TurretPitch = 40,
            TurretPitchRange = 50,
            TurretPitchSpeed = 30,
            TurretYaw = 0,
            TurretYawRange = 180,
            TurretYawSpeed = 10,
            Turreted = true,
            WeaponCategory = 'Direct Fire Naval',
        },
        {
            AlwaysRecheckTarget = true,
            AimsStraightOnDisable = true,
            Audio = {
                BeamLoop = Sound {
                    Bank = 'URLWeapon',
                    Cue = 'URL0402_Beam_Loop',
                    LodCutoff = 'Weapon_LodCutoff',
                },
                BeamStart = Sound {
                    Bank = 'TM_AEONWEAPONS',
                    Cue = 'AEONNOVACATBLUELASERFX',
                    LodCutoff = 'Weapon_LodCutoff',
                },
                BeamStop = Sound {
                    Bank = 'URLWeapon',
                    Cue = 'URL0402_Beam_Stop',
                    LodCutoff = 'Weapon_LodCutoff',
                },
                Unpack = Sound {
                    Bank = 'URLWeapon',
                    Cue = 'URL0402_Beam_Charge',
                    LodCutoff = 'Weapon_LodCutoff',
                },
            },
            BallisticArc = 'RULEUBA_LowArc',
            BeamCollisionDelay = 0.1,
            BeamLifetime = 1.2,
            CannotAttackGround = true,
            CollideFriendly = false,
            ContinuousBeam = false,
            Damage = 480,
            DamageFriendly = false,
            DamageType = 'Normal',
            DamageRadius = 2,
            DisplayName = 'Blue Laser',
            FireTargetLayerCapsTable = {
                Land = 'Air',
                Water = 'Air',
                Air = 'Air',
            },
            FiringRandomness = 0,
            FiringTolerance = 1.1,
            Label = 'laserblue3',                                          --aa 3
            MaxRadius = 55,
            MuzzleSalvoDelay = 0,
            MuzzleSalvoSize = 1,
            RackBones = {
                {
                    MuzzleBones = {
                        'Muzzle_F',
                    },
                    RackBone = 'Turret_Front',
                },
            },
            RackFireTogether = false,
            RackRecoilDistance = 0,
            RackReloadTimeout = 10,
            RackSalvoChargeTime = 0,
            RackSalvoReloadTime = 0,
            RackSalvoSize = 1,
            RackSlavedToTurret = false,
            RangeCategory = 'UWRC_AntiAir',
            RateOfFire = 0.05,
            TargetCheckInterval = 1.4,
            TargetPriorities = {
                'EXPERIMENTAL',
                'SPECIALHIGHPRI',
                'AIR MOBILE HIGHPRIAIR',
                'AIR MOBILE TECH3 BOMBER',
                'AIR MOBILE BOMBER',
                'AIR MOBILE GROUNDATTACK',
                'AIR MOBILE TRANSPORTATION',
                'AIR MOBILE',
                'ALLUNITS',
            },
            TargetRestrictDisallow = 'UNTARGETABLE',
            TrackingRadius = 1.4,
            TurretBoneMuzzle = 'Muzzle_F',
            TurretBonePitch = 'Turret_Front',
            TurretBoneYaw = 'Turret_Front',
            TurretDualManipulators = false,
            TurretPitch = 0,
            TurretPitchRange = 145,
            TurretPitchSpeed = 50,
            TurretYaw = 0,
            TurretYawRange = 180,
            TurretYawSpeed = 50,
            Turreted = true,
            WeaponCategory = 'Anti Air',
        },
        {
            AboveWaterTargetsOnly = true,
            Audio = {
                Fire = Sound {
                    Bank = 'UALWeapon',
                    Cue = 'UAB2301_Cannon_Oblivion_Fire',
                    LodCutoff = 'Weapon_LodCutoff',
                },
                MuzzleChargeStart = Sound {
                    Bank = 'UALWeapon',
                    Cue = 'UAB2301_Cannon_Oblivion_Charge',
                    LodCutoff = 'Weapon_LodCutoff',
                },
            },
            BallisticArc = 'RULEUBA_LowArc',
            CollideFriendly = false,
            Damage = 600,
            DamageFriendly = false,
            DamageRadius = 3,
            DamageType = 'Normal',
            DisplayName = 'Oblivion Cannon',
            FireTargetLayerCapsTable = {
                Land = 'Land|Water|Seabed',
                Water = 'Land|Water|Seabed',
                Air = 'Land|Water|Seabed',
            },
            FiringRandomness = 2.8,
            FiringTolerance = 0.5,
            Label = 'MainGun4',                                        --Oblivion PD back1
            LeadTarget = true,
            MaxRadius = 40,
            MuzzleChargeDelay = 0.5,
            MuzzleSalvoDelay = 0,
            MuzzleSalvoSize = 1,
            MuzzleVelocity = 35,
            ProjectileId = '/projectiles/ADFOblivionCannon03/ADFOblivionCannon03_proj.bp',
            ProjectileLifetimeUsesMultiplier = 1.15,
            ProjectilesPerOnFire = 1,
            RackBones = {
                {
                    MuzzleBones = {
                        'Attachpoint_Med_07',
                    },
                    RackBone = 'Attachpoint_Med_07',
                },
            },
            RackFireTogether = false,
            RackRecoilDistance = 0,
            RackReloadTimeout = 10,
            RackSalvoChargeTime = 0,
            RackSalvoFiresAfterCharge = false,
            RackSalvoReloadTime = 0,
            RackSalvoSize = 1,
            RackSlavedToTurret = false,
            RangeCategory = 'UWRC_DirectFire',
            RateOfFire = 0.55,
            TargetCheckInterval = 1,
            TargetPriorities = {
                'SPECIALHIGHPRI',
                'MOBILE',
                'STRUCTURE DEFENSE',
                'SPECIALLOWPRI',
                'ALLUNITS',
            },
            TargetRestrictDisallow = 'UNTARGETABLE',
            TrackingRadius = 1.15,
            TurretBoneMuzzle = 'Attachpoint_Med_07',
            TurretBonePitch = 'Attachpoint_Med_07',
            TurretBoneYaw = 'Attachpoint_Med_07',
            TurretDualManipulators = false,
            TurretPitch = 0,
            TurretPitchRange = 150,
            TurretPitchSpeed = 30,
            TurretYaw = 0,
            TurretYawRange = 180,
            TurretYawSpeed = 80,
            Turreted = true,
            WeaponCategory = 'Direct Fire',
            WeaponUnpacks = false,
        },
        {
            AboveWaterTargetsOnly = true,
            Audio = {
                Fire = Sound {
                    Bank = 'UALWeapon',
                    Cue = 'UAB2301_Cannon_Oblivion_Fire',
                    LodCutoff = 'Weapon_LodCutoff',
                },
                MuzzleChargeStart = Sound {
                    Bank = 'UALWeapon',
                    Cue = 'UAB2301_Cannon_Oblivion_Charge',
                    LodCutoff = 'Weapon_LodCutoff',
                },
            },
            BallisticArc = 'RULEUBA_LowArc',
            CollideFriendly = false,
            Damage = 600,
            DamageFriendly = false,
            DamageRadius = 3,
            DamageType = 'Normal',
            DisplayName = 'Oblivion Cannon',
            FireTargetLayerCapsTable = {
                Land = 'Land|Water|Seabed',
                Water = 'Land|Water|Seabed',
                Air = 'Land|Water|Seabed',
            },
            FiringRandomness = 2.5,
            FiringTolerance = 1.5,
            Label = 'MainGun5',                                               --Oblivion PD back2
            LeadTarget = true,
            MaxRadius = 40,
            MuzzleChargeDelay = 0.5,
            MuzzleSalvoDelay = 0,
            MuzzleSalvoSize = 1,
            MuzzleVelocity = 35,
            ProjectileId = '/projectiles/ADFOblivionCannon03/ADFOblivionCannon03_proj.bp',
            ProjectileLifetimeUsesMultiplier = 1.15,
            ProjectilesPerOnFire = 1,
            RackBones = {
                {
                    MuzzleBones = {
                        'Right_Attachpoint06',
                    },
                    RackBone = 'Right_Attachpoint06',
                },
            },
            RackFireTogether = false,
            RackRecoilDistance = 0,
            RackReloadTimeout = 10,
            RackSalvoChargeTime = 0,
            RackSalvoFiresAfterCharge = false,
            RackSalvoReloadTime = 0,
            RackSalvoSize = 1,
            RackSlavedToTurret = false,
            RangeCategory = 'UWRC_DirectFire',
            RateOfFire = 0.75,
            TargetCheckInterval = 1,
            TargetPriorities = {
                'SPECIALHIGHPRI',
                'MOBILE',
                'STRUCTURE DEFENSE',
                'SPECIALLOWPRI',
                'ALLUNITS',
            },
            TargetRestrictDisallow = 'UNTARGETABLE',
            TrackingRadius = 1.15,
            TurretBoneMuzzle = 'Right_Attachpoint06',
            TurretBonePitch = 'Right_Attachpoint06',
            TurretBoneYaw = 'Right_Attachpoint06',
            TurretDualManipulators = false,
            TurretPitch = 0,
            TurretPitchRange = 150,
            TurretPitchSpeed = 30,
            TurretYaw = 0,
            TurretYawRange = 180,
            TurretYawSpeed = 20,
            Turreted = true,
            WeaponCategory = 'Direct Fire',
            WeaponUnpacks = false,
        },
        {
            AboveWaterTargetsOnly = true,
            Audio = {
                Fire = Sound {
                    Bank = 'UALWeapon',
                    Cue = 'UAB2301_Cannon_Oblivion_Fire',
                    LodCutoff = 'Weapon_LodCutoff',
                },
                MuzzleChargeStart = Sound {
                    Bank = 'UALWeapon',
                    Cue = 'UAB2301_Cannon_Oblivion_Charge',
                    LodCutoff = 'Weapon_LodCutoff',
                },
            },
            BallisticArc = 'RULEUBA_LowArc',
            CollideFriendly = false,
            Damage = 600,
            DamageFriendly = false,
            DamageRadius = 3,
            DamageType = 'Normal',
            DisplayName = 'Oblivion Cannon',
            FireTargetLayerCapsTable = {
                Land = 'Land|Water|Seabed',
                Water = 'Land|Water|Seabed',
                Air = 'Land|Water|Seabed',
            },
            FiringRandomness = 3.1,
            FiringTolerance = 0.5,
            Label = 'MainGun6',                                                --Oblivion PD 3
            LeadTarget = true,
            MaxRadius = 40,
            MuzzleChargeDelay = 0.5,
            MuzzleSalvoDelay = 0,
            MuzzleSalvoSize = 1,
            MuzzleVelocity = 35,
            ProjectileId = '/projectiles/ADFOblivionCannon03/ADFOblivionCannon03_proj.bp',
            ProjectileLifetimeUsesMultiplier = 1.15,
            ProjectilesPerOnFire = 1,
            RackBones = {
                {
                    MuzzleBones = {
                        'Attachpoint_Med_06',
                    },
                    RackBone = 'Attachpoint_Med_06',
                },
            },
            RackFireTogether = false,
            RackRecoilDistance = 0,
            RackReloadTimeout = 10,
            RackSalvoChargeTime = 0,
            RackSalvoFiresAfterCharge = false,
            RackSalvoReloadTime = 0,
            RackSalvoSize = 1,
            RackSlavedToTurret = false,
            RangeCategory = 'UWRC_DirectFire',
            RateOfFire = 0.45,
            TargetCheckInterval = 1,
            TargetPriorities = {
                'SPECIALHIGHPRI',
                'MOBILE',
                'STRUCTURE DEFENSE',
                'SPECIALLOWPRI',
                'ALLUNITS',
            },
            TargetRestrictDisallow = 'UNTARGETABLE',
            TrackingRadius = 1.15,
            TurretBoneMuzzle = 'Attachpoint_Med_06',
            TurretBonePitch = 'Attachpoint_Med_06',
            TurretBoneYaw = 'Attachpoint_Med_06',
            TurretDualManipulators = false,
            TurretPitch = 0,
            TurretPitchRange = 150,
            TurretPitchSpeed = 30,
            TurretYaw = 0,
            TurretYawRange = 180,
            TurretYawSpeed = 80,
            Turreted = true,
            WeaponCategory = 'Direct Fire',
            WeaponUnpacks = false,
        },       
        {
            AboveWaterTargetsOnly = true,
            Audio = {
                Fire = Sound {
                    Bank = 'TM_AEONWEAPONS',
                    Cue = 'BROT3HAMPLASMAFIRE',
                    LodCutoff = 'Weapon_LodCutoff',
                },
            },
            BallisticArc = 'RULEUBA_LowArc',
            CollideFriendly = false,
            Damage = 400,
            DamageRadius = 5,
            DamageType = 'Normal',
            DamageFriendly = false,
            DisplayName = 'Cluster rockets',
            FireTargetLayerCapsTable = {
                Land = 'Land|Water|Seabed',
                Water = 'Land|Water|Seabed',
                Air = 'Land|Water|Seabed',
            },
            FiringTolerance = 2,
            Label = 'bigGun',                                                             -- cluster rockets
            MaxRadius = 40,
            MinRadius = 10,
            MuzzleChargeDelay = 2,
            MuzzleSalvoDelay = 0,
            MuzzleSalvoSize = 1,
            MuzzleVelocity = 15,
            ProjectileId = '/mods/TotalMayhem/projectiles/BROT3BTBOTproj/BROT3BTBOTproj_proj.bp',
            ProjectileLifetimeUsesMultiplier = 3,
            ProjectilesPerOnFire = 1,
            RackBones = {
                {
                    MuzzleBones = {
                        'Attachpoint_Lrg_01',
                        'Attachpoint_Lrg_02',
                    },
                    RackBone = 'Attachpoint_Lrg_01',
                },
            },
            RackFireTogether = false,
            RackRecoilDistance = 0,
            RackReloadTimeout = 10,
            RackSalvoChargeTime = 0,
            RackSalvoReloadTime = 0,
            RackSalvoSize = 1,
            RackSlavedToTurret = false,
            RangeCategory = 'UWRC_IndirectFire',
            RateOfFire = 0.045,
            RenderFireClock = true,
            TargetCheckInterval = 0.5,
            TargetPriorities = {
                'EXPERIMENTAL',
                'SPECIALHIGHPRI',
                'TECH3 MOBILE',
                'TECH2 MOBILE',
                'TECH1 MOBILE',
                'STRUCTURE DEFENSE',
                'SPECIALLOWPRI',
                'ALLUNITS',
            },
            TargetRestrictDisallow = 'UNTARGETABLE',
            TrackingRadius = 1,
            TurretBoneMuzzle = 'Attachpoint_Lrg_01',
            TurretBonePitch = 'Attachpoint_Lrg_01',
            TurretBoneYaw = 'Attachpoint_Lrg_01',
            TurretDualManipulators = false,
            TurretPitch = 0,
            TurretPitchRange = 90,
            TurretPitchSpeed = 190,
            TurretYaw = 0,
            TurretYawRange = 60,
            TurretYawSpeed = 190,
            Turreted = true,
            WeaponCategory = 'Direct Fire Experimental',
            WeaponRepackTimeout = 0,
            WeaponUnpacks = false,
       },
        {
            Damage = 100333,
            DamageFriendly = true,
            DamageRadius = 28,
            DamageType = 'Normal',
            DisplayName = 'Air Crash',
            DummyWeapon = true,
            FiringTolerance = 2,
            Label = 'DeathImpact',
            WeaponCategory = 'Death',
        },
    },
    Wreckage = {
        Blueprint = '/props/DefaultWreckage/DefaultWreckage_prop.bp',
        EnergyMult = 0,
        HealthMult = 0.9,
        MassMult = 0.1,
        ReclaimTimeMultiplier = 1,
        WreckageLayers = {
            Air = false,
            Land = true,
            Seabed = false,
            Sub = false,
            Water = false,
        },
    },
}
Check out my 2 maps: "Survival_Mayhem&BO_3d_v1" "Survival_Mayhem&BO_3d_RPG"
as well as my mod: "Survival Mayhem&BO balance"
-- let me know of any bugs or issues regarding those 3.
DDDX
Avatar-of-War
 
Posts: 170
Joined: 21 Mar 2016, 16:13
Has liked: 18 times
Been liked: 16 times
FAF User Name: DDDX

Re: Variable drones number based on enhancement

Postby Franck83 » 05 Nov 2018, 16:09

Can you post the mod file ? So i can test changes, go to error line number and so on...
Alliance of Heroes Mod is out ! Try it ! It's in the Mod Vault !
User avatar
Franck83
Evaluator
 
Posts: 538
Joined: 30 Dec 2016, 11:59
Location: France
Has liked: 114 times
Been liked: 122 times
FAF User Name: Franck83

Re: Variable drones number based on enhancement

Postby DDDX » 05 Nov 2018, 17:21

http://rgho.st/6V5B6z7Yp --script file
http://rgho.st/7JCpjhp4H --blueprints

that's all you need for the unit to work (be sure to have BO Unleashed and TMayhem mods because the files reference them, but i am pretty sure you do already ;)
Personalshield is missing but who cares, that segment works.
Check out my 2 maps: "Survival_Mayhem&BO_3d_v1" "Survival_Mayhem&BO_3d_RPG"
as well as my mod: "Survival Mayhem&BO balance"
-- let me know of any bugs or issues regarding those 3.
DDDX
Avatar-of-War
 
Posts: 170
Joined: 21 Mar 2016, 16:13
Has liked: 18 times
Been liked: 16 times
FAF User Name: DDDX

Next

Return to Mods & Tools

Who is online

Users browsing this forum: No registered users and 1 guest