[self:Replace()] "OnCreate return nil" when trying to use a class based on Marine

KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
edited April 2014 in Modding
Hi,

I am trying to write a class who inherit from the Marine one, but I am stuck with this error on the OnCreate. The file is correctly included in the Server VM and the Client VM, and for me the kMapName, the ClassLink and the heritage seem ok. Note that the exception is raised in Utility.lu at line 1755 (OnCreate) and not on the assert on my code. Can you help me to figure out whats wrong ?

Thanks
=================================
code:
Script.Load("lua/Marine.lua")

class 'VeteranMarine' (Marine)

VeteranMarine.kMapName = "veteran_marine"

local networkVars =
{
}

local marineOnCreate = Marine.OnCreate
function VeteranMarine:OnCreate()
   Print("VeteranMarine created")
   marineOnCreate(self)
   self.kFadedMentalStrenght = kFadedVeteranMarineMentalStrenght
   self:SetSelected(1, true, true)
   self:SetSelected(2, true, true)
end

function VeteranMarine:OnInitialized()
   Print("VeteranMarine:OnInitialized")
   Marine.OnInitialized()
end

function VeteranMarine:OnDestroy()
   Marine.OnDestroy(self)
end

-- Veteran have armor 1 / weapon 1
function VeteranMarine:GetArmorLevel()
   Print("VeteranMarine: GetArmorLevel")
   return (1)
end
function VeteranMarine:GetWeaponLevel()
   Print("VeteranMarine: GetWeaponLevel")
   return (1)
end

function VeteranMarine:GetMaxSpeed(possible)
   return (Player.kWalkMaxSpeed * 1.1)
end

Shared.LinkClassToMap("VeteranMarine", VeteranMarine.kMapName, networkVars, true)

Comments

  • JimWestJimWest Join Date: 2010-01-03 Member: 69865Members, Reinforced - Silver
    edited April 2014
    wtf is return (1) and assert(1) ????
    Also don't do that
    local marineOnCreate = Marine.OnCreate
    function VeteranMarine:OnCreate()
       Print("VeteranMarine created")
       assert(1)
       marineOnCreate(self)
    

    do that
    function VeteranMarine:OnCreate()
     Marine.OnCreate(self)
    end
    

    And ofc you have to include the marine.lua at the beginning of the file with Script.Load


  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    edited April 2014
    Thanks for the answer. The assert were here to have a strong indication if the lua interpreter goes there (a debug line). Also, the Script.Load is ok as I include both in the Shared.lua file: Marine first, then VeteranMarine.

    About the return (1), I overload the standard "GetWeaponLevel" (in Marine.lua) function to force the entity to have weapon 1 and armor 1 upgrade.

    Ps: Which "code" did you use on the forum to pretty print lua code ? (main post corrected)
  • GhoulofGSG9GhoulofGSG9 Join Date: 2013-03-31 Member: 184566Members, Super Administrators, Forum Admins, Forum Moderators, NS2 Developer, NS2 Playtester, Squad Five Blue, Squad Five Silver, Reinforced - Supporter, WC 2013 - Supporter, Pistachionauts
    Thanks for the answer. The assert were here to have a strong indication if the lua interpreter goes there (a debug line). Also, the Script.Load is ok as I include both in the Shared.lua file: Marine first, then VeteranMarine.

    About the return (1), I overload the standard "GetWeaponLevel" (in Marine.lua) function to force the entity to have weapon 1 and armor 1 upgrade.

    Ps: Which "code" did you use on the forum to pretty print lua code ?

    Code = the C button above in the "post editor" or ["code"]["/code"] ( without the "" )
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    The main post has been updated with the ["code"]. I will continue to search why OnCreate() return me nil and post the answer if I found it.
  • Soul_RiderSoul_Rider Mod Bean Join Date: 2004-06-19 Member: 29388Members, Constellation, Squad Five Blue
    edited April 2014
    Try changing the code to this:
    function VerteranMarine:OnCreate()
    
        Marine.OnCreate(self)
        blah, blah, blah
    
    end
    
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    edited April 2014
    hum, I still have a nil return value exception for the CreateEntity() function.

    I got around this issue by changing function in the Marine class and adding variable by hand.
    Ex:
    player.GetMaxSpeed = VeteranMarine.GetMaxSpeed
    

    For now it work well.
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    edited April 2014
    Up.
    I am trying to create a class from ClipWeapon and I am still stuck on the same issue.
    * "CreateEntity(...) return nil" when trying the command "give my_new_weapon". I have been looking for existing NS2 weapon and mod weapon but without success. My lua weapon files is correctly include by all three VM.

    Has someone a tuto or something to help me on creating even a weapon that does nothing but can be created and seen in the player weapon UI (on slot 6/7 for exemple to not conflict with grenade and mines, no matter which icon or animation).
    Thanks.
  • xDragonxDragon Join Date: 2012-04-04 Member: 149948Members, NS2 Playtester, Squad Five Gold, NS2 Map Tester, Reinforced - Shadow
    edited April 2014
    IDK if you fixed this already, but this is wrong
    function VeteranMarine:OnInitialized()
       Print("VeteranMarine:OnInitialized")
       Marine.OnInitialized()
    end
    
    You need a self in there, like below:
    function VeteranMarine:OnInitialized()
       Print("VeteranMarine:OnInitialized")
       Marine.OnInitialized(self)
    end
    
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    edited April 2014
    This has been fixed, but still have the exception.
    I past you the code used during the test (but in prod i remove the OnCreate, Marine heritage and the LinkClassToMap).
    To use the old version, the "VeteranMarine:UpgradeMarine(player)" is used for the upgrade, I change the MaxHealth and MaxArmor (so i do not have issue with Client/Server VM) as you can see in the last function GetMaxSpeed to know on client side if a marine has been upgraded.

    I try using networkMessage for this check (kIsMarineVeteran = "boolean", HookNetworkMessage, etc), it work but the Client seem to reset the value after a really short amount of time. Working on it.

    I past also the code of GetArmorLevel() which seem not working (to give weapon/armor upgrade the clean way), I overload instead damageMixin with the same 'self:GetMaxArmor() == kFadedVeteranArmor' check to get it working. I know its not the clean way to do it but for now it is the only way I made this working. Note: kFadedVeteranArmor and kFadedVeteranHealth are declared in an other file which is loaded before this one.

    I add in attachment a screen shot of the console, hope this can help.
    Script.Load("lua/Marine.lua")
    -- Script.Load("lua/FadedMarine.lua")
    
    -- If true, the next marine created will be a veteran
    -- kFadedIsNextMarineVeteran = false
    
    class 'VeteranMarine' (Marine)
    
    VeteranMarine.kMapName = "veteranmarine"
    
    local networkVars =
    {
    }
    function VeteranMarine:OnInitialized()
       Marine.OnInitialized(self)
    end
    
    function VeteranMarine:OnCreate()
       Marine.OnCreate(self)
    end
    
    function VeteranMarine:UpgradeMarine(player)
       player.kFadedMentalStrenght = kFadedVeteranMarineMentalStrenght
       player.kFadedIsVeteran = true
    
       player:SetMaxArmor(kFadedVeteranArmor)
       player:SetArmor(kFadedVeteranArmor)
       player:SetMaxHealth(kFadedVeteranHealth)
       player:SetHealth(kFadedVeteranHealth)
    end
    
    -- Force printing of the GUI of marine armslabs upgrade
    -- even whithout arms labs
    if (Client) then
       local playerUI_GetArmorLevel = PlayerUI_GetArmorLevel
       function PlayerUI_GetArmorLevel(researched)
          local p = Client.GetLocalPlayer()
          if (p and p:GetMaxHealth() == kFadedVeteranHealth
    	  and p:GetMaxArmor() == kFadedVeteranArmor) then
    	 return (1)
          else
    	 return (playerUI_GetArmorLevel(researched))
          end
       end
    
       local playerUI_GetWeaponLevel = PlayerUI_GetArmorLevel
       function PlayerUI_GetWeaponLevel(researched)
          local p = Client.GetLocalPlayer()
          if (p and p:GetMaxHealth() == kFadedVeteranHealth
    	  and p:GetMaxArmor() == kFadedVeteranArmor) then
    	 return (1)
          else
    	 return (playerUI_GetWeaponLevel(researched))
          end
       end
    end
    
    -- local marineGetArmorLevel = Marine.GetArmorLevel
    -- function Marine:GetArmorLevel()
    --    local armor_lvl = marineGetArmorLevel(self)
    --    if (kFadedIsNextMarineVeteran == true) then
    --       armor_lvl = 1
    --    else
    --       armor_lvl = 3
    --    end
    --    return (armor_lvl)
    -- end
    
    -- local marineGetWeaponLevel = Marine.GetWeaponLevel
    -- function Marine:GetWeaponLevel()
    --    local weapon_lvl = marineGetWeaponLevel(self)
    --    if (kFadedIsNextMarineVeteran == true) then
    --       weapon_lvl = 1
    --    else
    --       weapon_lvl = 3
    --    end
    --    return (weapon_lvl)
    -- end
    
    -- Increase max walking speed of Veteran marine
    local marineGetMaxSpeed = Marine.GetMaxSpeed
    function Marine:GetMaxSpeed(possible)
       -- Print("VeteranMarine:GetMaxSpeed()")
       local speed_boost = 1
       if (self.GetMaxArmor and self.GetMaxHealth
    	  and self:GetMaxArmor() == kFadedVeteranArmor
    	  and self:GetMaxHealth() == kFadedVeteranHealth)
       then
          speed_boost = 1 + kFadedVeteranSpeedBonus
       end
       return (marineGetMaxSpeed(self, possible) * speed_boost)
    end
    
    Shared.LinkClassToMap("veteranmarine", VeteranMarine.kMapName, networkVars, true)
    
  • fsfodfsfod uk Join Date: 2004-04-09 Member: 27810Members, NS2 Developer, Constellation, NS2 Playtester, Squad Five Blue, Squad Five Silver, Squad Five Gold, Subnautica Playtester, NS2 Community Developer, Pistachionauts
    I think the only way you will get nil result from CreateEntity with no error printed to the log/console is if the was class not registered/name misspelled or was registered too late with LinkClassToMap. Calls to LinkClassToMap are effectively deferred because it hooked as part of the modentry system to the until PostLoadMod.lua is loaded. I think after its loaded LinkClassToMap just silently does nothing
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    edited April 2014
    Is it maybe because i load NS2 script before my script ?
    [...] MyModClient.lua
    Script.load("lua/Client.lua")
    (my lua)
    [...] MyModPredict.lua
    Script.load("lua/Predict.lua")
    (my lua)
    [...]MyModServer.lua 
    Script.load("lua/Server.lua")
    (my lua)
    

    Edit: The other mode seem to do the same, I don't thinks its that.
  • Soul_RiderSoul_Rider Mod Bean Join Date: 2004-06-19 Member: 29388Members, Constellation, Squad Five Blue
    Have you added Veteran marine to the tech data and tech tree constants? I would say it is almost certainly an issue with the way you have got the code set-up. You are probably missing something somewhere to get the code fully integrated.
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    I will give it a try today and keep you informed.
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    edited May 2014
    Look like I can't make it working, createEntity(...) continue to return a nil value. I was looking on how the xenoswarm/Factions (Workshop/m7e64c1a_1379113909/) mode were doing this kind of stuff (with the light machine gun). I was trying to create a class for a new Napalm Grenade entity this time.

    I have tried to:
    * Add data to TechData.lua
    kModdedTechData =
    {
          {[kTechDataId] = kTechId.NapalmGrenade,
           [kTechDataMapName] = NapalmGrenade.kMapName,
           [kTechDataDisplayName] = "NAPALM_GRENADE",
           [kTechDataTooltipInfo] =  "NAPALM_GRENADE_TOOLTIP",
           [kTechDataCostKey] = kClusterGrenadeCost }
    }
    
    
    local overrideBuildTechData = BuildTechData
    function BuildTechData()
    
       local defaultTechData = overrideBuildTechData()
       local moddedTechData = {}
       local usedTechIds = {}
    
       Print("Custom BuildTechData")
       for i = 1, #kModdedTechData do
          local techEntry = kModdedTechData[i]
          table.insert(moddedTechData, techEntry)
          table.insert(usedTechIds, techEntry[kTechDataId])
          Print("Insert Napalm")
       end
    
       for i = 1, #defaultTechData do
          local techEntry = defaultTechData[i]
          if not table.contains(usedTechIds, techEntry[kTechDataId]) then
    	 table.insert(moddedTechData, techEntry)
          end
       end
    
       return moddedTechData
    
    end
    
    * Add an entry to the TechId enum (which is const, so I have to overload the complete file)
    kTechId = createTechIdEnum({
       [...]
       // Added ID
        'NapalmGrenade', 'NapalmGrenadeProjectile', 'NapalmGrenadeThrower',
    
        // Maximum index
        'Max'
        
        })
    
    * Create class for the Napalm Grenade weapon (NapalmGrenade and NapalmGrenadeThrower). I simply copy/past the code of an existing grenade and change some name. At this point I knew there would be a lot of exception but at least if I had one this issue would be solved.
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    edited April 2015
    Up,

    I am trying to fix this again (creating a new class and use it ingame (with marine:giveItem(myItem.kMapName) for ex, even an empty one) but have no glue on why it does not works. CreateEntity() always return nil for a reason I ignore.

    For simplicity I am trying to run a mod with the smallest amount of change for it to work.
    Note: LaySentry.lua is a file I copy&past from the LastResistance mod on which it is working. (mod: "Workshop/m108be936_1428163690").

    Tree if the mod:
    .
    ├── lua
    │   ├── modShared.lua
    │   ├── modClient.lua
    │   ├── modServer.lua
    │   ├── modPredict.lua
    │   ├── modMarine.lua
    │   ├── LaySentry.lua
    │   ├── TechData.lua
    │   └── TechTreeConstants.lua
    ├── game_setup.xml
    └── .modinfo
    Changes to the TechData.lua file:

    { [kTechDataId] = kTechId.LaySentry,
    [kTechDataMapName] = LaySentry.kMapName,
    [kTechDataHint] = "SENTRY_HINT",
    [kTechDataDisplayName] = "SENTRY_TURRET",
    [kTechDataTooltipInfo] = "SENTRY_HINT",
    [kTechDataModel] = Sentry.kModelName,
    [kTechDataCostKey] = kMineCost },
    Lines Added to TechTreeConstant.lua (to the enum)
    'LaySentry', 'LayExosuit',
    modMarine.lua:
    Script.Load("lua/Marine.lua")

    local marineOnInitialized = Marine.OnInitialized
    function Marine:OnInitialized()
    ....marineOnInitialized(self)
    ....self:GiveItem(LaySentry.kMapName) -- This is not working
    ....-- self:GiveItem(LayExosuit.kMapName)
    end

    local marineOnCreate = Marine.OnCreate
    function Marine:OnCreate()
    ....marineOnCreate(self)
    end

    I have attached the whole set as a .zip (if you need it)

    Any help is welcomed :)
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
  • GhoulofGSG9GhoulofGSG9 Join Date: 2013-03-31 Member: 184566Members, Super Administrators, Forum Admins, Forum Moderators, NS2 Developer, NS2 Playtester, Squad Five Blue, Squad Five Silver, Reinforced - Supporter, WC 2013 - Supporter, Pistachionauts
    edited April 2015
    Up,

    I am trying to fix this again (creating a new class and use it ingame (with marine:giveItem(myItem.kMapName) for ex, even an empty one) but have no glue on why it does not works. CreateEntity() always return nil for a reason I ignore.

    For simplicity I am trying to run a mod with the smallest amount of change for it to work.
    Note: LaySentry.lua is a file I copy&past from the LastResistance mod on which it is working. (mod: "Workshop/m108be936_1428163690").

    Tree if the mod:
    .
    ├── lua
    │   ├── modShared.lua
    │   ├── modClient.lua
    │   ├── modServer.lua
    │   ├── modPredict.lua
    │   ├── modMarine.lua
    │   ├── LaySentry.lua
    │   ├── TechData.lua
    │   └── TechTreeConstants.lua
    ├── game_setup.xml
    └── .modinfo
    Changes to the TechData.lua file:

    { [kTechDataId] = kTechId.LaySentry,
    [kTechDataMapName] = LaySentry.kMapName,
    [kTechDataHint] = "SENTRY_HINT",
    [kTechDataDisplayName] = "SENTRY_TURRET",
    [kTechDataTooltipInfo] = "SENTRY_HINT",
    [kTechDataModel] = Sentry.kModelName,
    [kTechDataCostKey] = kMineCost },
    Lines Added to TechTreeConstant.lua (to the enum)
    'LaySentry', 'LayExosuit',
    modMarine.lua:
    Script.Load("lua/Marine.lua")

    local marineOnInitialized = Marine.OnInitialized
    function Marine:OnInitialized()
    ....marineOnInitialized(self)
    ....self:GiveItem(LaySentry.kMapName) -- This is not working
    ....-- self:GiveItem(LayExosuit.kMapName)
    end

    local marineOnCreate = Marine.OnCreate
    function Marine:OnCreate()
    ....marineOnCreate(self)
    end

    I have attached the whole set as a .zip (if you need it)

    Any help is welcomed :)

    Ok i had a short look.

    So far you change the game-setup.xml loading points but don't relink to some of the original vanilla files (Server.lua, Shared.lua).
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    The old zip was wrong (the one on the new "edit" post is ok), now modServer.lua correctly load Server.lua (like modPredict.lua load Predict.lua and modClient.lua load Client.lua). modMarine.lua loads Marine.lua.
  • GhoulofGSG9GhoulofGSG9 Join Date: 2013-03-31 Member: 184566Members, Super Administrators, Forum Admins, Forum Moderators, NS2 Developer, NS2 Playtester, Squad Five Blue, Squad Five Silver, Reinforced - Supporter, WC 2013 - Supporter, Pistachionauts
    edited April 2015
    Okay then fsfod's answer applies again. Your stuff gets loaded after PostLoadMap.lua has been loaded at which point LinkClassToMap is useless meaning the LaySentry class actually never gets mapped.

    So you have to make sure the class get loaded before that.

    You could do that by editing the given files Client.lua, Server.lua, Predict.lua files directly and overload them like you already do it with TechTreeConstants.lua and TechData.lua or start using the entry system or injecting your mod into some previous loading files etc. .

    Also Player:GiveItem() is a server sided method (make sure you don't mess up between the vms) ;)
  • KatzenfleischKatzenfleisch Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
    Its working :). I had to edit Shared.lua. Thank you you allow me to end a lots of pain.

    Finally, to add a new entity to the game we have to:
    1/ Edit TechData.lua & TechTreeConstants.lua
    2/ load the lua of your entity (Ex: LaySentry.lua) in Shared.lua

    It's finaly solved.
Sign In or Register to comment.