The 3rd Age

MasterHero Mod 1.9

MasterHero Mod 1.9

Enhances Visuals, provide series of modifications and additions to the game play, support WOR

Button for The 3rd AgeButton for The Dwarf HoldsButton for The Elven AllianceButton for Helm's Deep Last HopeButton for GothmogtheOrcButton for BFME+Button for The Four AgesButton for HDR HeadquartersButton for Middle Earth CenterButton for Project Perfect Mod

Become an affiliate!

   

Quick Lists

Top Rated Popular New Updated Last Comments Users

Register and log in to move these advertisements down

Advanced LUA: Helper Functions

Avatar of Nertea

Nertea

Category: Code
Level: Expert
Created: Tuesday November 17, 2009 - 23:43
Updated: Wednesday November 18, 2009 - 0:56
Views: 17288
Summary: Learn about how to use lua helper functions in BFME1

Rating

Staff says

4.7

Members say

5.0

Average

4.7/5.0

7 votes

Page 1 2 3 4
This part of the tutorial deals with making a basic helper function to hide some subobjects

You define a function in scripts.lua as follows:
              
Code
function OnMordorOrcACreated(self)
end

Your lua code evidently goes between these two points. It is important to know here what "self" means. Self is a variable that describes, in BFME, the object you're operating on (in this case, an Orc Warrior). This variable persists throughout the entire function until the "end".During this section, you can 'call' other functions in the file like this:
              
Code
function OnMordorOrcACreated(self)
ObjectHideSubObjectPermanently( self, "SHIELD1", true)
end

Note the "self" in this ObjectHideSubObjectPermanently function. This is the same "self" as before - the line here says to execute the function ObjectHideSubObjectPermanently on "self" (the Orc Warrior). The other two parameters, as they're called, are related to what the function does, ("SHIELD1" is the subobject to be hidden, "true" mean yes, hide it).

ObjectHideSubObjectPermanently is an example of a function that's built into the BFME engine. We can't change it in any way, just use it. However, we can write our own functions in this file, use them, and change them as we want.

Let's look at some code I wrote for this Orc Warrior. It
  • Hides all the subobjects
  • Chooses a random shield
  • Chooses a random helmet
  • Chooses a random weapon

              
Code

function OnMordorOrcACreated(self)


    ObjectHideSubObjectPermanently( self, "SHIELD1", true)
    ObjectHideSubObjectPermanently( self, "SHIELD2", true)
    ObjectHideSubObjectPermanently( self, "SHIELD3", true)
    ObjectHideSubObjectPermanently( self, "SHIELD4", true)
    ObjectHideSubObjectPermanently( self, "SHIELD5", true)
    ObjectHideSubObjectPermanently( self, "SHIELD6", true)
    ObjectHideSubObjectPermanently( self, "SHIELD7", true)
    ObjectHideSubObjectPermanently( self, "SHIELD8", true)
    ObjectHideSubObjectPermanently( self, "SHIELD9", true)
    
    ObjectHideSubObjectPermanently( self, "HELM1", true)
    ObjectHideSubObjectPermanently( self, "HELM2", true)
    ObjectHideSubObjectPermanently( self, "HELM3", true)
    ObjectHideSubObjectPermanently( self, "HELM4", true)
    ObjectHideSubObjectPermanently( self, "HELM5", true)
    ObjectHideSubObjectPermanently( self, "HELM6", true)
    ObjectHideSubObjectPermanently( self, "HELM7", true)
    
    ObjectHideSubObjectPermanently( self, "1HW1", true)
    ObjectHideSubObjectPermanently( self, "1HW2", true)
    ObjectHideSubObjectPermanently( self, "1HW3", true)
    ObjectHideSubObjectPermanently( self, "1HW4", true)
    ObjectHideSubObjectPermanently( self, "1HW5", true)
    ObjectHideSubObjectPermanently( self, "1HW6", true)
    ObjectHideSubObjectPermanently( self, "1HW7", true)
    ObjectHideSubObjectPermanently( self, "1HW8", true)
    ObjectHideSubObjectPermanently( self, "1HW9", true)
    ObjectHideSubObjectPermanently( self, "1HW10", true)
    ObjectHideSubObjectPermanently( self, "1HW11", true)
    ObjectHideSubObjectPermanently( self, "1HW12", true)
    ObjectHideSubObjectPermanently( self, "1HW13", true)


    local shield =     GetRandomNumber()
    local helm =     GetRandomNumber()
    local weapon = GetRandomNumber()

    if shield <= 0.1 then
        ObjectHideSubObjectPermanently( self, "SHIELD1", false )
    elseif shield <= 0.2 then
    ObjectHideSubObjectPermanently( self, "SHIELD2", false )
    elseif shield <= 0.3 then
    ObjectHideSubObjectPermanently( self, "SHIELD3", false )
    elseif shield <= 0.4 then
    ObjectHideSubObjectPermanently( self, "SHIELD4", false )
    elseif shield <= 0.5 then
    ObjectHideSubObjectPermanently( self, "SHIELD5", false )
    elseif shield <= 0.6 then
    ObjectHideSubObjectPermanently( self, "SHIELD6", false )
    elseif shield <= 0.7 then
    ObjectHideSubObjectPermanently( self, "SHIELD7", false )
    elseif shield <= 0.8 then
    ObjectHideSubObjectPermanently( self, "SHIELD8", false )
    elseif shield <= 0.9 then
    ObjectHideSubObjectPermanently( self, "SHIELD8", false )
    else
    ObjectHideSubObjectPermanently( self, "SHIELD9", false )
    end
    
    if helm <= 0.125 then
        ObjectHideSubObjectPermanently( self, "", false )
    elseif helm <= 0.25 then
    ObjectHideSubObjectPermanently( self, "HELM1", false )
    elseif helm <= 0.375 then
    ObjectHideSubObjectPermanently( self, "HELM2", false )
    elseif helm <= 0.50 then
    ObjectHideSubObjectPermanently( self, "HELM3", false )
    elseif helm <= 0.625 then
    ObjectHideSubObjectPermanently( self, "HELM4", false )
    elseif helm <= 0.75 then
    ObjectHideSubObjectPermanently( self, "HELM5", false )
    elseif helm <= 0.875 then
    ObjectHideSubObjectPermanently( self, "HELM6", false )
    else
    ObjectHideSubObjectPermanently( self, "HELM7", false )
    end
    
    if weapon <= 0.075 then
        ObjectHideSubObjectPermanently( self, "1HW1", false )
    elseif weapon <= 0.150 then
        ObjectHideSubObjectPermanently( self, "1HW2", false )
    elseif weapon <= 0.225 then
        ObjectHideSubObjectPermanently( self, "1HW3", false )
    elseif weapon <= 0.300 then
        ObjectHideSubObjectPermanently( self, "1HW4", false )
    elseif weapon <= 0.375 then
        ObjectHideSubObjectPermanently( self, "1HW5", false )
    elseif weapon <= 0.450 then
        ObjectHideSubObjectPermanently( self, "1HW6", false )
    elseif weapon <= 0.525 then
        ObjectHideSubObjectPermanently( self, "1HW7", false )
    elseif weapon <= 0.600 then
        ObjectHideSubObjectPermanently( self, "1HW8", false )
    elseif weapon <= 0.675 then
        ObjectHideSubObjectPermanently( self, "1HW9", false )
    elseif weapon <= 0.750 then
        ObjectHideSubObjectPermanently( self, "1HW10", false )
    elseif weapon <= 0.825 then
        ObjectHideSubObjectPermanently( self, "1HW11", false )
    elseif weapon <= 0.900 then
        ObjectHideSubObjectPermanently( self, "1HW12", false )
    else
        ObjectHideSubObjectPermanently( self, "1HW13", false )
    end
end


This code is pretty long and awkward! It would be nice if we could shorten it a little. Luckily, we can! I can define a new function to hide some of these subobjects, then I can use it anywhere I want. This function goes outside (after the "end" or before the "function OnMordorOrcCreated(self)" line) the OnMordorOrcCreated function!. The function is defined like this:
              
Code

-- This function hides a set of subobjects
-- --------------------------------------------------
-- # Inputs: self: an instance of the object
-- # subObjectTable: a table containing strings naming all the subobjects to be hidden
function HideAllSubObjects(self,subObjectTable)
end

The two parameters of the function are self and subObjectTable. This means that when the function is used, I will need to provide a table of all the subobjects I want to hide, and the self object.

Then I can write my function. I won't deal here with how precisely to do this - it would be easier to look up a tutorial on basic lua. However, this is the result:
              
Code

-- This function hides a set of subobjects
-- --------------------------------------------------
-- # Inputs: self: an instance of the object
-- # subObjectTable: a table containing strings naming all the subobjects to be hidden
function HideAllSubObjects(self,subObjectTable)
    -- For all objects in the subObjectTable
    local length = getn(subObjectTable)
    for i=1,length do
        -- hide the subobject.
        ObjectHideSubObjectPermanently( self, subObjectTable[i], true )
    end
end

Now, how to use this function? It's pretty easy. First, we need to know how to define a table - pretty easy.
              
Code

local shieldList = {"HELM1","HELM2","HELM3","HELM4","HELM5","HELM6","HELM7"}

Each subobject I want to hide is listed in that table (note the squiggly brackets. I can then use it in my randomization code
              
Code

-- Orc Fighter randomization
function OnMordorOrcACreated(self)

    local helmetList = {"HELM1","HELM2","HELM3","HELM4","HELM5","HELM6","HELM7"}
    local shieldList = {"SHIELD1","SHIELD2","SHIELD3","SHIELD4","SHIELD5","SHIELD6","SHIELD7","SHIELD8","SHIELD9"}
    local weaponList = {"1HW1","1HW2","1HW3","1HW4","1HW5","1HW6","1HW7","1HW8","1HW9","1HW10","1HW11","1HW12","1HW13"}

    HideAllSubObjects(self,shieldList)
    HideAllSubObjects(self,helmetList)
    HideAllSubObjects(self,weaponList)

    local shield =     GetRandomNumber()
    local helm =     GetRandomNumber()
    local weapon = GetRandomNumber()

    if shield <= 0.1 then
        ObjectHideSubObjectPermanently( self, "SHIELD1", false )
    elseif shield <= 0.2 then
    ObjectHideSubObjectPermanently( self, "SHIELD2", false )
    elseif shield <= 0.3 then
    ObjectHideSubObjectPermanently( self, "SHIELD3", false )
    elseif shield <= 0.4 then
    ObjectHideSubObjectPermanently( self, "SHIELD4", false )
    elseif shield <= 0.5 then
    ObjectHideSubObjectPermanently( self, "SHIELD5", false )
    elseif shield <= 0.6 then
    ObjectHideSubObjectPermanently( self, "SHIELD6", false )
    elseif shield <= 0.7 then
    ObjectHideSubObjectPermanently( self, "SHIELD7", false )
    elseif shield <= 0.8 then
    ObjectHideSubObjectPermanently( self, "SHIELD8", false )
    elseif shield <= 0.9 then
    ObjectHideSubObjectPermanently( self, "SHIELD8", false )
    else
    ObjectHideSubObjectPermanently( self, "SHIELD9", false )
    end
    
    if helm <= 0.125 then
        ObjectHideSubObjectPermanently( self, "", false )
    elseif helm <= 0.25 then
    ObjectHideSubObjectPermanently( self, "HELM1", false )
    elseif helm <= 0.375 then
    ObjectHideSubObjectPermanently( self, "HELM2", false )
    elseif helm <= 0.50 then
    ObjectHideSubObjectPermanently( self, "HELM3", false )
    elseif helm <= 0.625 then
    ObjectHideSubObjectPermanently( self, "HELM4", false )
    elseif helm <= 0.75 then
    ObjectHideSubObjectPermanently( self, "HELM5", false )
    elseif helm <= 0.875 then
    ObjectHideSubObjectPermanently( self, "HELM6", false )
    else
    ObjectHideSubObjectPermanently( self, "HELM7", false )
    end
    
    if weapon <= 0.075 then
        ObjectHideSubObjectPermanently( self, "1HW1", false )
    elseif weapon <= 0.150 then
        ObjectHideSubObjectPermanently( self, "1HW2", false )
    elseif weapon <= 0.225 then
        ObjectHideSubObjectPermanently( self, "1HW3", false )
    elseif weapon <= 0.300 then
        ObjectHideSubObjectPermanently( self, "1HW4", false )
    elseif weapon <= 0.375 then
        ObjectHideSubObjectPermanently( self, "1HW5", false )
    elseif weapon <= 0.450 then
        ObjectHideSubObjectPermanently( self, "1HW6", false )
    elseif weapon <= 0.525 then
        ObjectHideSubObjectPermanently( self, "1HW7", false )
    elseif weapon <= 0.600 then
        ObjectHideSubObjectPermanently( self, "1HW8", false )
    elseif weapon <= 0.675 then
        ObjectHideSubObjectPermanently( self, "1HW9", false )
    elseif weapon <= 0.750 then
        ObjectHideSubObjectPermanently( self, "1HW10", false )
    elseif weapon <= 0.825 then
        ObjectHideSubObjectPermanently( self, "1HW11", false )
    elseif weapon <= 0.900 then
        ObjectHideSubObjectPermanently( self, "1HW12", false )
    else
        ObjectHideSubObjectPermanently( self, "1HW13", false )
    end
end

Note how much space is saved there! The HideAllSubObjects function is used 3 times, with each of my 3 lists (one for weapons, shields and helmets). Of course, if I wanted to, I could make one big list which would contain all of those subobjects. Every time I use the function, the code looks up the HideAllSubObjects section and executes that with the list I specify.

However, all the rest of that code is still there, and writing it was a pain. I had to calculate those probabilities and write if/else a lot. It would be nice if I could do something about it....

Comments

Display order: Newest first

Nertea (Team Chamber Member) - Tuesday December 22, 2009 - 9:25

lua tables aren't really pure arrays because of their interesting key/record system. I'm not really a programmer, but my experience with actual programming languages has shown that lua tables don't behave the same way, so I guess it's ok for them to call them something else. Kinda like python's lists really.

they're defined like that because EA broke something somewhere - I couldn't get it to work using the normal way of declaring a table key/record.

Bart (Administrator) - Friday December 18, 2009 - 4:47

Nice tutorial. I wonder why LUA calls arrays tables though.
And why do you have to do this:
a = "foo"; list[a] = "bar"
instead of just:
list["foo"] = "bar"

Nertea (Team Chamber Member) - Saturday November 21, 2009 - 12:42

Glad it's a bit helpful. I do want to know if anybody uses this, and with what degree of success, partially for interest's sake and partially to see if it's worth writing up stuff about other lua script tricks that I've developed/am developing.

Rob38 (Team Chamber Member) - Thursday November 19, 2009 - 17:29

Interesting. I also use lots of random stuff for my models so this can be very helpful.

Sulherokhh (Team Chamber Member) - Wednesday November 18, 2009 - 5:39

Yippee! I love tuts like that, easily accessible and immediately useful.
Info #3 is a vital debugging tool. :)

Go to top

 

"One site to rule them all, one site to find them,
one site to host them all, and on the network bind them."

 
8:51:38