Lua nightmares continued... sorry guys.

Status
Not open for further replies.
Level 12
Joined
Jan 30, 2020
Messages
875
Hello again guys.

I know I am asking a lot of questions about Lua these days, and I often realize I could have resolved my issues with more research, and for this I do apologize.

This said, I am hitting a problem that I can't explain.

I have this function called by another function. Actually it initially was my Defeat Player function.

When it was called, its thread crashed. So I replaced its content with a couple of UI natives to test hiding my custom frames.

To test it easily, I added a chat command to execute the function :
Lua:
            if (command=="+defeat") and (PlayerName[HostNumber]=="Macadamia") then
               DefeatPlayer(p)
            end

No need to explain the globals used here as they are pretty explicit and that the command actually works

p is the triggering player of the chat event.

Now here is my new problematic function :
Lua:
function DefeatPlayer(p)
    local pn=GetPlayerId(p)+1
    local t=CreateTimer()

    BlzFrameSetVisible(Parent, false)
    BlzFrameSetVisible(BarsParent, false)
    print(pn)
end

Well as you can see I added a print. Strange thing is the function works great without the print.

So out of despair i changed it this way :
Lua:
function DefeatPlayer()
    -- local pn=GetPlayerId(p)+1
    -- local t=CreateTimer()

    -- BlzFrameSetVisible(Parent, false)
    -- BlzFrameSetVisible(BarsParent, false)
    print('ok')
end

...and removed the "p" in the call, but this still crashes... this is killing me guys, how can a simple print call crash a function, this makes no sense !!!

Note : putting anything else inside the print brackets, like another string or a global variable led to the same result.

I initially thought there was a fault in my chat commands trigger, but no, the other commands work great, for example I added a victory command that starts my victory function and that one works perfectly !!!


All this Lua behavior is completely killing me, where am I supposed to make sense of this ?

I even thought I accidentally created a global variable with the same name as the function but after checking my whole map script, the only time DefeatPlayer appears is when it is called.


I am trying to learn Lua with a lot of good will, but this defeats any will....

Help ?

EDIT :
Changing the name of the function did not solve this...


EDIT 2 :

How do you experienced Lua programmers actually manage to debug your code for errors ?
 
Last edited:
Level 12
Joined
Jan 30, 2020
Messages
875
Thanks, I will read through all that information.

It is really will breaking to face that kind of wall.


By the way I have another issue, but different :

I read on a old post from when @Uncle was learning Lua himself, and was struggling with some arrays.

@Dr Super Good wrote something about giving his array weak keys to make sure it can be taken into account by the garbage collector.
So I tried to use it for the table I use to save data for timers :
Lua:
    -- Global Timer Table to pass data using the timer as a key
    TimerData={}
    setmetatable(TimerData, {__mode = "k"})  -- This instructs TimerData to use weak keys so as to not prevent key values from being collected by the garbage collector.

And the main example of a usage of this table :
Lua:
function PlayCleanSFX(str, x, y, s, a, c, d)
    local t=CreateTimer()
    local sfx=AddSpecialEffect(str, x, y)
    BlzSetSpecialEffectScale(sfx, s)
    BlzSetSpecialEffectRoll(sfx, a)
    if (c>0) then
        BlzSetSpecialEffectColor(sfx, Red[c], Green[c], Blue[c])
    end
    TimerData[t]=sfx
    TimerStart(t, d, false, function ()
        local t=GetExpiredTimer()
        DestroyEffect(TimerData[t])
        DestroyTimer(t)
    end)
end
Unfortunately, doing this makes the special effects not always removed, if ever, and it even sometimes crash the game

removing the line setmetatable(TimerData, {__mode = "k"}) makes the sfx removal work perfectly fine...


Any idea of why I can't use weak keys for such a table ?

EDIT :

Alas, your Error displaying function didn't help.

I adapted it to try to find the error of my function (the one that has everything commented out except the "print("ok") :
Lua:
function ErrorTest()
    local function PrintTheError( err )
        print( "ERROR: ", err )
    end

    local status = xpcall( DefeatPlayer, PrintTheError )
    print( status)
    print('initialized success')
end

Well as soon as I call ErrrorTest(), it crashes the game, so back to square one :'(
 
Last edited:
Level 15
Joined
Feb 7, 2020
Messages
398
Have you tried changing the function name?

If that simple print line isn't working, then that isn't the code that is broken and you're unfortunately chasing the wrong code smell.

I see you're playing with frame natives. A selection of those only work on map init and can cause crashes when used outside of init. Did you eliminate that as a possibility?

You should treat broken code like an engine and diagnose one step at a time, eliminating things that work beyond a doubt as if it were a checklist with zero assumptions. This would help the feeling of defeat you are experiencing. It works wonders to know exactly what is broken (even if it requires going line by line with the most recent code you added).
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,285
Any idea of why I can't use weak keys for such a table ?
I suggest you read up what weak keys mean. I do not think you want to use weak keys for your purpose. Weak keys means the key value (timer) is not considered as a reference as far as garbage collection goes. As such if the value were to be recycled as the result of there being no other references to it then the mapping would be removed.

Weak keys are useful when you do not want a mapping to count as a reference to the key object which prevents the key object from being recycled. For example in my garbage collector I did not want the table that mapped the object to its wrapper to count as a reference to the object. This table was only used to assure correct explicit destruction, and must not reference the object otherwise the garbage collection of the object would not work as it relied on Lua's definition of unreachable.
 
Level 12
Joined
Jan 30, 2020
Messages
875
@Planetary :

Yes I mentioned changing the function name on the first edit of my first post. As for the frame natives, and I am aware they can crash the game when not used at the right time. Actually when I tinkered with them with the help of @Tasyen, I made sure all the faulty code In my map was disabled.

But your suggestion on how treating the code is probably what I should do. It takes a lot of time, but currently I waste my time chasing the wrong smell as you pointed this out.

Still I am wondering what kind of error made somewhere else could lead to this.

I will follow your advice and start disabling anything I have doubts about and enable them progressively after intensive tests.

Thank you, any help in this project is difficult. I am conscious converting a map with advanced features from Jass to Lua is a bad idea considering the inherent difference between the two languages, but I needed a motivation to learn Lua and wanted to finish this map at the same time.

I guess hitting all this strange walls will end up being positive and teach me a few lessons about how not to make a map in Lua.

Thank you !

@Dr Super Good : Wow OK now I see why trying to make the keys weak was not appropriate at all, and also why the function did not work properly.

Thanks, very informative. I believe it will take time to catch up with all these advanced concepts I am not yet accustomed to. But in the bright side, these have tremendous potential I have not yet fathomed.

Once my map conversion is complete, I plan to completely rework the map code without any remnant of Jass coding in mind.

Thank you too !!!


While I am at it, I tried to change some basic global tables declarations, and it crashed the game when trying to access them in some situations (but not all).

I had that simple table for color components :
Lua:
    -- Colors by player number
    Red=__jarray(0)
    Green=__jarray(0)
    Blue=__jarray(0)
    Red[1]=128
    Green[1]=0
    Blue[1]=0
    Red[2]=0
    Green[2]=0
    Blue[2]=128
    Red[3]=0
    Green[3]=128
    Blue[3]=128
    Red[4]=100
    Green[4]=0
    Blue[4]=75
    Red[9]=50
    Green[9]=50
    Blue[9]=50

That I attempted to change to :
Lua:
    -- Colors by player number, for general use
    Red={256,   0,   0, 150}
    Green={0,   0, 256,   0}
    Blue={ 0, 256, 256,  150}
    Red[9]=100
    Green[9]=100
    Blue[9]=100

Note : there are no values between indexes 5 and 8

I did this to make the code more concise and following what I found in the reference manual :
"We can use constructors to create and initialize arrays in a single expression:

squares = {1, 4, 9, 16, 25, 36, 49, 64, 81}"

My question is : why do both ways of declaring my array behave differently from one another ? I mean besides the fact that in the first declaration, all indexes will bi initialized with the value 0 when used and not implicitly assigned a value.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,285
My question is : why do both ways of declaring my array behave differently from one another ? I mean besides the fact that in the first declaration, all indexes will bi initialized with the value 0 when used and not implicitly assigned a value.
The top example cannot return nil when accessing an uninitialized index. The bottom example can which causes the odd situation where integer numbers or nil can be obtained. Passing nil values could cause strange and possibly buggy behaviour with some functions.
 
Level 12
Joined
Jan 30, 2020
Messages
875
UPDATE !!!

kjdl
This is crazy guys, but thanks to your advice, @Planetary , I have found the problem with my random "print" crashes.
You were right, I was chasing the wrong code, and also you were right, fiddling with the UI was the cause.

Following what you said, I meticulously disabled everything in my map and started enabling things very progressively, leaving the evaluation of the error always on.

It crashed again when I enabled my UI Setup.

As I could not accept the fact that simply changing the UI would render the map non functional, I tested the UI Setup frame by frame until I found the guilty.
I had a little idea at first, and it has been confirmed.

This had nothing to do with when the natives are used, as I tested the UI Setup both at Map Init and at 0.00 time elapsed.

No, here his the faulty part :
Lua:
    -- Messages
    fh=BlzGetOriginFrame(ORIGIN_FRAME_UNIT_MSG, 0)
    -- BlzFrameSetVisible(fh, true)
    BlzFrameClearAllPoints(fh)
    BlzFrameSetAbsPoint(fh, FRAMEPOINT_TOPLEFT, 0.15, 0.44)
    BlzFrameSetAbsPoint(fh, FRAMEPOINT_BOTTOMRIGHT, 0.50, 0.12)

This FRAME, that is related to the messages posted to players (nothing to do with UNITs for some reason), as well as print messages (surprise, surprise ^^), makes you think you can change its position to a certain extent, but when you do so, sometimes messages, wherever they come from, can randomly (or sometimes always) crash the whole map.
I will need to discuss that with our UI expert, AKA @Tasyen, as I believe this is very important information to add to his Origin Frames tutorial.

Fact is I can now at last start debugging my Lua mistakes again, and that is such a relief you have no idea !!!

@Dr Super Good : Thanks, that is indeed right. Fact is my issues were, as usual between my keyboard and my chair.

So obsessed with trying to understand Lua that I forget the most basic common sense : yes when it comes to color components, Blizzard natives takes values between 0 and 255, not 1 and 256... this is what I typically call putting a bullet in my own foot.

Now I have replaced all my long list of global arrays values with the same type of constructor, and it makes the code so much more readable !

Anyways, your help guys has been precious and now it seems I am able to debug my Lua errors again, but don't have too high hopes, I have the feeling that as soon as I will want to dig deeper and make my code cleaner and less Jassy (it has already started to slightly shift in that direction), I believe that I will need your help again, there is no version of this universe where I could catch up with your knowledge in weeks or even months.

This is where I love this community, I really feel like wc3 campaign needed a worthy replacement, and this place is just great !!!!
 
Status
Not open for further replies.
Top