[self:Replace()] "OnCreate return nil" when trying to use a class based on Marine
Katzenfleisch
Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
Join Date: 2014-03-21 Member: 194881Members, Squad Five Blue, Squad Five Silver, NS2 Community Developer
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:
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
Also don't do that
local marineOnCreate = Marine.OnCreate function VeteranMarine:OnCreate() Print("VeteranMarine created") assert(1) marineOnCreate(self)do that
And ofc you have to include the marine.lua at the beginning of the file with Script.Load
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)
Code = the C button above in the "post editor" or ["code"]["/code"] ( without the "" )
function VerteranMarine:OnCreate() Marine.OnCreate(self) blah, blah, blah endI got around this issue by changing function in the Marine class and adding variable by hand.
Ex:
For now it work well.
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.
function VeteranMarine:OnInitialized() Print("VeteranMarine:OnInitialized") Marine.OnInitialized() endYou need a self in there, like below:function VeteranMarine:OnInitialized() Print("VeteranMarine:OnInitialized") Marine.OnInitialized(self) endI 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)[...] 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.
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 endkTechId = createTechIdEnum({ [...] // Added ID 'NapalmGrenade', 'NapalmGrenadeProjectile', 'NapalmGrenadeThrower', // Maximum index 'Max' })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
{ [kTechDataId] = kTechId.LaySentry,
[kTechDataMapName] = LaySentry.kMapName,
[kTechDataHint] = "SENTRY_HINT",
[kTechDataDisplayName] = "SENTRY_TURRET",
[kTechDataTooltipInfo] = "SENTRY_HINT",
[kTechDataModel] = Sentry.kModelName,
[kTechDataCostKey] = kMineCost },
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).
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)
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.