Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REQUEST: Allow DeriveGamemode("darkrp") #2244

Closed
EstevanTH opened this issue Dec 12, 2015 · 21 comments
Closed

REQUEST: Allow DeriveGamemode("darkrp") #2244

EstevanTH opened this issue Dec 12, 2015 · 21 comments

Comments

@EstevanTH
Copy link

Hi Falco & all,

I am making a gamemode based on DarkRP. I do not want to edit the DarkRP itself because I want to keep it up-to-date with SVN.

The problem is:

function GM:PlayerBindPress(ply, bind, pressed)
    self.BaseClass:PlayerBindPress(ply, bind, pressed) -- PROBLEM

    local bnd = string.match(string.lower(bind), "gm_[a-z]+[12]?")
    if bnd and FKeyBinds[bnd] then
        hook.Call(FKeyBinds[bnd], GAMEMODE)
    end

    if not self.Config.deadvoice and not ply:Alive() and string.find(string.lower(bind), "voicerecord") then return true end
end

When you use self.BaseClass on the DarkRP, it means that you use the GM from Sandbox.
But as I use a gamemode derived from the DarkRP, a problem happens: self.BaseClass means DarkRP instead of Sandbox.
Every call of GM or GAMEMODE methods using self.BaseClass are translated to the wrong GAMEMODE.

My solution is:
Replace any self.BaseClass in GM / GAMEMODE methods by something like FindSandboxGamemode().

The function FindSandboxGamemode() is shared and will find the GM / GAMEMODE from Sandbox. I will put an example later.

If you prefer, I can make a pull request and fix it myself.

@willox
Copy link

willox commented Dec 12, 2015

The proper solution is to use DEFINE_BASECLASS and the BaseClass upvalue rather than something like 'FindSandboxGamemode'.

@FPtje
Copy link
Owner

FPtje commented Dec 12, 2015

There's this guy called Giraffen93 (A.K.A. Braxen) who has a gamemode derived from DarkRP, in the way you describe. I've resolved similar issues with him before. Changing stuff to use DEFINE_BASECLASS might fuck shit up for him, he and I would have to look together to minimise breaking changes.

Either way, really good choice to create your gamemode this way. Thanks for thinking about the core files!

@EstevanTH
Copy link
Author

Currently I do not really understand how to use DEFINE_BASECLASS(). I have seen it in SENTs and SWEPs but it looks weird to me in gamemodes, especially when deriving.

There is something that I do not really understand with the BaseClass GM field. As displayed on GM Structure, it should be automatically translated when I use DeriveGamemode(). In my case it does not seem to.

I'll fix each failing feature by copying or hacking.

For reference, here is how I derived DarkRP:
shared.lua

GM.Name = "University RP"
GM.Author = "Mohamed RACHID"
GM.Website = "gmod-games.thouvest.ovh"
-- GM.TeamBased = true

if !universityrp_derived then
    universityrp_derived = true
    DeriveGamemode( "darkrp" )
end

init.lua

AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )

include( "shared.lua" )

cl_init.lua

include( "shared.lua" )

-- [hidden] fixed GM:PlayerBindPress() using self.BaseClass.BaseClass:PlayerBindPress(ply, bind, pressed)

@willox
Copy link

willox commented Dec 12, 2015

self.BaseClass can't automatically be correct because self is always an instance of the MAIN gamemode, not any sub-gamemodes.

DEFINE_BASECLASS( x )

evaluates as

local BaseClass = baseclass.Get( x )

It also does some other stuff (SWEP.Base = x, ENT.Base = x).

@EstevanTH
Copy link
Author

Thanks William!

Check this out, Falco! Of course it is not tested, I just used my inspiration.

local SANDBOX
function GM:FindSandboxGamemode()
    if SANDBOX then
        return SANDBOX
    else
        local parent = self
        for i=0,255 do
            if parent.BaseClass then
                if parent.BaseClass.Folder == "gamemodes/sandbox" then
                    SANDBOX = parent.BaseClass
                    return SANDBOX
                end
            end
            parent = parent.BaseClass
            if !parent then
                SANDBOX = self.BaseClass -- if DarkRP is not Sandbox-based
                return SANDBOX
            end
        end
        SANDBOX = self.BaseClass -- huge deriving loop
        return SANDBOX
    end
end

@FPtje
Copy link
Owner

FPtje commented Dec 12, 2015

I'd rather prevent that with DEFINE_BASECLASS

@EstevanTH
Copy link
Author

For information, I modified my deriving code. Here's my solution:

if !universityrp_derived then
    universityrp_derived = true
    DeriveGamemode( "darkrp" )

    hook.Add( "PostGamemodeLoaded", "TranslateDarkrpMethod", function()
        local function TranslateDarkrpMethod( MethodName )
            local old_MethodName = GAMEMODE[MethodName]
            GAMEMODE[MethodName] = function( self, ... )
                return old_MethodName( self.BaseClass, ... )
            end
        end

        TranslateDarkrpMethod( "SetupMove" )
        if CLIENT then
            TranslateDarkrpMethod( "PlayerStartVoice" )
            TranslateDarkrpMethod( "PlayerEndVoice" )
            TranslateDarkrpMethod( "PlayerBindPress" )
            TranslateDarkrpMethod( "DrawDeathNotice" )
            TranslateDarkrpMethod( "HUDPaint" )
        else
            TranslateDarkrpMethod( "Initialize" )
            TranslateDarkrpMethod( "PlayerSpawnProp" )
            TranslateDarkrpMethod( "PlayerSpawnedProp" )
            TranslateDarkrpMethod( "PlayerSpawnSENT" )
            TranslateDarkrpMethod( "PlayerSpawnedSENT" )
            TranslateDarkrpMethod( "PlayerSpawnSWEP" )
            TranslateDarkrpMethod( "PlayerGiveSWEP" )
            TranslateDarkrpMethod( "PlayerSpawnEffect" )
            TranslateDarkrpMethod( "PlayerSpawnVehicle" )
            TranslateDarkrpMethod( "PlayerSpawnedVehicle" )
            TranslateDarkrpMethod( "PlayerSpawnNPC" )
            TranslateDarkrpMethod( "PlayerSpawnedNPC" )
            TranslateDarkrpMethod( "PlayerSpawnRagdoll" )
            TranslateDarkrpMethod( "PlayerSpawnedRagdoll" )
            TranslateDarkrpMethod( "EntityRemoved" )
            TranslateDarkrpMethod( "KeyPress" )
            TranslateDarkrpMethod( "CanTool" )
            TranslateDarkrpMethod( "DoPlayerDeath" )
            TranslateDarkrpMethod( "PlayerDeath" )
            TranslateDarkrpMethod( "PlayerSetModel" )
            TranslateDarkrpMethod( "PlayerInitialSpawn" )
            -- TranslateDarkrpMethod( "PlayerSelectSpawn" ) -- explicit call from a method of DarkRP
            TranslateDarkrpMethod( "PlayerLoadout" )
            TranslateDarkrpMethod( "PlayerDisconnected" )
            TranslateDarkrpMethod( "PlayerLeaveVehicle" )
        end
    end )
end

@MrBrax
Copy link
Contributor

MrBrax commented Dec 13, 2015

function GM:PlayerBindPress( ... )
    self.BaseClass:PlayerBindPress( ... )
end

this is how i made the bind work

@FPtje
Copy link
Owner

FPtje commented Dec 13, 2015

Latest version contains fixes. @MrBrax your workarounds should still work, but you can remove them.

I'll upload a dummy derived gamemode.

@FPtje FPtje closed this as completed Dec 13, 2015
@FPtje
Copy link
Owner

FPtje commented Dec 13, 2015

@Shigbeard
Copy link
Contributor

Does this mean we get a new corefiles song?

On 13/12/2015 11:15 PM, Falco Peijnenburg wrote:

https:/FPtje/DarkRP/releases/tag/derived


Reply to this email directly or view it on GitHub
#2244 (comment).

@FPtje
Copy link
Owner

FPtje commented Dec 13, 2015

The old one still applies, this is just a way to make a gamemode based on DarkRP

@EstevanTH
Copy link
Author

Hello, I just noticed something that is dangerous when derivating the DarkRP:
DarkRP/blob/derived/gamemode/modules/base/sv_gamemode_functions.lua

timer.Simple(0.1, function()
    if not InitPostEntityCalled then
        GAMEMODE:InitPostEntity()
    end
end)

This makes GAMEMODE:InitPostEntity() being called with Lua live-refresh.
Do you know why this piece of code has been added?

@Bo98
Copy link
Contributor

Bo98 commented Dec 22, 2015

#168.

Not convinced if it's really needed anymore as you can break DarkRP in so many other ways (like enabling MySQL but not installing a MySQL module).

@FPtje
Copy link
Owner

FPtje commented Dec 22, 2015

I am, DarkRP breaks when another addon breaks in InitPostEntity. That piece of code prevents me from being blamed for other people's fuck ups.

@EstevanTH Why is it dangerous?

@EstevanTH
Copy link
Author

It's dangerous because I use GM:InitPostEntity() and GM:PostCleanupMap() in my derived gamemode to spawn things such as desks, video projectors, projector screens. 😇
And each time I changed one little thing of the gamemode, it respawned everything! 😧

@FPtje
Copy link
Owner

FPtje commented Dec 22, 2015

Good point

@FPtje FPtje reopened this Dec 22, 2015
@FPtje FPtje closed this as completed Dec 22, 2015
FPtje added a commit that referenced this issue Dec 22, 2015
Should fix the issue mentioned in #2244
@EstevanTH
Copy link
Author

Oh no, the update has not been put to the derived tag! 😵
The modification seems good though. 😃

@FPtje
Copy link
Owner

FPtje commented Dec 22, 2015

I can't push things to tags. The derived tag is just there to abuse the releases system to have a download. Don't tell Github about this little secret.

@EstevanTH
Copy link
Author

Huh, that's so sad. 😭 So in the end, the derived tag will get updates only sometimes, is that right?

@FPtje
Copy link
Owner

FPtje commented Dec 22, 2015

never if it's up to me. I might replace the download in the releases tag, but I don't give a shit otherwise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants