diff --git a/css/rulesAssistant/activationConditions.css b/css/rulesAssistant/activationConditions.css
new file mode 100644
index 0000000000000000000000000000000000000000..62dc010f9d226c7135a41d2db48eda4be41b9ef0
--- /dev/null
+++ b/css/rulesAssistant/activationConditions.css
@@ -0,0 +1,10 @@
+.rule-group {
+    margin: 5px;
+    border: #00cb7a 5px solid;
+    cursor: grab;
+}
+.rule-condition {
+    margin: 5px;
+    border: red 5px solid;
+    cursor: grab;
+}
diff --git a/devTools/types/FC/RA.d.ts b/devTools/types/FC/RA.d.ts
index a771bac04b26912b7ce2018e7672581060b64bab..1816bfdbefc2b23de03c7a762061f5b3d250424a 100644
--- a/devTools/types/FC/RA.d.ts
+++ b/devTools/types/FC/RA.d.ts
@@ -175,7 +175,7 @@ declare namespace FC {
 			scarDesign: string;
 			hornColor: string;
 			labelTagsClear: boolean;
-			choosesOwnClothes: 0|1;
+			choosesOwnClothes: 0 | 1;
 			pronoun: number;
 		}
 
@@ -183,7 +183,36 @@ declare namespace FC {
 			ID: string;
 			name: string;
 			condition: RuleConditions;
+			activation: RulePart;
 			set: RuleSetters;
 		}
+
+		type RulePart = RuleGroup | RuleNegation | RuleCondition;
+
+		interface RuleGroup {
+			type: "and" | "or"
+			parts: RulePart[]
+		}
+
+		interface RuleNegation {
+			type: "negate"
+		}
+
+		type RuleCondition = RuleConstant | RuleCustom | RuleBool;
+
+		interface RuleConstant {
+			type: "constant"
+			value: boolean
+		}
+
+		interface RuleCustom {
+			type: "custom"
+			value: string
+		}
+
+		interface RuleBool {
+			type: "bool"
+			key: string
+		}
 	}
 }
diff --git a/src/js/rulesAssistantActivationCondition.js b/src/js/rulesAssistantActivationCondition.js
new file mode 100644
index 0000000000000000000000000000000000000000..f60f2fd999a80a8e64a043539af0b2837d177638
--- /dev/null
+++ b/src/js/rulesAssistantActivationCondition.js
@@ -0,0 +1,336 @@
+App.RA.Activation = {};
+
+App.RA.Activation = (function() {
+	/**
+	 * @type {HTMLDivElement}
+	 */
+	let editorNode = null;
+	/**
+	 * @type {Map<string, RulePart>}
+	 */
+	let rulePartMap = new Map();
+
+	/**
+	 * @param {FC.RA.Rule} rule
+	 * @returns {HTMLDivElement}
+	 */
+	function editor(rule) {
+		// TODO do this once on story ready
+		boolPopulate();
+		// TODO: remove editorNode when leaving the passage
+		editorNode = document.createElement("div");
+		editorNode.append(buildEditor());
+		return editorNode;
+	}
+
+	/**
+	 * TODO: remove
+	 * @type {FC.RA.RulePart}
+	 */
+	const testRule = {
+		type: "and", parts: [
+			{type: "constant", value: true},
+			{
+				type: "or", parts: [
+					{type: "constant", value: false},
+					{type: "constant", value: true}
+				]
+			},
+			{
+				type: "and", parts: [
+					{type: "bool", key: "isamputee"},
+				]
+			},
+			{type: "bool", key: "isfertile"},
+			{type: "constant", value: true}
+		]
+	};
+
+	/**
+	 * @returns {DocumentFragment}
+	 */
+	function buildEditor() {
+		const f = new DocumentFragment();
+
+		rulePartMap = new Map();
+		f.append(_getRulePart(null, testRule).render());
+
+		return f;
+	}
+
+	function refreshEditor() {
+		if (editorNode !== null) {
+			$(editorNode).empty().append(buildEditor());
+		}
+	}
+
+	let id = 0;
+
+	class RulePart {
+		/**
+		 * @param {RuleGroup} parent
+		 * @param {FC.RA.RulePart} rulePart
+		 */
+		constructor(parent, rulePart) {
+			this.id = id.toString();
+			id++;
+			rulePartMap.set(this.id, this);
+
+			this.parent = parent;
+			this.rulePart = rulePart;
+		}
+
+		/**
+		 * @returns {Node}
+		 */
+		render() {
+			return App.UI.DOM.makeElement("div", "Empty RulePart");
+		}
+
+		/**
+		 * Validate the rule
+		 * @returns {boolean}
+		 */
+		validate() {
+			return true;
+		}
+
+		/**
+		 * Check if this rule applies to the given slave
+		 *
+		 * @param {App.Entity.SlaveState} slave
+		 * @returns {boolean}
+		 */
+		applies(slave) {
+			return false;
+		}
+	}
+
+	class RuleGroup extends RulePart {
+		/**
+		 * @param {RuleGroup} parent
+		 * @param {FC.RA.RuleGroup} ruleGroup
+		 */
+		constructor(parent, ruleGroup) {
+			super(parent, ruleGroup);
+			this.ruleGroup = ruleGroup;
+		}
+
+		render() {
+			const div = document.createElement("div");
+			div.classList.add("rule-group");
+			div.append(this.ruleGroup.type);
+			for (const rulePart of this.ruleGroup.parts) {
+				div.append(_getRulePart(this, rulePart).render());
+			}
+			div.ondragover = ev => {
+				if (canDrop(ev, this)) {
+					// show that it can be dropped
+					ev.preventDefault();
+				}
+				// stop groups further out from capturing the event.
+				ev.stopPropagation();
+			};
+			div.ondrop = ev => {
+				ev.preventDefault();
+				// stop groups further out from capturing the event.
+				ev.stopPropagation();
+				const rulePartID = ev.dataTransfer.getData("text/plain");
+				const rulePart = rulePartMap.get(rulePartID);
+				rulePart.parent.ruleGroup.parts.delete(rulePart.rulePart);
+				this.ruleGroup.parts.push(rulePart.rulePart);
+				refreshEditor();
+			};
+			if (this.parent !== null) {
+				// if null, it's the outermost and that can't be draggable
+				makeDraggable(div, this);
+			}
+			return div;
+		}
+
+
+		validate() {
+			if (this.ruleGroup.parts.length === 0) {
+				return false;
+			}
+			return this.ruleGroup.parts.reduce((c, rulePart) => c && _getRulePart(this, rulePart).validate(), true);
+		}
+
+		applies(slave) {
+			/**
+			 * @type {function(boolean, boolean):boolean}
+			 */
+			const cmp = this.ruleGroup.type === "and"
+				? (a, b) => a && b
+				: (a, b) => a || b;
+
+			let sumValue = true;
+			for (const rulePart of this.ruleGroup.parts) {
+				sumValue = cmp(sumValue, _getRulePart(this, rulePart).applies(slave));
+			}
+			return sumValue;
+		}
+	}
+
+	/**
+	 * @param {DragEvent} event
+	 * @param {RulePart} targetPart
+	 * @returns {boolean}
+	 * @private
+	 */
+	function canDrop(event, targetPart) {
+		const movedPartID = event.dataTransfer.getData("text/plain");
+		const movedPart = rulePartMap.get(movedPartID);
+		// don't allow dragging onto itself
+		if (movedPart === targetPart) {
+			return false;
+		}
+		// don't allow dragging onto children
+		const v = isParent(movedPart.rulePart, targetPart.rulePart);
+		return !v;
+	}
+
+	/**
+	 * @param {FC.RA.RulePart} maybeParent
+	 * @param {FC.RA.RulePart} maybeChild
+	 */
+	function isParent(maybeParent, maybeChild) {
+		switch (maybeParent.type) {
+			case "and":
+			case "or":
+				for (const child of maybeParent.parts) {
+					if (child === maybeChild) {
+						return true;
+					} else if (isParent(child, maybeChild)) {
+						return true;
+					}
+				}
+		}
+		return false;
+	}
+
+
+	class RuleConstant extends RulePart {
+		/**
+		 * @param {RuleGroup} parent
+		 * @param {FC.RA.RuleConstant} ruleConstant
+		 */
+		constructor(parent, ruleConstant) {
+			super(parent, ruleConstant);
+			this.ruleConstant = ruleConstant;
+		}
+
+		render() {
+			const b = App.UI.DOM.makeElement("button", this.ruleConstant.value ? "Always" : "Never", ["rule-condition"]);
+			b.onclick = () => {
+				this.ruleConstant.value = !this.ruleConstant.value;
+				refreshEditor();
+			};
+			makeDraggable(b, this);
+			return b;
+		}
+
+		applies(slave) {
+			return this.ruleConstant.value;
+		}
+	}
+
+	/**
+	 * @param {HTMLElement} node
+	 * @param {RulePart} rulePart
+	 */
+	function makeDraggable(node, rulePart) {
+		node.draggable = true;
+		node.ondragstart = ev => {
+			ev.stopPropagation();
+			ev.dataTransfer.setData("text/plain", rulePart.id);
+		};
+	}
+
+	class RuleBoolCheck extends RulePart {
+		/**
+		 * @param {RuleGroup} parent
+		 * @param {FC.RA.RuleBool} ruleBool
+		 */
+		constructor(parent, ruleBool) {
+			super(parent, ruleBool);
+			this.ruleBool = ruleBool;
+		}
+
+		render() {
+			// make container
+			const span = document.createElement("span");
+			span.classList.add("rule-condition");
+			makeDraggable(span, this);
+			// fill container
+			span.append("Slave");
+			let matchFound = false;
+			let select = document.createElement("select");
+
+			for (const [key, value] of boolCheckMap.entries()) {
+				let el = document.createElement("option");
+				el.value = key;
+				el.textContent = value.name;
+				if (this.ruleBool.key === key) {
+					el.selected = true;
+					matchFound = true;
+				}
+				select.append(el);
+			}
+			if (!matchFound) {
+				select.selectedIndex = -1;
+			}
+			select.onchange = () => {
+				/** @type {HTMLSelectElement} */
+				// @ts-ignore
+				const option = select.children.item(select.selectedIndex);
+				this.ruleBool.key = option.value;
+				refreshEditor();
+			};
+			span.append(select);
+			return span;
+		}
+
+		validate() {
+			return boolCheckMap.has(this.ruleBool.key);
+		}
+
+		applies(slave) {
+			return boolCheckMap.get(this.ruleBool.key).cond(slave);
+		}
+	}
+
+	/**
+	 * @param {RuleGroup} parent
+	 * @param {FC.RA.RulePart} rulePart
+	 * @returns {RulePart}
+	 */
+	function _getRulePart(parent, rulePart) {
+		switch (rulePart.type) {
+			case "and":
+			case "or":
+				return new RuleGroup(parent, rulePart);
+			case "constant":
+				return new RuleConstant(parent, rulePart);
+			case "bool":
+				return new RuleBoolCheck(parent, rulePart);
+		}
+	}
+
+	/**
+	 * TODO: encapsulate for outside access
+	 * TODO: add availability check
+	 *
+	 * @type {Map<string, {name: string, cond: (function(FC.SlaveState): boolean)}>}
+	 */
+	const boolCheckMap = new Map();
+
+	function boolPopulate() {
+		boolCheckMap.set("isfertile", {name: "Is Fertile?", cond: isFertile});
+		boolCheckMap.set("isamputee", {name: "Is Amputee?", cond: isAmputee});
+	}
+
+	return {
+		editor: editor
+	};
+})();
diff --git a/src/js/rulesAssistantOptions.js b/src/js/rulesAssistantOptions.js
index be981014f9eecc1976b3d181b3fb01e5bc378309..51b06b2c675e7769142ab1f69df557be508604b4 100644
--- a/src/js/rulesAssistantOptions.js
+++ b/src/js/rulesAssistantOptions.js
@@ -1267,14 +1267,12 @@ App.RA.options = (function() {
 	}
 
 	// parent section for condition editing
-	class ConditionEditor extends Section {
-		constructor() {
-			super("Activation Condition");
-			this.appendChild(new ConditionFunction());
-			this.appendChild(new AssignmentInclusion());
-			this.appendChild(new FacilityHeadAssignmentInclusion());
-			this.appendChild(new SpecificInclusionExclusion());
-			this.appendChild(new ApplyRuleOnce());
+	class ConditionEditor extends Element {
+		render() {
+			const f = document.createElement("p");
+			App.UI.DOM.appendNewElement("h1", f, "Activation condition");
+			f.appendChild(App.RA.Activation.editor(current_rule));
+			return f;
 		}
 	}