Skip to content

Instantly share code, notes, and snippets.

@Novaras
Last active January 20, 2022 03:58
Show Gist options
  • Save Novaras/16a69813172caa9639fea441511effa7 to your computer and use it in GitHub Desktop.
Save Novaras/16a69813172caa9639fea441511effa7 to your computer and use it in GitHub Desktop.

here's an example mission script showing how modkit allows you to write mission scripts more expressively

I made this from a desire to write linear things like this:

Given a rule A
If A is finished, start rule B
If B is finished, with the result of B, start C or D
..etc.

but also complex branching like this:

Given some rules A, B, C
If A and (B or C) are finished, start rule D
If (A and B) or C are finished, start rule E

(in both cases clearing the other listener)

modkit can write campaign scripts which implement the above almost in plain english:

-- my_custom_mission.lua

-- import modkit
if (modkit == nil) then dofilepath("data:scripts/modkit.lua"); end

-- alias
rules = modkit.campaign.rules;

-- set up some dummy rules
-- notice A is deterministic, but B and C decay randomly (although C is less likely than B)
-- this means you can first see 'first listener' fire first, or sometimes 'second listener' is first!
-- this is a contrived example of how this syntax can implement complex real campaign situations

local rule_a = rules:make(
	"A",
	function (self)
		local gametime = Universe_GameTime();
		print("hello from rule fn A! (" .. gametime .. ")");

		if (gametime > 10) then
			return "done bruh";
		end
	end,
	1
);

local rule_b = rules:make(
	"B",
	function (self)
		local gametime = Universe_GameTime();
		print("hello from rule fn B! (" .. gametime .. ")");

		if (random() < 0.5) then
			-- we dont branch on rule returns in this example, but we could use these return values
			-- to branch our behavior to next fire rule x OR y, etc.
			return "B fin";
		end
	end,
	1
);

local rule_c = rules:make(
	"C",
	function (self)
		local gametime = Universe_GameTime();
		print("hello from rule fn C! (" .. gametime .. ")");

		if (random() < 0.1) then
			return "C finish";
		end
	end,
	1 -- all the rules have the same interval for the decay chance to be fair for B and C
);

-- rules can of course be fired at leisure
rules:begin(rule_a);
rules:begin(rule_b);
rules:begin(rule_c);

-- here's the nice part:
rules:on("A and (B or C)", function (rules)
	print("first listener!");
end);

rules:on("(A and B) or C", function (rules)
	print("second listener!");
end);

-- if we had a rule called 'my_rule' and another called 'rule2', you can use those names just fine:
-- rules:on("my_rule and rule2", function()...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment