Duon's Lua Help Thread (Because I know I need one)

Status
Not open for further replies.

Sapheros

Member
Me and Lat' have been working on a script towards an unofficial riders mod no one wants. Along the way, we came up with different ideas, one of them was to use the pointless-in-race-mode teleporter monitor as a workaround for adding a monitor to the random monitor cycle as the air monitor, which rewarded players air when they receive it....

Except it doesn't do jack shit.

We tried to use the MainCfg to create a deathstate for one of the frames, but it was also hopeless.

We're now wondering how would we reward a player a variable through the MobjDeath hook, or do we need a different hook?

Code:
addHook("MobjDeath", function(mo, toucher)
 toucher.player.air = $1 + 30
 S_StartSound(player.mo, 135)
end, MT_MIXUPICO)
 
Last edited:
The MobjDeath hook is only triggered when P_KillMobj is used on an object, not when the object disappears without running out of health first, which is the case for monitor icons. You'd be better off putting that code in a custom Action and replacing A_MixUp with that Action in the state where the Teleport Monitor calls it.
 
To make a quick update, it worked, But there is an irritating bug with it. It rewards the all of the players air.
 
Code:
function A_MixUp(actor, var1, var2)
    for player in players.iterate
        if player.mo
            player.air = $1 + 30
            S_StartSound(player.mo, 135)
        end
    end
end

I'm not sure if I can affect a player individually since A_MixUp affects all players.
 
The problem is that you're iterating over all players with for player in players.iterate, thus applying the code inside the loop to each player, instead of only to the player who popped the monitor. By default, monitor icons have their target set to the mobj of the popping player, so you can access the correct player's mobj with actor.target, and the player themselves with actor.target.player.

Code:
function A_MixUp(actor, var1, var2)
    if (actor.target) and (actor.target.valid) //Make sure the player mobj wasn't destroyed somehow
    and (actor.target.player) and (actor.target.player.valid) //Make sure the player data is accessible from the mobj
        //Do the stuff
        actor.target.player.air = $1 + 30
        S_StartSound(actor.target, 135)
    end
end
 
I'm so bad at lua I might have a thread for each problem. DX

Anyways, I tried to make a script that would add air after a certain amount of time... except it doesn't really pay attention to the timer at all and add by tics instead.

Code:
        // Increase the air though the whirlwind shield!
        if player.powers[pw_shield] == SH_JUMP
        and p.mo.airadd == 0
            p.mo.airadd = 2*TICRATE
        end

        if p.mo.airadd > 0
            p.mo.airadd = $1 - 1
            p.air = $1 + 1
        end

Note: This is part of a script with the thinkframe hook, just incase anyone is aware.
 
In that script, it adds air every time airadd counts down. Instead, you should replace that line about adding 1 to air with a check to see whether airadd has become zero first. For example:

Code:
if p.mo.airadd > 0
            p.mo.airadd = $1 - 1
            if p.mo.airadd == 0
                     p.air = $1 + 1
            end
        end
 
Ironically enough I JUST figured out the problem before the post. Thanks for the help though. I'm getting to be a novice! ...at making small scripts....

EDIT: New problem with the script..
Code:
if p.airadd == nil
            p.airadd = 0
        end
        // Increase the air though the whirlwind shield and Zoomtube!
        if (player.powers[pw_shield] == SH_JUMP)
        or (player.mo.tracer and player.mo.tracer.type == MT_TUBEWAYPOINT)
        and p.airadd == 0
            p.airadd = TICRATE/2
        end


        if p.airadd > 0
            p.airadd = $1 - 1
        end

        if p.airadd == 1
            p.air = $1 + 2
        end
For some reason, the "or" in the script always points to the zoomtube instead of the wind shield... When the wind shield is up, it doesn't do anything, but if it were the zoomtube, it works like it should.
 
Last edited:
Code:
if ((player.powers[pw_shield] == SH_JUMP) or (player.mo.tracer and player.mo.tracer.type == MT_TUBEWAYPOINT)) and p.airadd == 0

Make your order of operations clear using brackets. This makes it so that either of the things in those two brackets can happen alongside the check for p.airadd.
 
Code:
        if not (p.omochao)
            p.omochao = 0
        end

        if p.omochao > 0
            p.omochao = 0
        end

        if p.air == 10
            p.omochao = 1
        end

        if player.powers[pw_shield] == SH_JUMP
            p.omochao = 2
        end

        if p.air == 0
            p.omochao = 3
        end

        if p.omochao == 1
            print("Omochao: "..player.name.. " is running out of air!")
        end

        if p.omochao == 2
            print("Omochao: "..player.name.. " is slowly gaining air...")
        end

        if p.omochao == 3
            print("Omochao: Oh no!" ..player.name.. "is out of air! That racer better get air quick!")
        end
To be honest, this script is atrocious. The whole point of it is to simply print a message. Except I don't know how to pull the official stop switch with this lua. It just continues to go on and on until the reason it printed in the first place is inactive. Any solutions?

NOTE: This script is part of a larger script, where "p" is a shortcut for "player".
 
Code:
        if p.air <= 10
        and p.air >= 1
            S_StartSound(nil, sfx_dwnind)
            print("Omochao: "..player.name.." is running out of air!")
            p.omochao = 1
        else
            return
        end
I tried to revise it, but it only led to the same issue. I was told to set a toggle, but I don't think I know how to set a proper toggle.
 
Sorry for the Triple Post, no one has been responding lately, and I have a new script to get help with.

Code:
addHook("ThinkFrame", do
    for player in players.iterate
        if player.mo.rider == 1
            if p.air > 15
            and P_IsObjectOnGround(player.mo)
                if (player.cmd.sidemove < 0)
                    P_Thrust(player.mo, -ANG2, 5*FRACUNIT)
                    player.mo.drifting = 1
                    local mobj = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_EXPLODE) 
                end
                
                if (player.cmd.sidemove > 0)
                    P_Thrust(player.mo, +ANG2, 5*FRACUNIT)
                    player.mo.drifting = 1    
                    local mobj = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_EXPLODE) 
                end
            end
        end
    end
end)
I started on a drifting mechanic similar to riders, and there are two things i'm not sure of. 1: The Angle turning. The wiki told me things, but I honestly don't know if I'm doing anything right. This also might have to do with the MobjSpawn. I'm going to test it right now just in case.
 
P_Thrust's angle parameter is absolute, not relative to the angle of the object that it's used on. You'll need to take the player mobj's angle into account when you try to control their momentum that way.
 
Thankfully, I tried it out and found my error, but the results of the angle don't seem to take place. Could this be a similar issue?

Code:
addHook("ThinkFrame", do
    for player in players.iterate
        if player.mo.rider == 1
            if player.air > 15
            and P_IsObjectOnGround(player.mo)

                if not (player.mo.drifting)
                    player.mo.drifting = 0
                end

                    if (player.cmd.sidemove < 0) --Left
                    and P_IsObjectOnGround(player.mo)
                        P_Thrust(player.mo, player.mo.angle-ANG2, 5*FRACUNIT)
                        player.mo.drifting = 1
                        local mobj = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_EXPLODE)
                    else
                        player.mo.drifting = 0
                    end
                else
                    if (player.cmd.sidemove > 0) --Right
                    and P_IsObjectOnGround(player.mo)
                        P_Thrust(player.mo, player.mo.angle+ANG2, 5*FRACUNIT)
                        player.mo.drifting = 1
                        local mobj = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_EXPLODE)
                    else
                        player.mo.drifting = 0
                    end
                end
            end
        end
    end)
 
If you're not seeing any change in the player's angle of movement, it's probably because ANG2 is very small, only 2 degrees out of 360. Try some of the larger angle constants and see if they produce visible effects.
 
The weird thing is that it doesn't auto turn the player.

EDIT: Changed up the code a little bit, but the effect is still the same.

Code:
addHook("ThinkFrame", do
    for player in players.iterate
        if player.mo.rider == 1
        and player.speed > player.runspeed
            if player.air > 15
            and P_IsObjectOnGround(player.mo)

                if not (player.mo.drifting)
                    player.mo.drifting = 0
                end

                    if (player.cmd.sidemove < 0) --Left
                    and P_IsObjectOnGround(player.mo)
                        P_Thrust(player.mo, player.mo.angle+ANGLE_90, 4*FRACUNIT)
                        player.mo.drifting = 1
                    else
                        player.mo.drifting = 0
                    end

                    if (player.cmd.sidemove > 0) --Right
                    and P_IsObjectOnGround(player.mo)
                        P_Thrust(player.mo, player.mo.angle-ANGLE_90, 4*FRACUNIT)
                        player.mo.drifting = 1
                    else
                        player.mo.drifting = 0
                    end

                    if player.mo.drifting == 1
                        local mobj = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_EXPLODE)
                    end
                end
            end
        end
    end)

EDIT: It turns out strafing doesn't seem to work correctly when being thrusted.... How the hell am I supposed to get around this?!
 
Last edited:
Code:
addHook("ThinkFrame", do
    for player in players.iterate
        if player.mo.rider == 1
        and player.speed > player.runspeed
            if player.air > 15
            and P_IsObjectOnGround(player.mo)

                if not (player.mo.drifting)
                    player.mo.drifting = 0
                end

                    if (player.cmd.sidemove < 0) --Left
                    and P_IsObjectOnGround(player.mo)
                        P_Thrust(player.mo, player.mo.angle+ANGLE_90, 4*FRACUNIT)
                        P_Thrust(player.mo, player.mo.angle, 4*FRACUNIT)
                        player.mo.drifting = 1
                    else
                        player.mo.drifting = 0
                    end

                    if (player.cmd.sidemove > 0) --Right
                    and P_IsObjectOnGround(player.mo)
                        P_Thrust(player.mo, player.mo.angle-ANGLE_90, 4*FRACUNIT)
                        P_Thrust(player.mo, player.mo.angle, 4*FRACUNIT)
                        player.mo.drifting = 1
                    else
                        player.mo.drifting = 0
                    end

                    if player.mo.drifting == 1
                        local mobj = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_PARTICLE)
                    end
                end
            end
        end
    end)

Not much has changed, but I shall post a gif alongside any changes for you to better understand the situation.

http://imgur.com/JSjKwgz
 
Show stuff on rankings HUD for all players?

Here was my Idea, I made a working HP bar with some sprites to go with it. But I also wanted the Rankings HUD screen to display each player's Health bar on the HUD... But then for some reason... Well... lemme show you with this lua...

Code:
local function scorehpbar(v, player)
    if player.mo and player.mo.skin == "sonic"
    and not (player.pflags & PF_NIGHTSMODE)        
        if player.mo.charhp == 4
        and netgame == true
            v.draw(480, 42, v.cachePatch("LIFET1"), V_SMALLSCALEPATCH)
        elseif player.mo.charhp == 3
        and netgame == true
            v.draw(480, 42, v.cachePatch("LIFET2"), V_SMALLSCALEPATCH)
        elseif player.mo.charhp == 2
        and netgame == true
            v.draw(480, 42, v.cachePatch("LIFET3"), V_SMALLSCALEPATCH)
        elseif player.mo.charhp == 1
        and netgame == true
            v.draw(480, 42, v.cachePatch("LIFET4"), V_SMALLSCALEPATCH)
        elseif player.mo.charhp == 0
        and netgame == true
            v.draw(480, 42, v.cachePatch("LIFET5"), V_SMALLSCALEPATCH)
        end        
    end
end
hud.add(scorehpbar, "scores")
SRB2 Said:
log.txt said:
WARNING: HPBAR.wad|LUA_HPBR:118: attempt to index local 'player' (a nil value)

Not sure what went wrong, but I was noted earlier I used a hook other than ThinkFrame.
 
I'm not sure which line is line 118, since you didn't provide the entirety of the script lump, but you might be able to fix your problem by adding "if player == nil return" before the first line of the scorehpbar function. That should prevent the function from causing problems when called on a nil player, which is what the game seems to be doing if you're getting that error message.
 
Status
Not open for further replies.

Who is viewing this thread (Total: 1, Members: 0, Guests: 1)

Back
Top