Steam Workshop Mod Loader, v.1


Recommended Posts

q2CUUCS.png

 

 

http://steamcommunity.com/sharedfiles/filedetails/?id=492172658

 

v1 of an Integrated mod loader

 

To install:
1. Subscribe to this mod
2. Go into Invisible Inc, and press Refresh Languages
3.. Make a backup of these files in your root directory:
      - main.lua
      - moai.lua
      - scripts.zip
4. Go into the mod directory and find this readme.txt 
5. Copy the files into the game's root directory
6. Launch Invisible, Inc, and enjoy some simple mod support
 
Check mods/sample to see how to publish your own compatible workshop mod.

 

 
If you install this mod, and follow the directions, you can subscribe to and run mods hosted on the steam workshop that will run whatever arbitrary lua code they want.
 
From there, we should be able to do a lot more. This supports mods defining a load() and unload() function to allow them to be toggled.
 
If you have any questions or want to help improve this, let me know. 
 
:-)
 
** NOW COMPATIBLE WITH UPDATE 11 **
 
 
Link to comment
Share on other sites

Does anyone have a very simple weapon / character / item / whatever mod that I should try to make work with this system?

 

I have a working workshop hosted emp/overload/shocktrap range fix mod, but since that's going to be fixed very soon it's not that useful besides as a proof of concept.

Link to comment
Share on other sites

Wow, awesome. Today I wanted to write an idea of how a modloader could work and ask if anyone wants to code it (Im still going to do it in some days since there are still the gog and Humble gamers). I will also port all my mods to this system (while still offering new versions here ofc). You could use this mod as an example:

http://forums.kleientertainment.com/topic/54356-mod-fully-eqiped-agents-in-detenion-centers/

and mark me as a creator. My Steam Name is Human_Kirby.

It just changes the code from 1041 to 1058. Which makes it a small tweak, good for a showcase of it.

Link to comment
Share on other sites

Ok, I looked into the sample, but could only find 2 files, main.lua and modinfo.txt, containing the following:

main.lua:

local mod = {};

function mod:load()
    log:write("Enabled");
    return true
end

function mod:unload()
    log:write("Disabled");
    return true
end

return mod;
 

modinfo.txt

name=Sample_Mod
modtype=game
id=samplemod

This doesnt really tell me what I have to do to make my mods run with this system.

Link to comment
Share on other sites

Yeah, the sample was purely for proof of concept to show running code from a workshop mod loaded by the game was actually possible. The hard part is figuring out how to access and hook the data you need to actually modify game behavior. It's a bit involved and can take some digging, but I've got a utility lib I developed while modding another lua-based game which should help. I only started modding Invisible, Inc today, so I'm sure there is a lot of domain knowledge you could share.

 

I'll take a look at the mod you suggest and see what I can do, and I'll message you on steam. :)

 

This is only v1. I'm sure there are many more improvements we could make to this modloader to improve the modding experience. :)

Link to comment
Share on other sites

Wow, awesome. Today I wanted to write an idea of how a modloader could work and ask if anyone wants to code it (Im still going to do it in some days since there are still the gog and Humble gamers). I will also port all my mods to this system (while still offering new versions here ofc). You could use this mod as an example:

http://forums.kleientertainment.com/topic/54356-mod-fully-eqiped-agents-in-detenion-centers/

and mark me as a creator. My Steam Name is Human_Kirby.

It just changes the code from 1041 to 1058. Which makes it a small tweak, good for a showcase of it.

 

Here we are:

http://steamcommunity.com/sharedfiles/filedetails/?id=492421576

 

You were right, that was a pretty easy one to do. :)

 

I sent you a friend request on steam, message me when you're on and I can tell you more about this. I'm not sure how to test this quickly, but I did test to make sure the data wasn't accessed before the mod changed it, so I believe it works.

 

I need to also add a modloader version number prereq to the modinfo.txt and do a million other things to make this better. :)

Link to comment
Share on other sites

Ok, I can confirm that it works. Also, I think Im ale to kinda figure it out, but its in my time zone really early and have it somewhat explained is always better. Thanky you for your work, this will get modding quite alot further, espacilly since it is alot easier to "install" and "deinstall" a mod for users and easier to update a mod for modmakers (also, if you mess up, it dosnt mean you have to load a backup of your game.).

 

 

Also, I added the Modloader to the Master Modlist and also add ways to indicate which mods use it.

Link to comment
Share on other sites

Ok, as an exercise, I tryed to port this mod http://forums.kleientertainment.com/topic/54588-mod-starting-programs/

into this system, it just downst work. Anyone know why?

local mod = {}

local function upvalues( func )
    local i = 0;
    if not func then
        return function() end
    else
        return function()
            i = i + 1
            local name, val = debug.getupvalue (func, i)
            if name then
                return i,name,val
            end -- if
        end
    end
end
    
local function GetUpValue( func, upname )
    for i,name,val in upvalues( func ) do
        if name == upname then
            return val
        end
    end
end

local serverdefs = include( "modules/serverdefs" )
local SELECTABLE_PROGRAMS = serverdefs.SELECTABLE_PROGRAMS

function mod:load()
    
    self.bak = {}
    
    log:write( "Programs+ Enabled" );
    self.bak.SELECTABLE_PROGRAMS = SELECTABLE_PROGRAMS
    SELECTABLE_PROGRAMS =
    {
    [1] = -- Power generators
    {
        "remoteprocessor",
        "fusion",
        "seed",
        "faust",
        "emergency_drip",
        "wildfire",
        "pwr_manager",
        "pwr_manager_2",
        "taurus",
        "lockpick_1",
        "lockpick_2",
        "wrench_2",
        "wrench_3",
        "wrench_4",
        "wrench_5",
        "hammer",
        "dagger",
        "dagger_2",
        "parasite",
        "parasite_2",
        "sniffer",
        "hunter",
        "mainframePing",
        "rapier",
        "brimstone",
        "oracle",
        "wings",
        "shade",
        "leash",
        "dataBlast",
        "esp",
        "love",
        
    },
    [2] = -- Breakers
    {
        "remoteprocessor",
        "fusion",
        "seed",
        "faust",
        "emergency_drip",
        "wildfire",
        "pwr_manager",
        "pwr_manager_2",
        "taurus",
        "lockpick_1",
        "lockpick_2",
        "wrench_2",
        "wrench_3",
        "wrench_4",
        "wrench_5",
        "hammer",
        "dagger",
        "dagger_2",
        "parasite",
        "parasite_2",
        "sniffer",
        "hunter",
        "mainframePing",
        "rapier",
        "brimstone",
        "oracle",
        "wings",
        "shade",
        "leash",
        "dataBlast",
        "esp",
        "love",
        
    },
    }
    SELECTABLE_PROGRAMS.hooked = true
    
    return true
end

function mod:unload()
    
    SELECTABLE_PROGRAMS = self.bak.SELECTABLE_PROGRAMS
    self.bak.SELECTABLE_PROGRAMS = nil
    SELECTABLE_PROGRAMS.hooked = false    
    log:write( "Programs+ Disabled" );
    
    return true
end

return mod;
 

Link to comment
Share on other sites

I figured out why your code doesn't work, HumanKirby. Instead of

SELECTABLE_PROGRAMS = {list}

you need

serverdefs.SELECTABLE_PROGRAMS = {list}

Also you don't need the hooks or the upvalue functions, as those were only needed since the detention center list is sort of like a 'list inside a list' if you understand what I mean. The code for selectable programs is alot easier in that sense.

 

Link to comment
Share on other sites

Hmmm, that makes sense, I just used the file of the FEAgents as a template. Im going to have alot of fun to port some of the mods which hopefully wont break with the update (the detention center and the programs should work (even if I have to add the new ones to the list)). So, the 8 augmentation mod and the MKII will be the next I look into. (yhe 8 augmentation should be easy, the MKII will need a bit more work but if I figure it out, I might be ready to do alot more complex stuff after the update.)

Link to comment
Share on other sites

Ok, once again, thank you for this program/mod. The backup works with the FEAgents Mod, but not with my Programs+. If you could tell me what I did wrong i could proced to learn more.

Also, here is a list of suggestions (mostly one)

- Hovering over a mods name should pop up a box (a blue box right or left to the mod gui) which shows the authors name, a brief description of the mod and the latest version of invisible which the mod suports. This information could be saved in the modinfo.txt

- a debug tickbox which shows more information which files are edited, if the mod was fully loaded(even if you see it on the on/off switch. if it doesnt work, it currently just stays off all the time), if a backup was created etc. It could be at the other site of the mod gui than the normal information. In my current case I haveto work at the mod, go into invisible inc, check and uncheck my mod and look if it deactived (it still shows me all the programs, so I messed up). This would eliminate this last step, which could be alot safed time if it changes something in day 10

- a button in the mod information box which opens a link in your browser to show you the mod on the forums. This again could be safed in the modinfo.txt, and if there is no link the box would be unclickable. (You should add an check that it really goes to http://forums.kleientertainment.com to prevent fishing links

Link to comment
Share on other sites

Oh, my mistake. I forgot to tell you that

SELECTABLE_PROGRAMS = self.bak.SELECTABLE_PROGRAMS

also needs to be

serverdefs.SELECTABLE_PROGRAMS = self.bak.SELECTABLE_PROGRAMS

 

Also, there is a problem with this program.

 

Let's say we have two mods, Mod1 and Mod2, that both change let's say selectable programs.

If you click first Mod1 and then Mod2, Mod2 will be overwritten.

If you then click Mod2 again, only Mod1 will be installed and if you also click Mod1 you will return to default.

However, if you click Mod1 first, you will still go back to default even if Mod2 is turned on, and if you click Mod2 after that, Mod1 will be installed, despide both of them being turned off!

 

I suggest that instead of installing a mod when you click it, don't apply changes until you have clicked accept.

That way you can start with a clean game and make sure all mods are installed in correct order.

Link to comment
Share on other sites

Ok, it works now and is published: http://steamcommunity.com/sharedfiles/filedetails/?id=492773671

THe picture is just placeholder and I will add actuall images. Also, is it possible to transfer the "ownage of a Steam Workshop page" to another person, so I can edit me Prisons are fully eqiped mod with images etc.

We are going to need some sort of guideline on how  a modpage should look. Also, I would like to see as tofeature to add .kwad files autside the script.zip, editing of te main.lua, and adding lua files in the scripts.zip and adding lines into lists, so I could, as an example, add the program "whatever_1" to the list of the SELECTABLE_PROGRAMS and another user could add "whatever_2".

Link to comment
Share on other sites

This sounds exciting! :)

 

Glad you've been able to figure it out. A lot of making it so multiple mods can modify the same thing are just dependent on people working together. Sometimes they are not compatible or conflict, but as long as you strive to change it in the least destructive way, you should maintain the highest amount of compatibility. 

 

For example with that last mod you posted, if you only added new items to the list, and the order doesn't matter, you could just append the list (util.extend i think does this), and then pull them out again if its unloaded. If you do it right, it won't matter if another mod adds/removes to the same list as long as you both only modify what you need to.

 

Editing main.lua could be possible, at least once we pass the mod-manager step... adding new assets should also be possible since that's essentially what the localization mods do. Changing pre-existing assets will be more of a challenge but again, it should be possible... it might just take hooking where lua references these assets to redirect them to a different file location (like i do with the options dialog)

Link to comment
Share on other sites

Does anyone have a very simple weapon / character / item / whatever mod that I should try to make work with this system?

 

I have a working workshop hosted emp/overload/shocktrap range fix mod, but since that's going to be fixed very soon it's not that useful besides as a proof of concept.

Hi there!

I've made an paralyzer that does the following:

- Uses 1 PWR per use

- Adds 1 KO when used

- TAGs the target

- No cooldown

scripts.zip

 

Files Modified:

strings.lua: 2944+, 3361+

paralyze.lua: 12+, 70-+, 87+

itemdefs.lua: 1155-+

 

This mod modifies some more files than itemdefs.lua, since it adds completely different function to existing items.

Well... Now I've read you're in need of "simple" item. Sorry...

Link to comment
Share on other sites

Yeah, it's not too hard to do this one either.

 

My only question is do lines 97-101 in executeAbility in paralyze.lua need to be in that exact spot? Do the dispatch events need to happen before it? Do the trash/use items need to happen after?

 

There's a really simple pattern for hooking these functions to add extra behavior like this IF the new code is either at the very start or very end of the function.

 

If it needs to be in the middle, you might need to mod the whole function.

 

As an example, to make this change to canUseAbility to include your new code:

local paralyze = include( "sim/abilities/paralyze" )local oldCanUseAbility = paralyze.canUseAbility; paralyze.canUseAbility = function( self, sim, unit )  local ok, reason = oldCanUseAbility( self, sim, unit )   if not ok then    return false, reason  end   if unit:getTraits().pwrCost then    if unit:getPlayerOwner():getCpus() < unit:getTraits().pwrCost then      return false, STRINGS.UI.REASON.NOT_ENOUGH_PWR, STRINGS.UI.FLY_TXT.NOT_ENOUGH_PWR    end  end   return trueend
Link to comment
Share on other sites

Yeah, it's not too hard to do this one either.

My only question is do lines 97-101 in executeAbility in paralyze.lua need to be in that exact spot? Do the dispatch events need to happen before it? Do the trash/use items need to happen after?

There's a really simple pattern for hooking these functions to add extra behavior like this IF the new code is either at the very start or very end of the function.

If it needs to be in the middle, you might need to mod the whole function.

As an example, to make this change to canUseAbility to include your new code:

local paralyze = include( "sim/abilities/paralyze" )local oldCanUseAbility = paralyze.canUseAbility; paralyze.canUseAbility = function( self, sim, unit )  local ok, reason = oldCanUseAbility( self, sim, unit )   if not ok then    return false, reason  end   if unit:getTraits().pwrCost then    if unit:getPlayerOwner():getCpus() < unit:getTraits().pwrCost then      return false, STRINGS.UI.REASON.NOT_ENOUGH_PWR, STRINGS.UI.FLY_TXT.NOT_ENOUGH_PWR    end  end   return trueend
Since TAGing after paralyzing is exactly same to paralyzing after TAGing, yes it's safe to move the code.

It's also Okay to check CPU reason after checking original reasons, for similar reasons.

In fact, this way of modding looks way better than what I did.

Edit: I think it's safe to do something after trashing/using item, since the code is already being executed.

Link to comment
Share on other sites

@ik1ne, here's the full version. Test it out and see if it works:

 

local mod = {} local util = include( "modules/util" )local commondefs = include( "sim/unitdefs/commondefs" )local simdefs = include( "sim/simdefs" ) local STRINGS = include( "client/strings" )local itemdefs = include( "sim/unitdefs/itemdefs" )local paralyze = include( "sim/abilities/paralyze" ) function mod:load()   STRINGS.ABILITIES.PARALYZE_NANO = "Paralyzer Dose"  STRINGS.ABILITIES.PARALYZE_NANO_DESC = "Inject pinned victims with nanobot. Target will be KO'd for {1} more turns and tagged.",   STRINGS.ITEMS.PARALYZER_NANO = "Nanobot Injector"  STRINGS.ITEMS.PARALYZER_NANO_TOOLTIP = "Use on pinned targets. KOs targets for an extra 1 turn and TAGs them."  STRINGS.ITEMS.PARALYZER_NANO_FLAVOR = "Instead of traditional toxin that might leave some trails, this experimental tech constructs nanobot from victim's blood cell."   -- no way to access item_template, so either need to do util.extend manually  -- or need to make your own item_template:  local item_template =    {    type = "simunit",    traits = { selectpriority = 0 },    onWorldTooltip = commondefs.onItemWorldTooltip,    onTooltip = commondefs.onItemTooltip,  }   -- since it's a hash table, the position in the array is completely irrelevant,  -- and we can just add it in like this:  itemdefs.item_paralyzer_nano = util.extend(item_template)  {    name = STRINGS.ITEMS.PARALYZER_NANO,    desc = STRINGS.ITEMS.PARALYZER_NANO_TOOLTIP,    flavor = STRINGS.ITEMS.PARALYZER_NANO_FLAVOR,    icon = "itemrigs/FloorProp_AmmoClip.png",    --profile_icon = "gui/items/icon-paralyzer.png",    profile_icon = "gui/icons/item_icons/items_icon_small/icon-item_paralyzerdose_small.png",    profile_icon_100 = "gui/icons/item_icons/icon-item_paralyzer_dose.png",    abilities = { "carryable","paralyze" },    traits = { koTime = 1, pwrCost = 1, canTag = true, nopwr_guards = {} },    value = 1000,    floorWeight = 3,  }   -- before returning the tool templates, there is a for loop that does this,   -- so we must do the same, but manually, since the for loop won't hit this new item  itemdefs.item_paralyzer_nano.id = "item_paralyzer_nano"   local oldCanUseAbility = paralyze.canUseAbility;  paralyze.canUseAbility =     function( self, sim, unit )      local ok, reason = oldCanUseAbility( self, sim, unit )       if not ok then        return false, reason      end       if unit:getTraits().pwrCost then        if unit:getPlayerOwner():getCpus() < unit:getTraits().pwrCost then          return false, STRINGS.UI.REASON.NOT_ENOUGH_PWR, STRINGS.UI.FLY_TXT.NOT_ENOUGH_PWR        end      end       return true    end   local oldExecuteAbility = paralyze.executeAbility  paralyze.executeAbility =     function( self, sim, unit, userUnit, target )      oldExecuteAbility( self, sim, unit, userUnit, target )       if unit:getTraits().canTag then        if not target:getTraits().tagged and target:getBrain() then          target:setTagged()        end      end    end   local oldCreateToolTip = paralyze.createToolTip  paralyze.createToolTip =     function( self, sim, abilityOwner )      if abilityOwner:getTraits().pwrCost and abilityOwner:getTraits().canTag then        return abilityutil.formatToolTip(STRINGS.ABILITIES.PARALYZE_NANO, util.sformat(STRINGS.ABILITIES.PARALYZE_NANO_DESC,abilityOwner:getTraits().koTime), simdefs.DEFAULT_COST)       end      return oldCreateToolTip( self, sim, abilityOwner )    end   self.bak =  {    canUseAbility = oldCanUseAbility,    executeAbility = oldExecuteAbility,    createToolTip = oldCreateToolTip,  }   return trueend function mod:unload()   STRINGS.ABILITIES.PARALYZE_NANO = nil  STRINGS.ABILITIES.PARALYZE_NANO_DESC = nil   STRINGS.ITEMS.PARALYZER_NANO = nil  STRINGS.ITEMS.PARALYZER_NANO_TOOLTIP = nil  STRINGS.ITEMS.PARALYZER_NANO_FLAVOR = nil   itemdefs.item_paralyzer_nano = nil   paralyze.canUseAbility = self.bak.canUseAbility  paralyze.executeAbility = self.bak.executeAbility  paralyze.createToolTip = self.bak.createToolTip     self.bak = nil   return trueend return mod;
Link to comment
Share on other sites

There is an issue with this in that if you have two mods modifying the same function, if you disable them in a different order than the order you enable them, you could end up with some weird state... but that's not too important yet. :)

Link to comment
Share on other sites

There is an issue with this in that if you have two mods modifying the same function, if you disable them in a different order than the order you enable them, you could end up with some weird state... but that's not too important yet. :-)

Thanks for the porting, I'll test it right now.

BTW, that disabling/enabling bug is happening because unloading mod just restores the status, not revert the actual difference...

How about replacing that so if user disable a mod, the modmanager restores the vanilla status and then enables all the mods again?

Link to comment
Share on other sites

Fixed everything except one error.

When I try to use the paralyzer, the game freezes and give me this warning:

attempt to index local 'target' (a number value): WIP/main.lua:97 (which is executeAbility)

...And it refuses to tag the target. Any help?

local mod = {}local util = include( "modules/util" )local commondefs = include( "sim/unitdefs/commondefs" )local simdefs = include( "sim/simdefs" )local abilityutil = include( "sim/abilities/abilityutil" )local STRINGS = include( "client/strings" )local itemdefs = include( "sim/unitdefs/itemdefs" )local paralyze = include( "sim/abilities/paralyze" )function mod:load()	STRINGS.ABILITIES.PARALYZE_NANO = "Paralyzer Dose"	STRINGS.ABILITIES.PARALYZE_NANO_DESC = "Inject pinned victims with nanobot. Target will be KO'd for {1} more turns and tagged."		STRINGS.ITEMS.PARALYZER_NANO = "Nanobot Injector"	STRINGS.ITEMS.PARALYZER_NANO_TOOLTIP = "Use on pinned targets. KOs targets for an extra 1 turn and TAGs them."	STRINGS.ITEMS.PARALYZER_NANO_FLAVOR = "Instead of traditional toxin that might leave some trails, this experimental tech constructs nanobot from victim's blood cell."			-- since it's a hash table, the position in the array is completely irrelevant,	-- and we can just add it in like this:	itemdefs.item_paralyzer_nano =	{		type = "simunit",		traits = { selectpriority = 0 },		onWorldTooltip = commondefs.onItemWorldTooltip,		onTooltip = function( tooltip, unit, userUnit ) 			commondefs.onItemTooltip( tooltip, unit, userUnit )			if unit:getTraits().canTag then				tooltip:addAbility( STRINGS.ITEMS.TOOLTIPS.CANTAG, string.format(STRINGS.ITEMS.TOOLTIPS.CANTAG_DESC), "gui/icons/arrow_small.png" )			end		end,		name = STRINGS.ITEMS.PARALYZER_NANO,		desc = STRINGS.ITEMS.PARALYZER_NANO_TOOLTIP,		flavor = STRINGS.ITEMS.PARALYZER_NANO_FLAVOR,		icon = "itemrigs/FloorProp_AmmoClip.png",		--profile_icon = "gui/items/icon-paralyzer.png",		profile_icon = "gui/icons/item_icons/items_icon_small/icon-item_paralyzerdose_small.png",		profile_icon_100 = "gui/icons/item_icons/icon-item_paralyzer_dose.png",		abilities = { "carryable","paralyze" },		traits = { koTime = 1, pwrCost = 1, canTag = true, nopwr_guards = {} },		value = 1000,		floorWeight = 3,	}		-- before returning the tool templates, there is a for loop that does this, 	-- so we must do the same, but manually, since the for loop won't hit this new item	itemdefs.item_paralyzer_nano.id = "item_paralyzer_nano"		local oldCanUseAbility = paralyze.canUseAbility;	paralyze.canUseAbility = 		function( self, sim, unit )			local ok, reason = oldCanUseAbility( self, sim, unit ) 			if not ok then				return false, reason			end						if unit:getTraits().pwrCost then				if unit:getPlayerOwner():getCpus() < unit:getTraits().pwrCost then					return false, STRINGS.UI.REASON.NOT_ENOUGH_PWR, STRINGS.UI.FLY_TXT.NOT_ENOUGH_PWR				end			end				return true		end		local oldExecuteAbility = paralyze.executeAbility	paralyze.executeAbility = 		function( self, sim, unit, userUnit, target )			oldExecuteAbility( self, sim, unit, userUnit, target )						if unit:getTraits().canTag then				if not target:getTraits().tagged and target:getBrain() then					target:setTagged()				end			end		end		local oldCreateToolTip = paralyze.createToolTip	paralyze.createToolTip = 		function( self, sim, abilityOwner )			if abilityOwner:getTraits().pwrCost and abilityOwner:getTraits().canTag then				return abilityutil.formatToolTip(STRINGS.ABILITIES.PARALYZE_NANO, util.sformat(STRINGS.ABILITIES.PARALYZE_NANO_DESC,abilityOwner:getTraits().koTime), simdefs.DEFAULT_COST) 			end			return oldCreateToolTip( self, sim, abilityOwner )		end		self.bak =	{		canUseAbility = oldCanUseAbility,		executeAbility = oldExecuteAbility,		createToolTip = oldCreateToolTip,	}		return trueendfunction mod:unload()	STRINGS.ABILITIES.PARALYZE_NANO = nil	STRINGS.ABILITIES.PARALYZE_NANO_DESC = nil		STRINGS.ITEMS.PARALYZER_NANO = nil	STRINGS.ITEMS.PARALYZER_NANO_TOOLTIP = nil	STRINGS.ITEMS.PARALYZER_NANO_FLAVOR = nil		itemdefs.item_paralyzer_nano = nil		paralyze.canUseAbility = self.bak.canUseAbility	paralyze.executeAbility = self.bak.executeAbility	paralyze.createToolTip = self.bak.createToolTip			self.bak = nil		return trueendreturn mod;
Link to comment
Share on other sites

It looks like you need to calculate what target is...

  oldExecuteAbility( self, sim, unit, userUnit, target )            local target = sim:getUnit(target) -- the new lineif unit:getTraits().canTag then  if not target:getTraits().tagged and target:getBrain() then    target:setTagged()  endend

 

 

You are right about the problem, and having modloader disable all and then reenable isn't a bad idea. If all mods properly restore the previous state, as long as you have a strict FILO queue of the mods, that would work... Whenever you want to disable one it would actually disable them all and then enable them all one by one skipping the one you were trying to disable. :)

 

Since you can change literally anything in Lua you want, to really do it safely a whole modding API would need to be built to modify these tables, hook functions, etc... it limits what you can mod though, so it would be better to try to do it with each mod being responsible for deactivating itself.

 

 

 

Link to comment
Share on other sites

It looks like you need to calculate what target is...

  oldExecuteAbility( self, sim, unit, userUnit, target )            local target = sim:getUnit(target) -- the new lineif unit:getTraits().canTag then  if not target:getTraits().tagged and target:getBrain() then    target:setTagged()  endend

You are right about the problem, and having modloader disable all and then reenable isn't a bad idea. If all mods properly restore the previous state, as long as you have a strict FILO queue of the mods, that would work... Whenever you want to disable one it would actually disable them all and then enable them all one by one skipping the one you were trying to disable. :-)

 

Since you can change literally anything in Lua you want, to really do it safely a whole modding API would need to be built to modify these tables, hook functions, etc... it limits what you can mod though, so it would be better to try to do it with each mod being responsible for deactivating itself.

Thank you, that was a silly mistake... :(

Anyways, everything's fine and working now. Thank you again!

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.