Login  Register
 



Post new topicReply to topic
 
Author Message
 PostPosted: 24 Mar, 2008 
 
User avatar

Joined: 15 Feb, 2007
Posts: 599
Location: Rockingham, Australia
Offline
Ok we've got the sticky for useful threads which I'm trying to keep up to date, and Manimal did suggest that a 'Script Toolbox' type thread would be useful, so, here it is.

Please post any helpful / handy scripts you currently use in your mod that solve various problems you've bumped into. Try to keep it short, to the point, and stripped of as much mod-related code as possible, to make it easy for the rest of us to just pick it up & use it.

Please use 1 post per script, so I can link each one to the list here:

How to find the path of your mod
How to pass data from sim to ui and back
How to selectively enable console commands in your mod (aka allowing 'cheat' type commands)

_________________
We are Supremilated
www.supremilated.com


Last edited by Pawz on 03 Mar, 2010, edited 3 times in total.

Top
 Profile  
 PostPosted: 24 Mar, 2008 
 
User avatar

Joined: 15 Feb, 2007
Posts: 599
Location: Rockingham, Australia
Offline
To get it started I'll post Manimal's handy script for finding the path to your mod.

Manimal wrote:
I noticed that you're naming explicitly the path to your mod.

Here is my little handy script that is subject to enhancements in a close future :

In case you need to get "dynamicaly" the path where your mod is currently installed in :

Code:
--[[################################################################################]]--
--[[#                                                                              #]]--
--[[# File      :  /hook/lua/modlocator.lua                                        #]]--
--[[#                                                                              #]]--
--[[# Author    : GPG Devs + Manimal                                               #]]--
--[[#                                                                              #]]--
--[[# Version   : 1                                                                #]]--
--[[#                                                                              #]]--
--[[# Revision  : 10 mars 2008                                                     #]]--
--[[#                                                                              #]]--
--[[# Summary   : Mod  Location scripts.                                           #]]--
--[[#                                                                              #]]--
--[[# Copyright : © 2008 Gas Powered Games, Inc. & Manimal  All rights reserved.   #]]--
--[[#                                                                              #]]--
--[[################################################################################]]--

-- given a MOD UID , returns mod location

local function GetActiveModLocation( mod_Id )
   for i, mod in __active_mods do
      if  mod_Id == mod.uid then
         LOG("MANIMAL\'s MOD LOCATOR INFO:  Active Mod Found (name="..(mod.name or 'unknown')..", UID="..(mod.uid or 'none')..", location = "..mod.location..")  .")
         return mod.location
      end
   end
    -- Signaler Echec  !
    LOG("MANIMAL\'s MOD LOCATOR WARNING:  Unable to get Mod Location ! Wrong or missing UID.")
   return {}
end

use it like this :
Code:
myModLocation =  GetActiveModLocation("1234-5678-9012-3456")
if myModLocation then
    import(myModLocation..'/lua/myScript.lua') --this should be defaulted when there is a missing mod location
end


Quiet simple and functional ! 8)

Note that the UID is fictive in this example, you need your own UID

See /mohodata/lua/mods.lua for more informations.


Manimal - feel free to post this again, with your own code so you can edit etc - I'm just borrowing this to get the toolbox started, if you will :)

_________________
We are Supremilated
www.supremilated.com


Top
 Profile  
 PostPosted: 24 Mar, 2008 
 
User avatar

Joined: 15 Feb, 2007
Posts: 599
Location: Rockingham, Australia
Offline
NovaPrim3 wrote:
Thanks for that Chirmaya, I saw a similar post by you with the 'LoadSilverPetals' thing, but I've finally managed to get my head around it.

I'm going to summarise Sim to UI and UI to Sim data transfers, in a situation that has nothing to do with maps or units. Hope this helps.


--- SIM LAYER --
/lua/someSim.lua
Code:
# You'd generally call this function as a thread from /hook/lua/simInit.lua
function mainThread()
  # send data to UI
  Sync.SomeData = "Hello UI"
end

function fromUI(args)
  # receiving data from the UI
  print(args)
end


/hook/lua/SimCallbacks.lua
Code:
Callbacks.SendToSim = import('/mods/ModName/lua/someSim.lua').fromUI


--- UI LAYER ---
/modules/someModule.lua
Code:
function someButtonClick()
  SimCallback( { Func = "SendToSim", Args = "Hello Sim" } )
end

function fromSim(args)
  # receiving data from the Sim
  print(args)
end


/hook/lua/UserSync.lua
Code:
local baseOnSync = OnSync

function OnSync()
  baseOnSync()

  if Sync.SomeData then
    import('/mods/ModName/modules/someModule.lua').fromSim(Sync.SomeData)
  end
end


That's it, for the hooked files,
/hook/lua/SimCallbacks.lua
/hook/lua/UserSync.lua
that's all you need in them, remembering they are hooked so there is more behind them. Your module file and your sim file of course will have a lot more to them.

If you want to pass more than one argument between the sim and UI, use arrays (as Chirmaya was doing above), ie:
Sync.SomeData = { "Hello", "World }


Good luck!

_________________
We are Supremilated
www.supremilated.com


Top
 Profile  
 PostPosted: 03 Apr, 2008 
 
Forum Scout
Forum Scout
User avatar

Joined: 18 Feb, 2007
Posts: 493
Location: Gone
Offline
Below is a new version of my selective cheats code that Pawz posted earlier. He is going to remove that copy so I can keep this one updated.

Detect if mod is running under FA. Useful if you want to write code that works in both versions
Code:
-- Set global variable FA to true if we are playing Forged Alliance
FA = string.sub(GetVersion(),1,3) == '1.5'


Selectively activating cheats (requires FA variable above). This code is designed for when you need some cheats to work but not others. Cheating must still be enabled in the lobby before the game starts.

Code:
-- if one of these strings appears anywhere in the command string it is a cheat
cheatStrings = {
   'setfocusarmy',
   'createentity',
   'createunit',
   'copy',
   'add',
   'blingbling',
   'sallyshears',
   'sim',
   'execute',
   'teleport',
   'destroy',
   'kill',
   'ai_',
}

function IsCheat( cmd )
   -- returns false or the position a cheat was found (true)
   local cheatFound = false
   if cmd then
      cmd = string.lower(cmd)
      for _,cheat in cheatStrings do
         cheatFound = string.find( cmd , cheat )
         if cheatFound then break end
      end
   end
   return cheatFound
end

-- CATCH CONSOLE CHEATERS
local oldConExecute = ConExecute
function ConExecute( cmd )
   if IsCheat( cmd ) then
      print('Haa ha! You tried to cheat and I stopped you.')
   else
      oldConExecute( cmd )
   end
end

local oldConExecuteSave = ConExecuteSave
function ConExecuteSave( cmd )
   if IsCheat( cmd ) then
      print('Haa ha! You tried to cheat and I stopped you.')
   else
      oldConExecuteSave( cmd )
   end
end

-- STOP KEYBINDING CHEATERS
local oldIN_AddKeyMapTable = IN_AddKeyMapTable
function IN_AddKeyMapTable(keyMapTable)
   -- remove keys that activate cheats
   LOG('Clearing cheats from added keymap.')
   local newKeyMapTable = {}
   for key,data in keyMapTable do
      if IsCheat( data.action ) then
         LOG('Keybinding ['..key..'] = '..data.action..' removed because it contains a cheat.')
      else
         newKeyMapTable[key] = data
      end
   end
   oldIN_AddKeyMapTable( newKeyMapTable )
end

-- REMOVE BOUND CHEATS
if FA then
   IN_ClearKeyMap()
   -- Add back all mapped keys and user prefs except cheats
   IN_AddKeyMapTable(import('/lua/keymap/keymapper.lua').GetKeyMappings(false))
else
   -- Remove all debug keys first
   local debugKeyMap = import('/lua/keymap/defaultKeyMap.lua').debugKeyMap
   IN_RemoveKeyMapTable(debugKeyMap)
   -- Now add them back with just the cheats removed
   IN_AddKeyMapTable(debugKeyMap)
end

_________________
I have left the community. To adopt one of my mods (Advanced Coop, Multiplayer Save, Advanced AI) or tools (Advanced Utils, Mod System Patch, Mod Installer) please PM me or visit http://warriorhut.org/forged_alliance


Top
 Profile  
 PostPosted: 29 Apr, 2008 
 
User avatar

Joined: 11 Apr, 2007
Posts: 1915
Offline
Thank you Pawz !

Here is the handy script that allows to get any NEW textures to show up ingame, such as strategic icons and new panels (for referencen, see my functional scripts+textures in SupCivs), in a very conveninent way as you won't have to tell the script where it is located !
WARNING:
I do not recommend this method for compatibility reasons.
Enabling the shadow folder could cause textures from other mod to be overwritten.
There is no way to know what mod will overwrite another mod, and in which order this will occur...
:?


[SC][FA] Data Path Mount Points script

This is a revised version that works so great since I added a very simple test to my previous release.

The main great advantage is that you won't need to alter a single line of the scripts in order your mod show up your own strategic icons and other home cooked textures ! 8)

Keeping this version of SupComDataPath.lua should not bring conflicts between mods.
You can leave it "on" permanently in the bin folder, it won't cause any troubles even with no mods enabled+selected.

Please support my patch request that concerns this file among others.

Code:
--[[################################################################################
#                                                                              #
# File      : Forger Alliance/bin/SupComDataPath.lua                           #
#                                                                              #
# Author    : GPG Devs + Manimal                                               #
#                                                                              #
# Version   : 1                                                                #
#                                                                              #
# Revision  : 28 avril 2008                                                    #
#                                                                              #
# Summary   : Data Path Mount Points script.                                   #
#                                                                              #
# Copyright : © 2007 Gas Powered Games, Inc. & Manimal  All rights reserved.   #
#                                                                              #
################################################################################]]--



path = {}



local function mount_dir( dir, mountpoint )
    table.insert(path, { dir = dir, mountpoint = mountpoint } )
end



local function mount_contents(dir, mountpoint)

    LOG('checking ' .. dir)

    for _,entry in io.dir(dir .. '\\*') do
        if entry != '.' and entry != '..' then

            local mp = string.lower(entry)

            # string.gsub ( string, pattern-to-find-in-string, substitution-string )
            mp = string.gsub( mp, '[.]scd$', '' )
            mp = string.gsub( mp, '[.]zip$', '' )

            mount_dir( dir .. '\\' .. entry, mountpoint .. '/' .. mp )

            # Added here the missing mountpoints
         if mountpoint== '/mods' then
            mount_dir( dir .. '\\' .. entry .. '\\textures', '/textures' )
         end;
        end
    end
end




mount_contents(SHGetFolderPath('PERSONAL') .. 'My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\mods', '/mods')
mount_contents(SHGetFolderPath('PERSONAL') .. 'My Games\\Gas Powered Games\\Supreme Commander Forged Alliance\\maps', '/maps')

mount_dir(InitFileDir .. '\\..\\gamedata\\*.scd', '/')
mount_dir(InitFileDir .. '\\..', '/')



hook = {
    '/hook',
    '/schook'
}



protocols = {
    'http',
    'https',
    'mailto',
    'ventrilo',
    'teamspeak',
    'daap',
    'im',
}

_________________
Console Plus - Solo A.C.U. - Experimental Wars Image


Last edited by Manimal on 31 Jan, 2009, edited 4 times in total.

Top
 Profile  
 PostPosted: 01 Aug, 2008 
 
User avatar

Joined: 11 Apr, 2007
Posts: 1915
Offline
[FA] Adjacency Check Revisited

I found among some other script parts that function AdjacencyCheck from lua/editor/UnitCountBuildConditions.lua works on a unit ID, and it's uniquely the UEF ones on the top !!! :shock:
You could get an error poping out even if your work is correct.

So I rewrote it for my own use in a more abstracted way, by using the existing data that are stored in BuildingTemplates.
By using my little fixture below, this will occur no more as it works with the related faction's unit instead, whatever its ID is. (custom units will be "seen" too) 8)


Remark:
I noticed that SkirtSizeX and SkirtSizeZ have not default values, so I added tests in order to avoid annoying errors. (I know, this is a cheap solution but it works)


How to use this :

Put this code in a copy of lua/editor/UnitCountBuildConditions.lua then drop it in the hook folder of your mod
Change the build conditions in all of your templates (there are few only :))
examples taken from lua/AI/AIBuilders/AIEconomicBuilders.lua:
Code:
--Now it won't work on 'ueb1106' (only!!), instead it will work with 'MASSSTORAGE' !
{ UCBC, 'AdjacencyCheck', { 'LocationType', 'MASSEXTRACTION TECH3', 100, 'MASSSTORAGE' } },


Code:
--Now it won't work on 'ueb1105' (only!!), instead it will work with 'ENERGYSTORAGE' !
{ UCBC, 'AdjacencyCheck', { 'LocationType', 'ENERGYPRODUCTION TECH3', 100, 'ENERGYSTORAGE' } },



Scripting it:

First of all, it needs to know the path to the file named BuildingTemplates:

Code:
--my little handy function will get the path

GetMyMod = function( byName, byUID, byAuthor )
    for i, mod in __active_mods do
        if (byName   and ( byName   == mod.name   ))
        or (byUID    and ( byUID    == mod.uid    ))
        or (byAuthor and ( byAuthor == mod.author )) then
            LOG("MANIMAL\'s DEBUG: Mod Location = "..mod.location)
            return mod
        end
    end
   WARN("MANIMAL\'s MOD LOCATOR:  Unable to get Mod Infos ! Either your mod is not installed or you have mistyped its name, UID or author.")
   return {}
end

-- UID de SupCivs Beta
local MyModInfos = GetMyMod( false, "3415261C-75B7-11DC-A11D-A05155D89593", false )
local MyModDir  = MyModInfos.location
local MyHookDir = MyModDir..MyModInfos.hookdir

local BuildingTemplates = import( MyHookDir .. '/lua/BuildingTemplates.lua' ).BuildingTemplates



Now here is the newly rewrote function:

Code:
# ======================================================================================= #
#     Adjacency Check - Ensures a building category can have something adjacent to it     #
#                                                                                         #
#     Altered by Manimal - Now works with a building template instead of unit ID !        #
# ======================================================================================= #

function AdjacencyCheck( aiBrain, locationType, category, radius, testCatUnit )
    local factoryManager = aiBrain.BuilderManagers[locationType].FactoryManager
    if not factoryManager then
        WARN('*AI WARNING: FactoryCapCheck - Invalid location - ' .. locationType)
        return false
    end

    local testCat = category
    if type(category) == 'string' then
        testCat = ParseEntityCategory(category)
    end
   
    local reference  = AIUtils.GetOwnUnitsAroundPoint( aiBrain, testCat, factoryManager:GetLocationCoords(), radius )
    if not reference or table.getn(reference) == 0 then
       return false
   end
   
    local factionIndex = aiBrain:GetFactionIndex()

   ## #######################################################################################################
   ## Given a faction, get the building unit from BuildingTemplates !
   ## #######################################################################################################

   local GetBuildingIDfromCategory = function ( factionIndex, category )
      if type(category) == 'string' and factionIndex and factionIndex > 0 then
         for indF, faction in BuildingTemplates do
            if indF == factionIndex then
               for i, structUnit in faction do
                  if structUnit[1] and structUnit[1] ~= "" and string.upper(structUnit[1]) == category then
                     --LOG("¤¤¤ MANIMAL\'s DEBUG:  UnitCountBuildConditions.lua -> AdjacencyCheck: GetBuildingIDfromCategory VERIFICATION DES DONNÉES :")
                     --LOG("¤¤¤ ----->  structUnit[1]="..structUnit[1])   ## e.g. structUnit[1]='MASSEXTRACTION'
                     --LOG("¤¤¤ ----->  structUnit[2]="..structUnit[2])   ## e.g. structUnit[2]='MassStorage'
                     return structUnit[2]
                  end
               end
            end
         end
      end
      return nil    --FAILURE : either Category or structureUnit don't exist
   end
   
   local testUnit = GetBuildingIDfromCategory( factionIndex, testCatUnit )
   if not testUnit or testUnit == nil then
      WARN("¤¤¤ MANIMAL\'s DEBUG:  UnitCountBuildConditions.lua -> AdjacencyCheck: GetBuildingIDfromCategory FAILURE => unable to check Adjacency !")
      return false
   end

   ## #######################################################################################################

    local template = {}   
    local unitSize = aiBrain:GetUnitBlueprint( testUnit ).Physics
   
   if unitSize.SkirtSizeX == nil then
      WARN("¤¤¤ MANIMAL\'s DEBUG:  UnitCountBuildConditions.lua -> AdjacencyCheck:  unitSize.SkirtSizeX is NIL ! testUnit="..repr(testUnit) or "HAS NO AVAIBLE INFOS !!!")
      return false
   end
   if unitSize.SkirtSizeZ == nil then
      WARN("¤¤¤ MANIMAL\'s DEBUG:  UnitCountBuildConditions.lua -> AdjacencyCheck:  unitSize.SkirtSizeZ is NIL ! testUnit="..repr(testUnit) or "HAS NO AVAIBLE INFOS !!!")
      return false
   end
   
    for k,v in reference do
        if not v:IsDead() then
            local targetSize = v:GetBlueprint().Physics
            local targetPos = v:GetPosition()
         
         local myUnit = v:GetBlueprint()
         if targetSize.SkirtSizeX == nil then
            WARN("¤¤¤ MANIMAL\'s DEBUG:  UnitCountBuildConditions.lua -> AdjacencyCheck:  targetSize.SkirtSizeX is NIL ! unit="..myUnit.General.UnitName or myUnit.Interface.HelpText or myUnit.Interface.Description or "HAS NO AVAIBLE INFOS !!!".."  v="..repr(v))
            return false
         end
         if targetSize.SkirtSizeZ == nil then
            WARN("¤¤¤ MANIMAL\'s DEBUG:  UnitCountBuildConditions.lua -> AdjacencyCheck:  targetSize.SkirtSizeZ is NIL ! unit="..myUnit.General.UnitName or myUnit.Interface.HelpText or myUnit.Interface.Description or "HAS NO AVAIBLE INFOS !!!".."  v="..repr(v))
            return false
         end
            targetPos[1] = targetPos[1] - (targetSize.SkirtSizeX/2)
            targetPos[3] = targetPos[3] - (targetSize.SkirtSizeZ/2)
         
            # Top/bottom of unit
            for i=0,((targetSize.SkirtSizeX/2)-1) do
                local testPos = { targetPos[1] + 1 + (i * 2), targetPos[3]-(unitSize.SkirtSizeZ/2), 0 }
                local testPos2 = { targetPos[1] + 1 + (i * 2), targetPos[3]+targetSize.SkirtSizeZ+(unitSize.SkirtSizeZ/2), 0 }
                table.insert( template, testPos )
                table.insert( template, testPos2 )
            end
            # Sides of unit
            for i=0,((targetSize.SkirtSizeZ/2)-1) do
                local testPos = { targetPos[1]+targetSize.SkirtSizeX + (unitSize.SkirtSizeX/2), targetPos[3] + 1 + (i * 2), 0 }
                local testPos2 = { targetPos[1]-(unitSize.SkirtSizeX/2), targetPos[3] + 1 + (i*2), 0 }
                table.insert( template, testPos )
                table.insert( template, testPos2 )
            end
        end
    end
   
    for k,v in template do
        if aiBrain:CanBuildStructureAt(testUnit, { v[1], 0, v[2] } ) then
            return true
        end
    end
    return false
end

_________________
Console Plus - Solo A.C.U. - Experimental Wars Image


Top
 Profile  
 PostPosted: 14 Sep, 2008 
 
User avatar

Joined: 09 Feb, 2008
Posts: 44
Location: France
Offline
[FA] Save & Restore selected construction tabs & command mode

UISelectionByCategory & SelectUnits reset construction context (if one of these function is called while you try to do an upgrade on ACU for exemple, the construction tab is displayed)

construction.lua must be hooked as follow

Code:
-- File: hook/lua/ui/game/construction.lua
-- Author: FuryNik
-- Summary: Add SaveCheckedTab & RestoreCheckedTab
-- Version: 0.1
-- Revision
--   0.1   09-09-2008  Creation

local savedTab = false
local savedNestedTab = false

function SaveCheckedTab()
    savedTab = false
    savedNestedTab = false

    if controls.constructionTab._checkState == 'checked' then
        savedTab = 'construction'
    end
    if controls.selectionTab._checkState == 'checked' then
        savedTab = 'selection'
    end
    if controls.enhancementTab._checkState == 'checked' then
        savedTab = 'enhancement'
    end
    if GetTabByID('LCH') and GetTabByID('LCH'):IsChecked() then
        savedNestedTab = 'LCH'
    end
    if GetTabByID('Back') and GetTabByID('Back'):IsChecked() then
        savedNestedTab = 'Back'
    end
    if GetTabByID('RCH') and GetTabByID('RCH'):IsChecked() then
        savedNestedTab = 'RCH'
    end
    if GetTabByID('templates') and GetTabByID('templates'):IsChecked() then
        savedNestedTab = 'templates'
    end
    if GetTabByID('t1') and GetTabByID('t1'):IsChecked() then
        savedNestedTab = 't1'
    end
    if GetTabByID('t2') and GetTabByID('t2'):IsChecked() then
        savedNestedTab = 't2'
    end
    if GetTabByID('t3') and GetTabByID('t3'):IsChecked() then
        savedNestedTab = 't3'
    end
    if GetTabByID('t4') and GetTabByID('t4'):IsChecked() then
        savedNestedTab = 't4'
    end
end

function RestoreCheckedTab()
    if not savedTab then
        return
    end
    if savedTab == 'construction' and controls.constructionTab._checkState != 'checked' then
        controls.constructionTab:ToggleCheck()
    end
    if savedTab == 'selection' and controls.selectionTab._checkState != 'checked' then
        controls.selectionTab:ToggleCheck()
    end
    if savedTab == 'enhancement' and controls.enhancementTab._checkState != 'checked' then
        controls.enhancementTab:ToggleCheck()
    end
    lastCheckedTab = savedTab
    savedTab = false
    if savedNestedTab then
        GetTabByID(savedNestedTab):SetCheck(true)
    end
end


Usage example :
Code:
  import('/lua/ui/game/construction.lua').SaveCheckedTab()
  local selectedUnits = GetSelectedUnits()
  local commandmode = import('/lua/ui/game/commandmode.lua')
  local currentCommand = commandmode.GetCommandMode()

  UISelectionByCategory("ALLUNITS", false, false, false, false)
  for _, unit in (GetSelectedUnits() or {}) do
    unitsList[unit:GetEntityId()] = unit
  end
 
  SelectUnits(selectedUnits)
  import('/lua/ui/game/construction.lua').RestoreCheckedTab()
  commandmode.StartCommandMode(currentCommand[1], currentCommand[2])


Hope this helps


Top
 Profile  
 PostPosted: 27 Sep, 2008 
 
User avatar

Joined: 15 Feb, 2007
Posts: 599
Location: Rockingham, Australia
Offline
Found this while browsing through some older threads - could be handy

Railgun Weapon (Passes through multiple units) script

Quote:
Projectile-script:

Code:
OnImpactDestroy = function( self, targetType, targetEntity )

   if targetEntity and not IsUnit(targetEntity) then
      NRailgunProjectilePolytrail.OnImpactDestroy(self, targetType, targetEntity)
      return
   end
   
   if self.counter then
      if self.counter >= 3 then
         NRailgunProjectilePolytrail.OnImpactDestroy(self, targetType, targetEntity)
         return
      else
         self.counter = self.counter + 1
      end
   else
      self.counter = 1
   end
   if targetEntity then
self.lastimpact = targetEntity:GetEntityId() #remember what was hit last
end
end,
}


addet text in unit.lua :
Code:
Code:
local oldUnit=Unit
Unit = Class(oldUnit) {
OnCollisionCheck = function(self, other, firingWeapon)
      if other.lastimpact and other.lastimpact == self:GetEntityId() then return false end
        return oldUnit.OnCollisionCheck(self, other, firingWeapon)
    end,
}


_________________
We are Supremilated
www.supremilated.com


Top
 Profile  
 PostPosted: 24 Nov, 2008 
 
User avatar

Joined: 28 Feb, 2007
Posts: 918
Offline
I'm gonna post several scripts, and I rather not put each in a seperate post.

Using methods on strings :

Comment the line metacleanup('') in mohodata/lua/system/config.lua.
Now you can do things like :
Code:
local s = ''
local slen = s:len()

or

local slen = (''):len() # '':len() is invalid syntax


I find it a lot easier than typing string.len(s).

Ignore errors when accessing nil values :

Open mohodata/lua/system/config.lua, and look for the globalsmeta table around line ~50. Comment the line that calls error(). Accessing nil values no longer cause scripts to halt.
This helps a lot, sometimes I need to check for a value, and it's not 100% that its set yet, and it would halt the script normally. Quite stupid imho.
Replacing error with WARN is good too.

Lua only classes:

This is an implementation to support Destroy() on lua-only classes.
Your new class should only override OnCreate() and OnDestroy() .

Code:
--[[
   Support for LUA-only objects.
--]]
local oldIsDestroyed = IsDestroyed
function IsDestroyed(obj)
   return obj.__IsDestroyed or oldIsDestroyed(obj)
end

--[[
   This is a base class for LUA-only classes to support Destroy

().
   OnCreate and OnDestroy should be overloaded.
   Includes ForkThread.
--]]
LuaClass = Class {
   __init = function(self, spec)
      self._trash = TrashBag()
      self:OnCreate(spec)
   end,
   
    ForkThread = function(self, fn, ...)
        if fn then
            local thread = ForkThread(fn, self, unpack(arg))
            self._trash:Add(thread)
            return thread
        else
            return nil
        end
    end,
   
    --[[
       Override the object's metatable, when index is accessed, it'll

return nil and LOG a WARN.
    --]]
   Destroy = function(self)
      self:OnDestroy()
      local destroyedFrom = debug.traceback('Object has been

destroyed from:')
      local oldMeta = getmetatable(self)
      metatable = {   
         __index = function(self, key)
            local _type = type(rawget(oldMeta,

key))
            WARN('Tried to access key: [' .. key

.. ' = ' .. _type ..  '] but object was destroyed\n' .. destroyedFrom)
            return nil
         end,
      }
      setmetatable(self, metatable)
      self.__IsDestroyed = true
      self._trash:Destroy()
   end,
   
   OnCreate = function(self, spec)
   end,
   
   OnDestroy = function(self)
   end,
}


Removing the annoying \000 in logs:

Code:
# removes the \000 when passing multiple arguments, arguments are

concatenated with ' '

local oldLOG = LOG
function LOG(...)
   local joined = (' '):join(arg)
   oldLOG(joined)
end

local oldWARN = WARN
function WARN(...)
   local joined = (' '):join(arg)
   oldWARN(joined)
end

local oldSPEW = SPEW
function SPEW(...)
   local joined = (' '):join(arg)
   oldSPEW(joined)
end

local oldError = error
function error(...)
   local joined = (' '):join(arg)
   oldError(joined)
end

# same as python's ''.join(list)
function string.join(str, tbl)
   local s = ''
   # sometimes the arg from LOGs are 'dirty' and the 'real' values can be unpacked with unpack
   local args = {unpack(tbl)}
   for k, arg in args do
      s = s .. tostring(arg) .. str
   end
   return s
end


Convert a quaternion to euler roll, pitch, yaw

Code:
#
# Convert a quaternion value to euler degrees.
#
function QuaternionToEuler(quaternion)
   local qx, qy, qz, qw = unpack(quaternion)
   
   local ys = (2*qy*qw) - (2*qx*qz)
   local yc = 1 - (2 * math.pow(qy, 2)) - (2 * math.pow(qz, 2))
   local yaw = math.atan2(ys, yc)
   
   local pitch = math.asin(2*qx*qy + 2*qz*qw)
   
   local rs = (2*qx*qw ) - (2*qy*qz)
   local rc = 1 - (2 * math.pow(qx, 2)) - (2 * math.pow(qz, 2))
   local roll = math.atan2(rs, rc)
   return pitch, roll, yaw
end


Get camera position in the world:

Code:
--[[
   Get the camera position in the game world.
   returns x, y, z
--]]
function GetCameraWorldPos(camera)
   if not camera then
      camera = GetCamera('WorldCamera')
   end
   local cSettings = camera:SaveSettings()
   local x, y, z = unpack(cSettings.Focus)
   local heading = cSettings.Heading
   local pitch = cSettings.Pitch
   local zoom = cSettings.Zoom
   local height = math.sin(pitch) * zoom
   local base = math.cos(pitch) * zoom
   return x + (math.cos(heading) * base), y+height, z + (math.sin(heading) * base)
end


Top
 Profile  
 PostPosted: 31 Jan, 2009 
 
User avatar

Joined: 11 Apr, 2007
Posts: 1915
Offline
Mod Locator (better explained)

I noticed that you're naming explicitly the path to your mod.

Here is my little handy script that is subject to enhancements in a close future :

In case you need to get "dynamicaly" the path where your mod is currently installed in :

Make a copy of /hook/lua/game.lua and add the following portion at its "top" part, below commented out file descriptor

Code:
local myMod_UID = "123456787-1234-1234-1234-0123456789ab"  --UID of The Mod WARNING : CASE SENSITIVE

--[[################################################################################
    # Manimal's Mod Locator  script                                                #   
    # The functionMyActiveModLocation = function( byName, byUID, byAuthor ) will   #
   # avoid making a list of units which is not convenient to be kept updated each #   
    # time someone creates and add a new unit in his mod.                          #   
    # This function will require the current Mod's UID ONLY in order to get the    #   
    # current active mod's location, that's more convenient as it won't change.    #   
    # It could work also by mod NAME or AUTHOR name.                               #   
    ################################################################################]]--

local GetMyActiveMod = function( byName, byUID, byAuthor )
   for i, leMod in __active_mods do
      if (byName   and ( byName   == leMod.name   ))
      or (byUID    and ( byUID    == leMod.uid    ))
      or (byAuthor and ( byAuthor == leMod.author )) then
         --LOG("MANIMAL\'s DEBUG: Mod infos = "..repr(leMod))
         return leMod
      end
   end
   WARN("MANIMAL\'s MOD FINDER:  Unable to get Mod Infos ! Either your mod is not installed or you have mistyped its name, UID or author.")
   return {}
end

local GetMyActiveModLocation = function( leMod )
   if leMod and (type(leMod) == 'table') then
      --LOG("MANIMAL\'s DEBUG: Mod Location = " .. leMod.location)
      return leMod.location
   end
   WARN("MANIMAL\'s MOD LOCATOR:  Unable to get Mod Infos ! Either your mod is not installed or you have mistyped its name, UID or author.")
   return ""
end

# GET and STORE the PATH for Later Access :D
MonMod = GetMyActiveMod( false, myMod_UID, false )
MyModPath = GetMyActiveModLocation( MonMod )


Then insert the following portion in any LUA that needs it :
Code:
local Game = import('/lua/game.lua')
local MyModPath = Game.MyModPath


example of an altered version of uiutils.lua that will allow your own strategic icons to show up (among others):
Code:
function UIFile(filespec)
    --local skins = import('/lua/skins/skins.lua').skins
    local visitingSkin = currentSkin()
    local currentPath = skins[visitingSkin].texturesPath

    if visitingSkin == nil or currentPath == nil then
        return nil
    end
   
   # =================================
    # TRAITER LES SKINS ORIGINAUX EN PREMIER.
   # Traiter les skins du Mod ensuite.
   # ======================================
    if visitingSkin == 'default' then -- if current skin is default, then don't bother trying to look for it, just append the default dir
        local curFile = currentPath .. filespec
      if DiskGetFileInfo(curFile) then
         return curFile
      else
         curFile = MyModPath .. curFile
         if DiskGetFileInfo(curFile) then
            return curFile
         end
      end
    else
        while visitingSkin do
            local curFile = currentPath .. filespec
            if DiskGetFileInfo(curFile) then
                return curFile
            else
            curFile = MyModPath .. curFile
            if DiskGetFileInfo(curFile) then
               return curFile
            else
               visitingSkin = skins[visitingSkin].default
               if visitingSkin then currentPath = skins[visitingSkin].texturesPath end
            end
            end
        end
    end

    WARN('Warning: uiutil.lua -> UIFile: Unable to find file ', filespec)
    -- pass out the final string anyway so resource loader can gracefully fail
    return filespec
end



Quiet simple and functional ! 8)

Note that the UID is fictive in this example, you need your own UID

See /mohodata/lua/mods.lua for more informations.

Please keep the credits as is and eventually keep me informed of any significant changes / enhancements you brought to my script.

_________________
Console Plus - Solo A.C.U. - Experimental Wars Image


Last edited by Manimal on 23 May, 2010, edited 2 times in total.

Top
 Profile  
 PostPosted: 31 Jan, 2009 
 

Joined: 13 Jun, 2008
Posts: 729
Offline
The table below will allow to recreate the in-game map info dialog.
SessionGetScenarioInfo() will return the table.

furynik wrote:
Code:
SessionGetScenarioInfo = {
  Configurations={
    standard={
      customprops={ ExtraArmies="ARMY_9 NEUTRAL_CIVILIAN" },
      teams={ { armies={ "ARMY_1", "ARMY_2" }, name="FFA" } }
    }
  },
  Options={
    AllowObservers=true,
    CheatsEnabled="false",
    CivilianAlliance="enemy",
    FogOfWar="explored",
    GameSpeed="normal",
    NoRushOption="Off",
    PrebuiltUnits="Off",
    ScenarioFile="/maps/x1mp_002/x1mp_002_scenario.lua",
    TeamLock="unlocked",
    TeamSpawn="fixed",
    Timeouts="3",
    UnitCap="500",
    Victory="sandbox"
  },
  description="<LOC X1MP_002_Description>In the waning days of the Earth Empire, this was the location where Commander Williamson valiantly stood his ground against the first Aeon invasion. Recent events have transformed Commander Williamson and the Bridge he once defended into symbols of hope and valor for the UEF people.",
  map="/maps/X1MP_002/X1MP_002.scmap",
  name="Williamson's Bridge",
  norushoffsetX_ARMY_1=0,
  norushoffsetX_ARMY_2=0,
  norushoffsetY_ARMY_1=0,
  norushoffsetY_ARMY_2=0,
  norushradius=75,
  preview="",
  save="/maps/X1MP_002/X1MP_002_save.lua",
  script="/maps/X1MP_002/X1MP_002_script.lua",
  size={ 256, 256 },
  starts=true,
  type="skirmish"
}


_________________
TVg V5 Alpha Testers Wanted!
Image
Bulletstorm released
other mods


Top
 Profile  
 PostPosted: 31 Jan, 2009 
 

Joined: 13 Jun, 2008
Posts: 729
Offline
furynik wrote:
Well, the ARMY_x match the start pos on the map and this is a code to get the list of all units without selecting units :

/mods/<modname>/hook/lua/ui/game/scoreaccum.lua
Code:
-- File: scoreaccum.lua
local original_UpdateScoreData = UpdateScoreData

function UpdateScoreData(newData)
  original_UpdateScoreData(newData)
 
  import('/mods/<modname>/lib/score.lua').UpdateScoreData(newData)
end


/mods/<modname>/lib/score.lua
Code:
-- File: score.lua
local scoreData = {}

function UpdateScoreData(newData)
  scoreData = table.deepcopy(newData)
end

function GetScoreData()
  return scoreData
end


/mods/<modname>/lib/units.lua
Code:
-- File: units.lua
local GetScoreData = import('/mods/<modname>/lib/score.lua').GetScoreData

-- return the table of all existing units
function GetAllUnits()
  local unitsList = {}
  local newCount = 0
  local unit = nil
  local id = 0
-- get unit count in the score data
  local curCount = GetScoreData()[GetFocusArmy()].general.currentunits.count

-- loop until unit count reached
  while newCount < curCount do
    unit = GetUnitById(id)
    if unit != nil then
      unitsList[newCount] = unit
      newCount = newCount + 1
    end
    id = id + 1
  end
--    LOG('Units management: units list: ', repr(unitsList))
  return unitsList
end

_________________
TVg V5 Alpha Testers Wanted!
Image
Bulletstorm released
other mods


Top
 Profile  
 PostPosted: 01 Apr, 2009 
 
User avatar

Joined: 01 May, 2007
Posts: 4219
Offline
Carrier and Drone Scripts...

Resin_Smoker

Carrier Script

Code:
#****************************************************************************
#**
#**  File     :  URA0305_script.lua
#**  Author   :  Resin_Smoker, Optimus Prime
#** 
#**  Summary  :  Cybran Retribution, Airborne Drone Carrier
#**
#**  Special Thanks to :  ChirmayaWrongEmail, Eni, Neruz, Goom, Gilbot-X
#**
#**  Copyright © 2009, 4th Dimension
#****************************************************************************

#### Localy imported files ####
local CAirUnit = import('/lua/cybranunits.lua').CAirUnit

#### Weapon local files ####
local CollisionBeamFile = import('/mods/4th_Dimension_201/hook/lua/ura0305_defaultcollisionbeams.lua')
local DefaultBeamWeapon = import('/lua/sim/defaultweapons.lua').DefaultBeamWeapon
LaserBeamWeapon = Class(DefaultBeamWeapon) {
    BeamType = CollisionBeamFile.RetributionGreenLaserCollisionBeam,
    FxMuzzleFlash = {},
}
local CDFProtonCannonWeapon = import('/lua/cybranweapons.lua').CDFProtonCannonWeapon
local CAAMissileNaniteWeapon = import('/lua/cybranweapons.lua').CAAMissileNaniteWeapon

URA0305 = Class(CAirUnit) {

    Weapons = {
        TriCannon = Class(CDFProtonCannonWeapon) {},
        GreenLaser = Class(LaserBeamWeapon) {},
        AA_Front_L = Class(CAAMissileNaniteWeapon) {},
        AA_Front_R = Class(CAAMissileNaniteWeapon) {},
        AA_Rear_L = Class(CAAMissileNaniteWeapon) {},
        AA_Rear_R = Class(CAAMissileNaniteWeapon) {},
    },

    ExhaustBones = {
                    'engine_center01','engine_center02','engine_center03','engine_center04','engine_center05','engine_center06',
                    'engine_left01','engine_left02','engine_left03','engine_left04','engine_left05','engine_left06',
                    'engine_right01','engine_right02','engine_right03','engine_right04','engine_right05','engine_right06',
                   },

    BeamExhaustCruise = '/effects/emitters/gunship_thruster_beam_01_emit.bp',
    BeamExhaustIdle = '/effects/emitters/gunship_thruster_beam_01_emit.bp',

OnStopBeingBuilt = function(self,builder,layer)
    CAirUnit.OnStopBeingBuilt(self,builder,layer)
    ### Initializes Drone spawn sequence and radar jammer energy useage
    self:ForkThread(self.InitialDroneSpawn)
    self:SetMaintenanceConsumptionInactive()
    self:SetScriptBit('RULEUTC_StealthToggle', true)
    self:SetScriptBit('RULEUTC_ProductionToggle', false)
    self:RequestRefreshUI()
    self.UnitComplete = true
    self.Army = self:GetArmy()

    ### Drone Globals
    self.Side = 0
    self.DroneTable = {}

    ### Globals uses for target assists and counter attacks
    self.CurrentTarget = nil
    self.OldTarget = nil
    self.MyAttacker = nil
    self.Retaliation = false
end,

OnIntelEnabled = function(self)
    CAirUnit.OnIntelEnabled(self)
    ### Radar rotation on jammer activation
    if not self:IsDead() and not self.SpinManip then
        self.SpinManip = CreateRotator(self, 'radar_dish', 'y', nil, 0, 20, 100)
        self.Trash:Add(self.SpinManip)
    end
    if not self:IsDead() and self.SpinManip then
        self.SpinManip:SetTargetSpeed(100)
    end
end,

OnIntelDisabled = function(self)
    CAirUnit.OnIntelDisabled(self)
    ### Radar rotation halt on jammer de-activation
    if not self:IsDead() and self.SpinManip then
        self.SpinManip:SetTargetSpeed(0)
    end
end,

InitialDroneSpawn = function(self)
    ### spawning a number of drones times equal to the number preset by numcreate
    local numcreate = 8
    ### Randomly determines which launch bay will be the first to spawn a drone
    self.Side = Random(1,2)
    ### Short delay after the carrier has been built
    WaitSeconds(2)
    ### Are we dead yet, if not spawn drones
    if not self:IsDead() then
        for i = 0, (numcreate -1) do
            if not self:IsDead() then
                self:ForkThread(self.SpawnDrone)
                ### Short delay between spawns to spread them out
                WaitSeconds(1)
            end
        end
        ### Runs assist commands only after all of the drones have been built
        self:AssistHeartBeat()
    end
end,

SpawnDrone = function(self)
    ### Small respawn delay so the drones are not instantly respawned after death
    WaitSeconds(1)
    ### Only respawns the drones if the parent unit is not dead
    if not self:IsDead() then
        ### Sets up local Variables used and spawns a drone at the parents location
        local myOrientation = self:GetOrientation()     
        if self.Side == 1 then
            ### Gets the current position of the carrier launch bay in the game world
            local location = self:GetPosition('drone_launch_left')
            ### Creates our drone in the left launch bay and directs the unit to face the same direction as its parent unit
            local drone = CreateUnit('ura0106', self:GetArmy(), location[1], location[2], location[3], myOrientation[1], myOrientation[2], myOrientation[3], myOrientation[4], 'Air')
            ### Adds the newly created drone to the parent carriers drone table
            table.insert (self.DroneTable, drone)
            ### Sets the Carrier unit as the drones parent
            drone:SetParent(self, 'ura0305')
            drone:SetCreator(self) 
            ### Issues the move command
            IssueClearCommands({drone})
            local  destination = self:CalculateWorldPositionFromRelative({-5,0,30})
            IssueMove({drone}, destination)
            ### Flips from the left to the right self.Side after a drone has been spawned
            self.Side = 2
            ###Drone clean up scripts
            self.Trash:Add(drone)
        elseif self.Side == 2 then
            ### Gets the current position of the carrier launch bay in the game world
            local location = self:GetPosition('drone_launch_right')
            ### Creates our drone in the right launch bay and directs the unit to face the same direction as its parent unit
            local drone = CreateUnit('ura0106', self:GetArmy(), location[1], location[2], location[3], myOrientation[1], myOrientation[2], myOrientation[3], myOrientation[4], 'Air')
            ### Adds the newly created drone to the parent carriers drone table
            table.insert (self.DroneTable, drone)
            ### Sets the Carrier unit as the drones parent
            drone:SetParent(self, 'ura0305')
            drone:SetCreator(self)
            ### Issues the move command
            IssueClearCommands({drone})
            local  destination = self:CalculateWorldPositionFromRelative({5, 0, 30})
            IssueMove({drone}, destination)
            ### Flips from the right to the left self.Side after a drone has been spawned
            self.Side = 1
            ###Drone clean up scripts
            self.Trash:Add(drone)
        end
    end
end,

NotifyOfDroneDeath = function(self)
    ### Only respawns the drones if the parent unit is not dead
    if not self:IsDead() then
        local mass = self:GetAIBrain():GetEconomyStored('Mass')
        local energy = self:GetAIBrain():GetEconomyStored('Energy')
        ### Check to see if the player has enough mass / energy
        ### And that the production is enabled.
        if self:GetScriptBit('RULEUTC_ProductionToggle') == false and mass >= 100 and energy >= 1000 then
            ###Remove the resources and spawn a single drone
            self:GetAIBrain():TakeResource('Mass',100)
            self:GetAIBrain():TakeResource('Energy',1000)
            self:ForkThread(self.SpawnDrone)
        else
            ### If the above conditions are not met the carrier will wait a short time and try again
            self:ForkThread(self.EconomyWait)
        end
    end   
end,

EconomyWait = function(self)
    if not self:IsDead() then
        WaitSeconds(5)
        if not self:IsDead() then
            self:ForkThread(self.NotifyOfDroneDeath)
        end
    end
end,

AssistHeartBeat = function(self)
    while not self:IsDead() do
        WaitSeconds(1)   
        if not self:IsDead() and self.Retaliation == true and self.MyAttacker != nil then
            ### Clears flags if there is no longer a target to retaliate against thats in range
            if self.MyAttacker:IsDead() or self:GetDistanceToAttacker() >= 31 then
                ### Clears flag to allow retaliation on another attacker
                self.MyAttacker = nil
                self.Retaliation = false
            end
        end
        if not self:IsDead() and self.Retaliation == false and table.getn({self.MyAttacker}) > 0 and self:GetDistanceToAttacker() <= 30 then
            if not self.MyAttacker:IsDead() then
                ###Issues the retaliation command to each of the drones on the carriers table
                if table.getn({self.DroneTable}) > 0 then
                    for k, v in self.DroneTable do
                        IssueClearCommands({self.DroneTable[k]})
                        IssueAttack({self.DroneTable[k]}, self.MyAttacker)
                    end
                    ### Performs retaliation flag
                    self.Retaliation = true         
                end
            end
        elseif not self:IsDead() and self.Retaliation == false and self:GetTargetEntity() then
            ### Updates variable with latest targeting info
            self.CurrentTarget = self:GetTargetEntity()     
            ### Verifies that the carrier is not dead and that it has a target
            ### Ensures that either there hasnt been a target before or that its new
            ### To prevent the same retargeting command from being given out multible times
            if self.OldTarget == nil or self.OldTarget != self.CurrentTarget then   
                ### Updates the OldTarget to match CurrentTarget
                self.OldTarget = self.CurrentTarget       
                ###Issues the attack command to each of the drones on the carriers table
                if table.getn({self.DroneTable}) > 0 then
                    for k, v in self.DroneTable do
                        IssueClearCommands({self.DroneTable[k]})
                        IssueAttack({self.DroneTable[k]}, self.CurrentTarget)
                    end
                end
            end
        end
    end
end,

GetDistanceToAttacker = function(self)
    local tpos = self.MyAttacker:GetPosition()
    local mpos = self:GetPosition()
    local dist = VDist2(mpos[1], mpos[3], tpos[1], tpos[3])
    return dist
end,

OnDamage = function(self, instigator, amount, vector, damagetype)
    ### Check to make sure that the carrier isnt already dead and what just damaged it is a unit we can attack
    if self:IsDead() == false and damagetype == 'Normal' and self.MyAttacker == nil then
        ### only attack if retaliation not already active
        if IsUnit(instigator) then
            self.MyAttacker = instigator
        end
    end
    CAirUnit.OnDamage(self, instigator, amount, vector, damagetype)
end,

OnKilled = function(self, instigator, type, overkillRatio)
    ### Disables the laser beam after death
    local wep = self:GetWeaponByLabel('GreenLaser')
    for k, v in wep.Beams do
        v.Beam:Disable()
    end
    if self.BeamFX then
       self.BeamFX:Destroy()
    end
    ### Disables weapons after death
    self:SetWeaponEnabledByLabel('GreenLaser', false)
    self:SetWeaponEnabledByLabel('FrontCannon', false)
    self:SetWeaponEnabledByLabel('AA_Front_L', false)
    self:SetWeaponEnabledByLabel('AA_Front_R', false)
    self:SetWeaponEnabledByLabel('AA_Rear_L', false)
    self:SetWeaponEnabledByLabel('AA_Rear_R', false)   
    ### Small bit of table manipulation to sort thru all of the avalible drones and remove them after the carrier is dead
    if table.getn({self.DroneTable}) > 0 then
        for k, v in self.DroneTable do
            IssueClearCommands({self.DroneTable[k]})
            IssueKillSelf({self.DroneTable[k]})
        end
    end
    ### Removes radar spin effects
    if self.SpinManip then
        self.Trash:Add(self.SpinManip)
    end
    ### Final command to finish off the carriers death event
    CAirUnit.OnKilled(self, instigator, type, overkillRatio)
end,
}
TypeClass = URA0305


Drone Script

Code:
#****************************************************************************
#**
#**  File     :  URA0106_script.lua
#**  Author(s):  Resin_Smoker, Optimus Prime
#**
#**  Summary  :  Cybran Mosquito, Drone Gunship Script
#**
#**  Special Thanks to :  ChirmayaWrongEmail, Eni, Neruz, Goom, Gilbot-X, Sorian
#**
#**  Copyright © 2009
#****************************************************************************

#### Localy imported files ####
local CAirUnit = import('/lua/cybranunits.lua').CAirUnit
local EffectUtil = import('/lua/EffectUtilities.lua')
local util = import('/lua/utilities.lua')

#### Weapon local files ####
local CAAAutocannon = import('/lua/cybranweapons.lua').CAAAutocannon

URA0106 = Class(CAirUnit) {
    Weapons = {
        MainGun = Class(CAAAutocannon) {       
            CreateProjectileAtMuzzle = function(self, muzzle)
                if not self.unit:IsDead() and self.unit:GetWeaponByLabel('MainGun'):GetCurrentTarget() then
                    local myWeapon = self.unit:GetWeaponByLabel('MainGun')
                    local myTarget = myWeapon:GetCurrentTarget()
                    ### Checks current target for its unit category and sets the weapons stats accordingly
                    if table.find(myTarget:GetBlueprint().Categories,'AIR') and not table.find(myTarget:GetBlueprint().Categories,'EXPERIMENTAL') then     
                        ### Prevents the Activation of the DMG modification if it is already on
                        if self.unit.DmgMod == false then
                            myWeapon:SetFiringRandomness(myWeapon:GetBlueprint().FiringRandomness)
                            myWeapon:AddDamageMod(-20)
                            self.unit.DmgMod = true
                        end
                    elseif self.unit.DmgMod == true then
                        ### Prevents the De-activation of the DMG modification if it is already off         
                        myWeapon:SetFiringRandomness(myWeapon:GetBlueprint().FiringRandomness * 2)
                        myWeapon:AddDamageMod(20)
                        self.unit.DmgMod = false
                    end
                end
                local proj = CAAAutocannon.CreateProjectileAtMuzzle(self, muzzle)
            end,
        },
    },
   
### File pathing and special paramiters called ###########################

    ### Setsup parent call backs between drone and parent
    Parent = nil,

    SetParent = function(self, parent, droneName)
        self.Parent = parent
        self.Drone = droneName
    end,

    ### Afterburner and exhaust effect pathing

    BeamAfterBurner = '/effects/emitters/aeon_nuke_exhaust_beam_01_emit.bp',
    BeamCruise = '/effects/emitters/aeon_nuke_exhaust_beam_02_emit.bp',
    ExhaustSmoke = '/effects/emitters/missile_smoke_exhaust_02_emit.bp',
   
##########################################################################

    OnCreate = function(self, builder, layer)
    CAirUnit. OnCreate(self,builder,layer)   
        if not self:IsDead() then
            ### Disables weapons
            self:SetWeaponEnabledByLabel('MainGun', false)
            self:SetScriptBit('RULEUCC_RetaliateToggle', false)
               
            ### Global Varibles
            self.BeamExhaustEffectsBag = {}
            self.BurnerActive = false
            self.Evade = false
            self.MoveToParent = false
            self.Duration = 1
            self.MyWeapon = self:GetWeaponByLabel('MainGun')
            self.MyMaxSpeed = self:GetBlueprint().Air.MaxAirspeed
            self.WepRng = self.MyWeapon:GetBlueprint().MaxRadius
            self.DmgMod = false
           
            ### Start of launch special effects
            self:ForkThread(self.LaunchEffects)
        end
    end,

    LaunchEffects = function(self)
        ### Are we dead?
        if not self:IsDead() then
            ### Set flag to true
            self.BurnerActive = true 
                 
            ### Kick off Afterburner multi and effects
            self:ForkThread(self.Afterburner)
                         
            ### Duration of launch
            WaitSeconds(self.Duration)
           
            if not self:IsDead() and not self.Parent:IsDead() then
           
                ### Tells the drone to guard the carrier
                self:ForkThread(self.GuardCarrier)
                             
                ### Enables weapons
                self:SetWeaponEnabledByLabel('MainGun', true)
                self:SetScriptBit('RULEUCC_RetaliateToggle', true)
               
                ### Heartbeat event to monitor the drones distance from the carrier, if the drone gets too far away it is recalled to the carrier
                self:HeartBeatDroneCheck()
            end
        end
    end,
   
    HeartBeatDroneCheck = function(self)
        while self and not self:IsDead() do       
            ### Verify that we have fuel and get distance from parent carrier
            local myFuel = self:GetFuelRatio()
            local dronePos = self:GetPosition()
            local parentPos = self.Parent:CalculateWorldPositionFromRelative({0, 0, 25})
            local parentDist = VDist2(dronePos[1], dronePos[3], parentPos[1], parentPos[3])
           
            if myFuel <= 0 then
                ### Kill drone if no fuel avalible
                self:Kill(self,'Normal',0) 
                             
            elseif parentDist >= 70 and self.Evade == false and self.MoveToParent == false then
                ### Set flag to true     
                self.MoveToParent = true
               
                ### Disables weapons and attempts to move drone back to parent
                self:SetWeaponEnabledByLabel('MainGun', false)         
                self:SetScriptBit('RULEUCC_RetaliateToggle', false)
                IssueClearCommands({self})
                IssueMove({self}, parentPos)
                     
            elseif parentDist <= 70 then
                ### Set flag to false
                self.MoveToParent = false
               
                ### Enables weapons
                self:SetWeaponEnabledByLabel('MainGun', true)
                self:SetScriptBit('RULEUCC_RetaliateToggle', true)                   
                if self.MyWeapon:GetCurrentTarget() then
                    local myTarget = self.MyWeapon:GetCurrentTarget()
                                       
                    ### Verify that our current target is a valid air target
                    if table.find(myTarget:GetBlueprint().Categories,'HIGHALTAIR') and not table.find(myTarget:GetBlueprint().Categories,'EXPERIMENTAL') then             
                       
                        ### Get the distance to our target
                        local tarPos = myTarget:GetPosition()
                        local distance = VDist2(dronePos[1], dronePos[3], tarPos[1], tarPos[3])
                        local myTargetSpeed = myTarget:GetBlueprint().Air.MaxAirspeed 
                                           
                        ### Sets the fighter max speed to that of the target to help prevent overshoot.
                        if distance <= self.WepRng and self.Evade == false then                                                                                         
                            ### Compute the speed of the target and match it
                            self:SetSpeedMult(myTargetSpeed / self.MyMaxSpeed)
                            self:SetAccMult(1.0)
                            self:SetTurnMult(1.5)
                                                       
                        ### If our target is out of weapons range then engage afterburner                                         
                        elseif distance > self.WepRng and self.BurnerActive == false then 
                                                 
                            ### Set flag to true
                            self.BurnerActive = true   
                                                   
                            ### Kick off Afterburner multi and effects
                            self:ForkThread(self.Afterburner)     
                        end
                    end
                else
                    ### Tells the drone to guard the carrier
                    self:ForkThread(self.GuardCarrier)
                end
            end         
            ### Delay between checks
            WaitSeconds(0.25)
        end
    end,
       
    OnMotionHorzEventChange = function(self, new, old)
        ### Should the drone stop flying it will automaticly be re-assigned to guard the carrier
        if not self:IsDead() and new == 'Stopped' and not self.Parent:IsDead() then
            ### Clears the current drone commands if any and forces the drone to guard the carrier         
            self:ForkThread(self.GuardCarrier)
        elseif not self:IsDead() and new == 'Stopping' and not self.Parent:IsDead() then
            ### Clears the current drone commands if any and forces the drone to guard the carrier         
            self:ForkThread(self.GuardCarrier)
        end               
        CAirUnit.OnMotionHorzEventChange(self, new, old)
    end,
   
    GuardCarrier = function(self)
        if not self:IsDead() and not self.Parent:IsDead() then
            ### Tells the drone to guard the carrier
            IssueClearCommands(self)
            IssueGuard({self}, self.Parent)
        end
    end,
   
    OnDamage = function(self, instigator, amount, vector, damagetype)
        CAirUnit.OnDamage(self, instigator, amount, vector, damagetype)
        if self:IsDead() == false and instigator and IsUnit(instigator) then
            local myFuel = self:GetFuelRatio()
            if self.BurnerActive == false and myFuel > 0 then               
                ### Set flags to true
                self.BurnerActive = true
                self.Evade = true             
                ### Kick off Afterburner multi and effects
                self:ForkThread(self.Afterburner)                           
            end   
        end
    end,

    Afterburner = function(self)
        if not self:IsDead() then
            if self.BeamExhaustEffectsBag then
                ### Engine effects clean up
                EffectUtil.CleanupEffectBag(self,'BeamExhaustEffectsBag')
            end
            ### Engage Afterburn speed and turn rates
            self:SetSpeedMult(1.5)
            self:SetAccMult(2.0)
            self:SetTurnMult(0.5)
           
            ### Afterburner sound effects
            self:PlayUnitSound('Launch')
           
            ### Afterburn effects and smoke
            table.insert(self.BeamExhaustEffectsBag, CreateAttachedEmitter(self, 'contrail', self:GetArmy(), self.ExhaustSmoke):ScaleEmitter(0.25))
            table.insert(self.BeamExhaustEffectsBag, CreateBeamEmitterOnEntity(self, 'exhaust', self:GetArmy(), self.BeamAfterBurner):ScaleEmitter(0.2))
           
            ### Play Afterburner sound effects
            self:PlayUnitSound('Afterburn')
           
            ### Get current fuel levels
            local preBurnFuel = self:GetFuelRatio()
           
            ### Duration of Afterburn
            WaitSeconds(self.Duration)
           
            ### Get the fuel levels post Afterburner
            local postBurnFuel = self:GetFuelRatio()

            ### Fuel calculations and Afterburn effect clean up
            if not self:IsDead() then
     
                ### Calculate new fuel levels as per *** BIGOs New ASF MOD ***
                local newFuelLvl = preBurnFuel - (5 *(preBurnFuel - postBurnFuel))
               
                if newFuelLvl > 0 then
                    self:SetFuelRatio(newFuelLvl)
                end
           
                if self.BeamExhaustEffectsBag then
                    ### Engine effects clean up
                    EffectUtil.CleanupEffectBag(self,'BeamExhaustEffectsBag')
                end
               
                ### Sets cruise thrust effect post afterburn
                table.insert(self.BeamExhaustEffectsBag, CreateBeamEmitterOnEntity( self, 'engine01', self:GetArmy(), self.BeamCruise):ScaleEmitter(0.1))
                table.insert(self.BeamExhaustEffectsBag, CreateBeamEmitterOnEntity( self, 'engine02', self:GetArmy(), self.BeamCruise):ScaleEmitter(0.1))
                table.insert(self.BeamExhaustEffectsBag, CreateBeamEmitterOnEntity( self, 'engine03', self:GetArmy(), self.BeamCruise):ScaleEmitter(0.1))

                ### Resets the speed and turn rates
                self:SetSpeedMult(1.0)
                self:SetAccMult(1.0)
                self:SetTurnMult(1.0)
               
                ### Short cool down between Afterburns
                WaitSeconds(self.Duration)
               
                ### Resets Afterburn and Evade triggers     
                if not self:IsDead() then
                    self.BurnerActive = false
                    self.Evade = false
                end
            end
        end
    end,
   
    OnKilled = function(self, instigator, type, overkillRatio)
        ### Disables weapons
        self:SetWeaponEnabledByLabel('MainGun', false)

        if self.BeamExhaustEffectsBag then
            ### Engine effects clean up
            EffectUtil.CleanupEffectBag(self,'BeamExhaustEffectsBag')
        end

        ### Clears the current drone commands if any
        IssueClearCommands(self)

        ### Notifies parent of drone death and clears the offending drone from the parents table
        if not self.Parent:IsDead() then
            self.Parent:NotifyOfDroneDeath(self.Drone)
            table.removeByValue(self.Parent.DroneTable, self)
            self.Parent = nil
        end
       
        ### Final command to finish off the fighters death event
        CAirUnit.OnKilled(self, instigator, type, overkillRatio)
    end,   
}
TypeClass = URA0106

_________________
Image
Blackhole http://www.youtube.com/watch?v=B3aDT0Ft_Yg
WOFhttp://www.youtube.com/watch?v=FVqMqz8PgEc
FOD http://www.youtube.com/watch?v=be9cu9UHv-U
TML http://www.youtube.com/watch?v=1Apk08LAtxc


Last edited by Resin_Smoker on 13 Apr, 2009, edited 1 time in total.

Top
 Profile  
 PostPosted: 07 Apr, 2009 
 
User avatar

Joined: 01 May, 2007
Posts: 4219
Offline
Afterburner scripts with fuel modification...
Code:
#****************************************************************************
#**
#**  File     :  UEA0206_script.lua
#**  Author(s):  Resin_Smoker / Vissroid
#**
#**  Summary  :  UEF Thrasher Script
#**
#**  Copyright © 2009 4th Dimension
#****************************************************************************

#### Localy imported files ####
local TAirUnit = import('/lua/terranunits.lua').TAirUnit
local EffectUtil = import('/lua/EffectUtilities.lua')

#### Weapon local files ####
local TAirToAirLinkedRailgun = import('/lua/terranweapons.lua').TAirToAirLinkedRailgun
local ZealotMissileWeapon = import('/lua/aeonweapons.lua').AAAZealot02MissileWeapon

UEA0206 = Class(TAirUnit) {
    Weapons = {
        MachineGun = Class(TAirToAirLinkedRailgun) {},
        Missile_L = Class(ZealotMissileWeapon) {},
        Missile_R = Class(ZealotMissileWeapon) {},
    },

### File pathing and special paramiters called ###########################

    ### Afterburner and exhaust effect pathing

    BeamAfterBurner = '/effects/emitters/missile_exhaust_fire_beam_01_emit.bp',
    ExhaustSmoke = '/effects/emitters/missile_smoke_exhaust_02_emit.bp',
   
##########################################################################

    OnStopBeingBuilt = function(self,builder,layer)
    TAirUnit.OnStopBeingBuilt(self,builder,layer)   
        if not self:IsDead() then
            ### Global Varibles
            self.BeamExhaustEffectsBag = {}
            self.BurnerActive = false
            self.Evade = false
            self.MyWeapon = self:GetWeaponByLabel('MachineGun')
            self.MyMaxSpeed = self:GetBlueprint().Air.MaxAirspeed
            self.WepRng = self.MyWeapon:GetBlueprint().MaxRadius
           
            ### Start of heartbeat event
            self:ForkThread(self.HeartBeatDistanceCheck)
        end
    end,
   
    HeartBeatDistanceCheck = function(self)
        while self and not self:IsDead() do
            local myFuel = self:GetFuelRatio()
            ### Make sure we have a target and we have fuel
            if self.MyWeapon:GetCurrentTarget() and myFuel > 0 then
                local myTarget = self.MyWeapon:GetCurrentTarget()
               
                ### Verify that our current target is a valid air target
                if table.find(myTarget:GetBlueprint().Categories,'HIGHALTAIR') and not table.find(myTarget:GetBlueprint().Categories,'EXPERIMENTAL') then
               
                    ### Get the distance to our target
                    local myPos = self:GetPosition()
                    local tarPos = myTarget:GetPosition()
                    local distance = VDist2(myPos[1], myPos[3], tarPos[1], tarPos[3])
                    local myTargetSpeed = myTarget:GetBlueprint().Air.MaxAirspeed

                    ### Sets the fighter max speed to that of the target to help prevent overshoot.
                    if distance <= self.WepRng and self.Evade == false then
                        LOG('attempting to match speed')
                       
                        ### Engine effects clean up
                        if self.BeamExhaustEffectsBag then                                                   
                            EffectUtil.CleanupEffectBag(self,'BeamExhaustEffectsBag')
                        end
                                                                 
                        ### Compute the speed of the target and match it
                        self:SetSpeedMult(myTargetSpeed / self.MyMaxSpeed)
                        self:SetAccMult(1.0)
                        self:SetTurnMult(1.5)
                       
                    ### If our target is out of weapons range then engage afterburner                                         
                    elseif distance > self.WepRng and self.BurnerActive == false then
                        LOG('target is too far away')
                       
                        ### Set flag to true
                        self.BurnerActive = true
                     
                        ### Kick off Afterburner multi and effects
                        self:ForkThread(self.Afterburner)     
                    end
                end
            end
           
            ### Delay between checks
            WaitSeconds(0.25)
        end
    end,
   
    OnDamage = function(self, instigator, amount, vector, damagetype)
        TAirUnit.OnDamage(self, instigator, amount, vector, damagetype)
        if self:IsDead() == false and instigator and IsUnit(instigator) then
            LOG('Taking damage')
            local myFuel = self:GetFuelRatio()
            if self.BurnerActive == false and myFuel > 0 then
            LOG('Engaging Afterburner via OnDamage Event')
               
                ### Set flags to true
                self.BurnerActive = true
                self.Evade = true
               
                ### Kick off Afterburner multi and effects
                self:ForkThread(self.Afterburner)                           
            end   
        end
    end,

    Afterburner = function(self)
        if not self:IsDead() then
            if self.BeamExhaustEffectsBag then
                ### Engine effects clean up
                EffectUtil.CleanupEffectBag(self,'BeamExhaustEffectsBag')
            end
            LOG('Afterburner on')
            ### Engage Afterburn speed and turn rates
            self:SetSpeedMult(2.0)
            self:SetAccMult(2.0)
            self:SetTurnMult(0.5)
           
            ### Afterburn effects and smoke
            table.insert(self.BeamExhaustEffectsBag, CreateBeamEmitterOnEntity( self, 'afterburner', self:GetArmy(), self.BeamAfterBurner):ScaleEmitter(2.0))
            table.insert(self.BeamExhaustEffectsBag, CreateAttachedEmitter(self, 'exhaust', self:GetArmy(), self.ExhaustSmoke):ScaleEmitter(0.5))
           
            ### Play Afterburner sound effects
            self:PlayUnitSound('Afterburn')
           
            ### Get current fuel levels
            local preBurnFuel = self:GetFuelRatio()
            LOG('Pre burn fuel: ', preBurnFuel)
           
            ### Duration of Afterburn
            WaitSeconds(2)
           
            ### Get the fuel levels post Afterburner
            local postBurnFuel = self:GetFuelRatio()

            ### Fuel calculations and Afterburn effect clean up
            if not self:IsDead() then
     
                ### Calculate new fuel levels as per *** BIGO's New ASF MOD ***
                local newFuelLvl = preBurnFuel - (10 *(preBurnFuel - postBurnFuel))
                 LOG('Post burn fuel: ', newFuelLvl)
               
                if newFuelLvl > 0 then
                    self:SetFuelRatio(newFuelLvl)
                end
           
                if self.BeamExhaustEffectsBag then
                    ### Engine effects clean up
                    EffectUtil.CleanupEffectBag(self,'BeamExhaustEffectsBag')
                end

                ### Resets the speed and turn rates
                self:SetSpeedMult(1.0)
                self:SetAccMult(1.0)
                self:SetTurnMult(1.0)
                LOG('Afterburner Cooldown')
               
                ### Short pause between Afterburns
                WaitSeconds(4)
               
                ###Resets Afterburn and Evade triggers     
                if not self:IsDead() then
                    self.BurnerActive = false
                    self.Evade = false
                    LOG('Afterburner off')
                end
            end
        end
    end,
   
    OnKilled = function(self, instigator, type, overkillRatio)
        if self.BeamExhaustEffectsBag then
            ### Engine effects clean up
            EffectUtil.CleanupEffectBag(self,'BeamExhaustEffectsBag')
        end

        ### Final command to finish off the fighters death event
        TAirUnit.OnKilled(self, instigator, type, overkillRatio)
    end,
   
}

TypeClass = UEA0206


Resin_Smoker

_________________
Image
Blackhole http://www.youtube.com/watch?v=B3aDT0Ft_Yg
WOFhttp://www.youtube.com/watch?v=FVqMqz8PgEc
FOD http://www.youtube.com/watch?v=be9cu9UHv-U
TML http://www.youtube.com/watch?v=1Apk08LAtxc


Last edited by Resin_Smoker on 09 Apr, 2009, edited 2 times in total.

Top
 Profile  
 PostPosted: 07 Apr, 2009 
 
User avatar

Joined: 01 May, 2007
Posts: 4219
Offline
Lightning / BFG projectiles.
Code:
#
# Aeon "Annihilator" BFG Projectile
# Author Resin_Smoker
# Projectile based off ideas and scripts from Seiya's lobber mod
#

local DefaultProjectileFile = import('/lua/sim/defaultprojectiles.lua')
local EmitterProjectile = DefaultProjectileFile.EmitterProjectile
local ADisruptorShellProjectile = import('/lua/aeonprojectiles.lua').ADisruptorShellProjectile
local EffectTemplate = import('/lua/EffectTemplates.lua')
local RandomFloat = import('/lua/utilities.lua').GetRandomFloat
local utilities = import('/lua/utilities.lua')

BFGShell = Class(EmitterProjectile) {
   
    FxTrails = EffectTemplate.SDFExperimentalPhasonProjFXTrails01,
    FxTrailScale = 1,
    FxImpactUnit =  EffectTemplate.SDFExperimentalPhasonProjHit01,
    FxUnitHitScale = 0.5,
    FxImpactProp =  EffectTemplate.SDFExperimentalPhasonProjHit01,
    FxLandHitScale = 0.5,
    FxImpactLand =  EffectTemplate.SDFExperimentalPhasonProjHit01,
    FxPropHitScale = 0.5,
    AttackBeams = {'/mods/4th_Dimension_194/hook/effects/emitters/BFG_lightning_beam_01_emit.bp'},

    OnCreate = function(self)
   EmitterProjectile.OnCreate(self)
        self:ForkThread(self.BFGThread)
    end,
   
    BFGThread = function(self)
        WaitTicks(4)
        local beams = {}
        local avalibleTargets = {}
        while true do
       local instigator = self:GetLauncher()
            local launcherPos = instigator:GetPosition()
            local projPos = self:GetPosition()
            local dist = VDist2(projPos[1], projPos[3], launcherPos[1], launcherPos[3]) 
            local avalibleTargets = utilities.GetEnemyUnitsInSphere(self, self:GetPosition(), dist * 0.25)
            if dist > 10 and avalibleTargets then
                if table.getn(avalibleTargets) > 3 then
                    for i = 0, (3 -1) do
                        local ranTarget =Random(1,table.getn(avalibleTargets))
                       local target = avalibleTargets[ranTarget]   
                        DamageArea(instigator,target:GetPosition(),0.01,self.DamageData.DamageAmount*0.025,self.DamageData.DamageType,self.DamageData.DamageFriendly)
                        for k, v in self.AttackBeams do
                            local beam = AttachBeamEntityToEntity(self, -1, target, -1, self:GetArmy(), v)
                  table.insert(beams, beam)
                            self.Trash:Add(beam)
                        end
                    end
                elseif table.getn(avalibleTargets) <= 3 then
                    for k, v in avalibleTargets do
   
                        local target = v
                        DamageArea(instigator,target:GetPosition(),0.01,self.DamageData.DamageAmount*0.025,self.DamageData.DamageType,self.DamageData.DamageFriendly)
              for k, v in self.AttackBeams do
                            local beam = AttachBeamEntityToEntity(self, -1, target, -1, self:GetArmy(), v)
                  table.insert(beams, beam)
                            self.Trash:Add(beam)
                        end
                    end
                end
           end
           WaitTicks(4)
           for k, v in beams do
               v:Destroy()
           end
        end
    end,

    OnImpact = function(self, TargetType, targetEntity)
        local rotation = RandomFloat(0,2*math.pi)       
        CreateDecal(self:GetPosition(), rotation, 'crater_radial01_normals', '', 'Alpha Normals', 5, 5, 300, 0, self:GetArmy())
        CreateDecal(self:GetPosition(), rotation, 'crater_radial01_albedo', '', 'Albedo', 6, 6, 300, 0, self:GetArmy())
        ADisruptorShellProjectile.OnImpact( self, TargetType, targetEntity )
    end,
}

TypeClass = BFGShell

_________________
Image
Blackhole http://www.youtube.com/watch?v=B3aDT0Ft_Yg
WOFhttp://www.youtube.com/watch?v=FVqMqz8PgEc
FOD http://www.youtube.com/watch?v=be9cu9UHv-U
TML http://www.youtube.com/watch?v=1Apk08LAtxc


Last edited by Resin_Smoker on 09 Apr, 2009, edited 1 time in total.

Top
 Profile  
 PostPosted: 07 Apr, 2009 
 
User avatar

Joined: 01 May, 2007
Posts: 4219
Offline
Aircraft defensive / tactical teleportation
Code:
    OnCreate = function(self, builder, layer)
    AAirUnit.OnCreate(self,builder,layer)
        ### Are we alive?
        if not self:IsDead() then

            ### Global Varible Setup###
            self.DmgTotal = 0
 
        end
    end,

    OnDamage = function(self, instigator, amount, vector, damagetype)
        AAirUnit.OnDamage(self, instigator, amount, vector, damagetype)

        ### Are we alive and what form of damage did we receive
        if not self:IsDead() and damagetype == 'Normal' then
            local currentHealth = self:GetHealth()
            local dmgLimit = self:GetMaxHealth() * 0.1
           
            ### Verify what damaged our fightrer is a valid unit and that the damage amount taken doesnt kill us outright.
            ### Thus preventing a event from teleportation from triggering during our fighters death.
            if IsUnit(instigator) and amount < currentHealth then

                ### Update of global Variables
                self.DmgTotal = self.DmgTotal + amount

                ### teleport trigger check
                if self.DmgTotal >= dmgLimit then
                    CreateAttachedEmitter( self, 'uaa0306', self:GetArmy(), '/effects/emitters/generic_teleportout_01_emit.bp')
                    self:PlayUnitSound('Warp')
                    if table.find(instigator:GetBlueprint().Categories,'AIR') then
                        ### Our fighter teleports tacticaly as a defensive measure vs air units
                        ### It will teleport behind its attacker and retaliate
                        local enemyPos = instigator:CalculateWorldPositionFromRelative({0, 0, -10})
                        local enemyFacing = instigator:GetOrientation()                     
                        Warp(self, enemyPos, enemyFacing)
                        IssueAttack({self}, instigator)
                        self:ForkThread(self.Effects) 
                    else
                        ### fighter teleports randomly as a defensive measure vs non-air units
                        local location = self:GetPosition()
                        local ranx = location[1] + Random(-25, 25)
                        local rany = location[2] + Random(-25, 25)
                        local destination = {ranx, rany, location[3]}
                        Warp(self,destination)
                        self:ForkThread(self.TeleportEffects)
                    end
                    ### Reset of global Variables
                    self.DmgTotal = 0
                end
            end
        end
    end,

    TeleportEffects = function(self)
        if not self:IsDead() then
            ### Teleportation after effects
            CreateAttachedEmitter( self, 'uaa0306', self:GetArmy(), '/effects/emitters/generic_teleportin_01_emit.bp')
            CreateAttachedEmitter( self, 'uaa0306', self:GetArmy(), '/effects/emitters/generic_teleportin_02_emit.bp')
            CreateAttachedEmitter( self, 'uaa0306', self:GetArmy(), '/effects/emitters/generic_teleportin_03_emit.bp')
        end
    end,

_________________
Image
Blackhole http://www.youtube.com/watch?v=B3aDT0Ft_Yg
WOFhttp://www.youtube.com/watch?v=FVqMqz8PgEc
FOD http://www.youtube.com/watch?v=be9cu9UHv-U
TML http://www.youtube.com/watch?v=1Apk08LAtxc


Top
 Profile  
 PostPosted: 09 May, 2009 
 
User avatar

Joined: 15 Feb, 2007
Posts: 20036
Location: Presumably, at the time of posting, his computer.
Offline
I fixed up the custom icons scripts so that as long as you're using a unique unit ID, the game will always find your custom icons, located in /mods/<modname>/icons/<iconname>.dds

Going to be debuting this script in BO ACU v whatever.
This code goes in /lua/customIcons.lua, then imported into any function that needs it.

Code:
local BlueprintLocations = {} # Create a nice global var.
function FindBlueprints()
    for id, mod in __active_mods do
        local blueprints = DiskFindFiles(mod.location, '*_unit.bp')
        for id, bp in blueprints do
            # Now we need to get the unit ID from the file path. string.sub does this job effectively.
            # Get rid of the string in the second argument.
            bp = string.gsub(bp, '_unit.bp', '')
 
            # URL0001, seven letters, and without _unit.bp, they're the last seven.
            # This does enforce seven-character unitIDs, but they can be any seven.
            bp = string.sub(bp, (string.len(bp) - 7))
   
            bp = string.upper(string.gsub(bp,'/',''))
            BlueprintLocations[bp] = mod.location  # Store it off in our pre-defined global.
        end
    end
end

function GetCustomIconLocation(unitID)
    unitID = string.upper(unitID)
    if not BlueprintLocations[unitID] then
        FindBlueprints() # This should ONLY be called on first finding of a custom icon. No more than once.
        if not BlueprintLocations[unitID] then
            LOG("Mod icons folder not found!")
                        LOG(unitID)
                        LOG(repr(BlueprintLocations))
        else
            return BlueprintLocations[unitID]
        end
    else
        return BlueprintLocations[unitID]
    end
end

_________________
I'm watchin you!
Image


Top
 Profile  
 PostPosted: 25 Jul, 2009 
 
User avatar

Joined: 08 Jul, 2007
Posts: 5394
Offline
Making your projectiles not collide with allied units

Put this in the unit's script file, and allied projectiles will go right through it. Enemy projectiles will still hit. Or, you can hook Unit.lua and insert it into the OnCollisionCheck code there, that will make it a global thing.

Code:
OnCollisionCheck = function(self, other, firingWeapon)
    if IsAlly(self:GetArmy(), other:GetArmy()) then  ### Allows allies to pass through other allies
        return false ### Returning false allows the projectile to pass thru     
    else
        return true ### Projectile impacts normally
    end
end,

_________________
Image


Top
 Profile  
 PostPosted: 25 Feb, 2010 
 
User avatar

Joined: 11 Apr, 2007
Posts: 1915
Offline
Manimal's fix that prevents loss of Build Restrictions after an ACU's Enhancement.

I noticed that Build Restrictions made via a custom script are often lost after any ACU was enhanced .

Enhancements were coded by GPG Devs in a raw / rough way.
So I bring there a nice solution.

In my humble opinion ACUs Enahncements should have been coded originaly the way I show up, since it takes in count the probablity of changes made through any mod.

Here's the detailed paortion of the script that can be implemented to any ACU.


Code:
UEL0001 = Class( TWalkingLandUnit ) {   
   
    -- hidden useless part of the code for this post
   
    CreateEnhancement = function(self, enh)
       
        if enh == 'LeftPod' then
       
        -- hidden useless part of the code for this post
       
        elseif enh =='AdvancedEngineeringRemove' then
       
            local bpEconBR = self:GetBlueprint().Economy.BuildRate
            if not bpEconBR then return end

            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            # N.B. : CAUSES THE LOSS OF SPÉCIFIC RESTRICTIONS THAT ARE ADDED VIA ANY MOD
            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            #self:RestoreBuildRestrictions()
            #self:AddBuildRestriction( categories.UEF * (categories.BUILTBYTIER2COMMANDER + categories.BUILTBYTIER3COMMANDER) )

            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            # MANIMAL's FIX #1 PREVENTS THE LOSS OF BUILD RESTRICTIONS
            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            local preReq = bp.Prerequisite
            local bpPreReq = self:GetBlueprint().Enhancements[preReq]
            if not bpPreReq then return end
            local cat = ParseEntityCategory( bpPreReq.BuildableCategoryAdds )
            self:AddBuildRestriction( cat )

            if Buff.HasBuff( self, 'UEFACUT2BuildRate' ) then
                Buff.RemoveBuff( self, 'UEFACUT2BuildRate' )
            end
       
        elseif enh =='T3Engineering' then
       
        -- hidden useless part of the code for this post
       
        elseif enh =='T3EngineeringRemove' then
            local bpEconBR = self:GetBlueprint().Economy.BuildRate
            if not bpEconBR then return end

            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            # N.B. : CAUSES THE LOSS OF SPÉCIFIC RESTRICTIONS THAT ARE ADDED VIA ANY MOD
            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            #self:RestoreBuildRestrictions()
            #self:AddBuildRestriction( categories.UEF * (categories.BUILTBYTIER2COMMANDER + categories.BUILTBYTIER3COMMANDER) )

            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            # MANIMAL's FIX #2 PREVENTS THE LOSS OF BUILD RESTRICTIONS
            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            --# SUPPRESSION DE 'T3Engineering'
            local preReq = false
            local bpPreReq = false
            if bp.Prerequisite then
                preReq = bp.Prerequisite
                bpPreReq = self:GetBlueprint().Enhancements[preReq]
                if not bpPreReq then return end
            end
            local cat = ParseEntityCategory( bpPreReq.BuildableCategoryAdds )
            self:AddBuildRestriction( cat )
           
            --# SUPPRESSION DE 'AdvancedEngineering'
            preReq = false
            cat = false
            if bpPreReq.Prerequisite then
                preReq = bpPreReq.Prerequisite
                bpPreReq = self:GetBlueprint().Enhancements[preReq] or false
                if not bpPreReq then return end
            end
            cat = ParseEntityCategory( bpPreReq.BuildableCategoryAdds )
            self:AddBuildRestriction( cat )

            if Buff.HasBuff( self, 'UEFACUT3BuildRate' ) then
                Buff.RemoveBuff( self, 'UEFACUT3BuildRate' )
            end

        # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        # END OF THE FIX FOR Build Restrictions - SCRIPTED by MANIMAL
        # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        elseif enh =='DamageStablization' then
       
        -- hidden useless part of the code for this post
       
    end,
}


Enjoy the new ACU without undesired behavior ! 8)

_________________
Console Plus - Solo A.C.U. - Experimental Wars Image


Top
 Profile  
 PostPosted: 02 Mar, 2010 
 

Joined: 13 Jun, 2008
Posts: 729
Offline
On behalf of Resin_Smoker I've taken a look at properly cloaking the T2 Cybran Stealth Fighter of 4th-Dimension.
I found that below fix will allow proper functionality for all units. Initially meant as a timed exclusive to 4th-Dimension and TVg, I'm releasing this code with permission from Resin_Smoker.

Adding the following bit into your unit.lua will enable cloaking of individual units to work as intended, that is, once they can't be seen anymore, they won't be fired at, even if they uncloak and recloak without Omni coverage.
Code:
EnableUnitIntel = function(self, intel)
    if intel and intel == 'Cloak' then
        if not self.dnt then
            self:SetDoNotTarget(true)
            self.dnt = ForkThread(function() WaitTicks(1) self:SetDoNotTarget(false) self.dnt:Destroy() self.dnt= nil end)
            self.Trash:Add(self.dnt)
        end
    end
    oldUnit.EnableUnitIntel(self, intel)
end,

There appears to be also some bit referring to a cloakfield in the Intel tree, if you can point me to units using that bit I can test if above code needs to be expanded.

_________________
TVg V5 Alpha Testers Wanted!
Image
Bulletstorm released
other mods


Top
 Profile  
 PostPosted: 06 Mar, 2010 
 

Joined: 21 May, 2008
Posts: 706
Offline
stick this thread plz.


Top
 Profile  
 PostPosted: 06 Mar, 2010 
 
Forum Scout
Forum Scout
User avatar

Joined: 02 Mar, 2007
Posts: 8995
Location: Ninja Editing Your Post from a Canadian IPhone
Offline
I've added it to the Useful Info Thread under ''Misc"

Mike

_________________
God of Models - Moderator
BlackOps Team Twitter

Image


Top
 Profile  
 PostPosted: 06 Mar, 2010 
 

Joined: 13 Jun, 2008
Posts: 729
Offline
This thread used to be stickied and ought to again, I myself haven't seen it in the useful info thread.
AKA, people who might need the info might not even see it.

Also non-script postings including this one should not be made into this thread. I request them purged.

_________________
TVg V5 Alpha Testers Wanted!
Image
Bulletstorm released
other mods


Top
 Profile  
 PostPosted: 06 Mar, 2010 
 
Forum Scout
Forum Scout
User avatar

Joined: 02 Mar, 2007
Posts: 8995
Location: Ninja Editing Your Post from a Canadian IPhone
Offline
Ghaleon wrote:
This thread used to be stickied and ought to again, I myself haven't seen it in the useful info thread.
AKA, people who might need the info might not even see it.

I don't want to clutter up the sticky section of the forum right now, especially with SC2 stuff coming hard and fast, and as I said, I've added it to the Useful Info thread under "Misc"

Mike

_________________
God of Models - Moderator
BlackOps Team Twitter

Image


Top
 Profile  
 PostPosted: 06 Mar, 2010 
 

Joined: 13 Jun, 2008
Posts: 729
Offline
At the very least, please, clean the non-related posts so this thread remains useful and isn't filled with our non-contributing clutter.
Thank you OrangeKnight!

_________________
TVg V5 Alpha Testers Wanted!
Image
Bulletstorm released
other mods


Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic



Quick Tools

Search for:
Jump to:  

© 2002-2010 Gas Powered Games Corp. All Rights Reserved. Gas Powered Games is the exclusive trademark of Gas Powered Games Corp.
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
 
Home| Games | Company | News & Press | Support
  Terms of Use   |    Copyright Information   |    Privacy Policy