diff --git a/src/js/rulesAssistantOptions.tw b/src/js/rulesAssistantOptions.tw
index 1e2dccea9cdcf79de5b8894d3be263ec9fcb8f6c..b31451918820f399aa6922707e80562fd1137a38 100644
--- a/src/js/rulesAssistantOptions.tw
+++ b/src/js/rulesAssistantOptions.tw
@@ -34,7 +34,7 @@ window.rulesAssistantOptions = (function() {
 	// create a new rule and reload
 	function newRule(root) {
 		const id = generateNewID()
-		v.defaultRules.push({
+		V.defaultRules.push({
 			ID: id,
 			name: `Rule ${id}`,
 			condition: {
@@ -215,7 +215,7 @@ window.rulesAssistantOptions = (function() {
 	// it can be "bound" to a variable by setting its "onchange" method
 	class List extends Element {
 		constructor(prefix, textinput=false) {
-			super(prefix, textarea)
+			super(prefix, textinput)
 			this.selectedItem = null
 			this.value = this.element.querySelector(".rajs-value")
 		}
@@ -274,19 +274,19 @@ window.rulesAssistantOptions = (function() {
 			return n === NaN? 0: n
 		},
 		boobs(string) {
-			return Math.clamp(parse.integer(n), 0, 48000)
+			return Math.clamp(parse.integer(string), 0, 48000)
 		},
 		butt(string) {
-			return Math.clamp(parse.integer(n), 0, 10)
+			return Math.clamp(parse.integer(string), 0, 10)
 		},
 		lips(string) {
-			return Math.clamp(parse.integer(n), 0, 100)
+			return Math.clamp(parse.integer(string), 0, 100)
 		},
 		dick(string) {
-			return Math.clamp(parse.integer(n), 0, 10)
+			return Math.clamp(parse.integer(string), 0, 10)
 		},
 		balls(string) {
-			return Math.clamp(parse.integer(n), 0, 10)
+			return Math.clamp(parse.integer(string), 0, 10)
 		},
 	}
 
@@ -364,6 +364,56 @@ window.rulesAssistantOptions = (function() {
 		}
 	}
 
+	class ButtonList extends Element {
+		render(label) {
+			const elem = document.createElement("div")
+			const labelel = document.createElement("span")
+			labelel.innerhTML = label += ":"
+			elem.appendChild(labelel)
+			return elem
+		}
+
+		getSelection() {
+			return (this.children
+				.filter(child => child.selected)
+				.map(child => child.setvalue)
+			)
+		}
+
+		onchange() { return }
+	}
+
+	class ButtonItem extends Element {
+		constructor(label, setvalue, selected=false) {
+			super(label, selected)
+			this.selected = selected
+			this.setvalue = setvalue ? setvalue : label
+		}
+
+		render(label, selected) {
+			const container = document.createElement("div")
+			container.classList.add("rajs-listitem")
+			
+			const labelel = document.createElement("span")
+			labelel.innerHTML = label
+
+			const button = document.createElement("input")
+			button.setAttribute("type", "checkbox")
+			button.checked = selected
+			button.onchange = () => this.onchange(button.checked)
+
+			container.appendChild(labelel)
+			container.appendChild(button)
+
+			return container
+		}
+
+		onchange(value) {
+			this.selected = value
+			parent.onchange(this)
+		}
+	}
+
 	// rule import field
 	class NewRuleField extends Element {
 		constructor(root) {
@@ -486,13 +536,20 @@ window.rulesAssistantOptions = (function() {
 		}
 	}
 
+	class ExportField extends Element {
+		render(all=false) {
+			const element = document.createElement("textarea")
+			element.value = all ? JSON.stringify(V.currentRule) : map(i => JSON.stringify(i), V.defaultRules).join("\n\n")
+			return element
+		}
+	}
+
 	// parent section for condition editing
 	class ConditionEditor extends Element {
 		constructor() {
 			super()
 			this.appendChild(new ConditionFunction())
 			this.appendChild(new AssignmentInclusion())
-			this.appendChild(new AssignmentExclusion())
 			this.appendChild(new FacilityInclusion())
 			this.appendChild(new SpecialExclusion())
 			this.appendChild(new SpecificInclusionExclusion())
@@ -504,6 +561,228 @@ window.rulesAssistantOptions = (function() {
 		}
 	}
 
+	class ConditionFunction extends Element {
+		constructor() {
+			super()
+			this.fnlist = new List("Activation function:")
+			this.fneditor = null
+			["Never", "Always", "Custom"].forEach(i => this.fnlist.appendChild(i))
+			["Devotion", "Trust", "Health", "Sex drive", "Weight", "Age", "Body Age", "Visible Age", "Muscles", "Lactation", "Pregnancy", "Pregnancy Multiples", "Belly Implant", "Belly Size"].forEach(i => this.fnlist.appendChild(i, this.getAttribute(i)))
+			this.fnlist.onchange = () => this.fnchanged
+			
+			switch(V.currentRule.condition.function) {
+				case "Never":
+				case "Always":
+					break
+				case "Custom":
+					this.appendChild(new CustomEditor(V.currentRule.condition.data))
+					break
+				default:
+					this.appendChild(new RangeEditor(V.currentRule.condition.function, V.currentRule.condition.data))
+					break
+			}
+		}
+
+		render() {
+			return document.createElement("div")
+		}
+
+		getAttribute(what) {
+			return {
+				"Devotion": "devotion",
+				"Trust": "trust",
+				"Health": "health",
+				"Sex drive": "energy",
+				"weight": "weight",
+				"Age": "actualAge",
+				"Body Age": "physicalAge",
+				"Visible Age": "visualAge",
+				"Muscles": "muscles",
+				"Lactation": "lactation",
+				"Pregnancy": "preg",
+				"Pregnancy Multiples": "pregType",
+				"Belly implant": "bellyImplant",
+				"Belly Size": "belly",
+			}[what]
+		}
+
+		fnchanged(value) {
+			if (this.fneditor !== null) {
+				this.fneditor.element.remove()
+				this.fneditor = null
+			}
+			switch(value) {
+				case "Never":
+					V.currentRule.condition.function = false
+					V.currentRule.condition.data = {}
+					break
+				case "Always":
+					V.currentRule.condition.function = true
+					V.currentRule.condition.data = {}
+					break
+				case "Custom":
+					V.currentRule.condition.function = "custom"
+					V.currentRule.condition.data = {}
+					this.appendChild(new CustomEditor(V.currentRule.condition.data))
+					break
+				default:
+					V.currentRule.condition.function = "between"
+					V.currentRule.condition.data = { attribute: value, value: [null, null] }
+					this.appendChild(new RangeEditor(V.currentRule.condition.data))
+					break
+			}
+		}
+	}
+
+	class CustomEditor extends Element {
+		constructor(data) {
+			if (data.length === 0) data = "function(slave) { return slave.slaveName === 'Fancy Name'; }"
+			super(data)
+			this.elem.onfocusout = () => V.currentRule.data = this.elem.value
+		}
+
+		render(data) {
+			const elem = document.createElement("textarea")
+			elem.setAttribute(value, data)
+			return elem
+		}
+	}
+
+	class RangeEditor extends Element {
+		render(data) {
+			const elem = document.createElement("div")
+
+			const min = document.createElement("input")
+			min.setAttribute("type", "text")
+			min.value = data.between[0]
+			min.onkeypress = e => onreturn(e, () => this.setmin(min.value))
+			min.onfocusout = e => this.setmin(min.value)
+			elem.appendChild(min)
+
+			const max = document.createElement("input")
+			max.setAttribute("type", "text")
+			max.value = data.between[0]
+			max.onkeypress = e => onreturn(e, () => this.setmax(max.value))
+			max.onfocusout = e => this.setmax(max.value)
+			elem.appendChild(max)
+
+			const infobar = document.createElement("div")
+			infobar.innerHTML = this.info(data.attribute)
+			elem.appendChild(infobar)
+
+			return elem
+		}
+
+		parse(value) {
+			value = value.strip()
+			if (value === "null") value = null
+			else {
+				value = parseInt(value)
+				if (value === NaN) value = null
+			}
+			return value
+		}
+
+		setmin(value) {
+			V.currentRule.data.between[0] = this.parse(value)
+		}
+
+		setmax(value) {
+			V.currentRule.data.between[1] = this.parse(value)
+		}
+
+		info(attribute) {
+			return "TODO"
+		}
+	}
+
+	class AssignmentInclusion extends ButtonList() {
+		constructor() {
+			super("Apply to assignments")
+			["Rest", "Fucktoy", "Subordinate Slave", "House Servant", "Confined", "Whore", "Public Servant", "Classes", "Milked", "Gloryhole"].forEach(
+				i => this.appendChild(new ButtonItem(i, this.getAttribute(i), V.currentRule.condition.assignment.includes(i))))
+		}
+
+		onchange() {
+			V.currentRule.condition.assignment = this.getSelection()
+		}
+
+		getAttribute(what) {
+			return {
+				"Rest": "rest",
+				"Fucktoy": "please you",
+				"Subordinate Slave": "be a subordinate slave",
+				"House Servant": "be a servant",
+				"Confined": "stay confined",
+				"Whore": "whore",
+				"Public Servant": "serve the public",
+				"Classes": "take classes",
+				"Milked": "get milked",
+				"Gloryhole": "work a glory hole",
+			}[what]
+		}
+	}
+
+	class FacilityInclusion extends ButtonList() {
+		constructor() {
+			super("Apply to assignments")
+			const facilities = []
+			if (V.HGSuite > 0) facilities.push("Head Girl Suite")
+			if (V.brothel > 0) facilities.push("Brothel")
+			if (V.club > 0) facilities.push("Club")
+			if (V.arcade > 0) facilities.push("Arcade")
+			if (V.dairy > 0) facilities.push("Dairy")
+			if (V.servantQuarters > 0) facilities.push("Servant Quarters")
+			if (V.masterSuite > 0) facilities.push("Master Suite")
+			if (V.schoolroom > 0) facilities.push("Schoolroom")
+			if (V.spa > 0) facilities.push("Spa")
+			if (V.clinic > 0) facilities.push("Clinic")
+			if (V.cellblock > 0) facilities.push("Cellblock")
+			facilities.forEach(
+				i => this.appendChild(new ButtonItem(i, this.getAttribute(i), V.currentRule.condition.facility.includes(i))))
+		}
+
+		onchange(value) {
+			V.currentRule.condition.facility = this.getSelection()
+		}
+
+		getAttribute(what) {
+			return {
+				"Head Girl Suite": "live with your Head Girl",
+				"Brothel": "work in the brothel",
+				"Club": "serve in the club",
+				"Arcade": "be confined in the arcade",
+				"Dairy": "work in the dairy",
+				"Servant Quarters": "work as a servant",
+				"Master Suite": "serve in the master suite",
+				"Schoolroom": "learn in the schoolroom",
+				"Spa": "rest in the spa",
+				"Clinic": "get treatment in the clinic",
+				"Cellblock": "be confined in the cellblock",
+			}[what]
+		}
+	}
+
+	class SpecialExclusion extends List {
+		constructor() {
+			super("Exclude special slaves:")
+			const yes = new ListItem("Yes", "Yes", true)
+			const no = new ListItem("No", "No", false)
+			this.appendChild(yes)
+			this.appendChild(no)
+			if (V.currentRule.excludeSpecialSlaves) yes.select()
+			this.onchange = (label, value) => V.currentRule.excludeSpecialSlaves = value
+		}
+	}
+
+	class SpecificInclusionExclusion extends Options {
+		constructor() {
+			super()
+			this.appendChild(new OptionsItem("Limit to specific slaves", () => Engine.display("Rules Slave Select")))
+			this.appendChild(new OptionsItem("Exclude specific slaveS", () => Engine.display("Rules Slave Exclude")))
+		}
+	}
+
 	// parent section for effect editing
 	class EffectEditor extends Element {
 		constructor() {