Page 1 of 1

Faction Members belonging to multiple factions

Posted: Wed Dec 14, 2022 2:45 pm
by NotVeryProfessional
I'm using Love/Hate for a new project and wonder what's the correct approach is for characters belonging to multiple factions.

Specifically, in my fantasy setting I have racial relations (humans, dwarves, etc.) and social levels (noble, peasant, priest, etc.) and religious affiliation and a few more.

Most of these can be mixed and matched. There can be human, dwarf, etc. peasants or priests. Human peasants can belong to one of several religions, etc.


Do I need to define all possible combinations as seperate factions (e.g. human/noble/religionA, human/noble/religionB, human/peasant/religionA, etc. etc.) or can I attach multiple FactionMember components, or is there another solution I'm missing or am I doing this entirely the wrong way?

Re: Faction Members belonging to multiple factions

Posted: Wed Dec 14, 2022 4:00 pm
by Tony Li
Hi,

Define the races, social levels, and religions as separate factions:

loveHate1.png
loveHate1.png (27.75 KiB) Viewed 7802 times

Then create a faction for each character, and assign race, social level, and religion factions as its parents. For example, the character Elvish Partially below is a half-elf priest sun-worshipper:

loveHate2.png
loveHate2.png (34.28 KiB) Viewed 7802 times

Add only one FactionMember component to the NPC's GameObject, and assign the character faction.

Re: Faction Members belonging to multiple factions

Posted: Thu Dec 15, 2022 3:48 am
by NotVeryProfessional
Got it. So the right answer is to use factions and inheritance. Even if it means having lots of factions.

Re: Faction Members belonging to multiple factions

Posted: Thu Dec 15, 2022 5:16 am
by Tony Li
Yes. You can also create new factions at runtime if you need to.

Re: Faction Members belonging to multiple factions

Posted: Thu Dec 15, 2022 8:59 am
by NotVeryProfessional
Tony Li wrote: Thu Dec 15, 2022 5:16 am Yes. You can also create new factions at runtime if you need to.
That, actually, is a great piece of info.

It means I can create a very simple script, assign it the multiple factions I need (race, religion, class, etc.) and it will create a new faction for them and assign it to the character. That, I think, is the best solution for my use case.

Thanks, your support is simply amazing. I own Dialogue System and Love/Hate and have never regretted buying them even for a second.

Re: Faction Members belonging to multiple factions

Posted: Thu Dec 15, 2022 6:26 pm
by Tony Li
Thanks! Glad to help. If I recall correctly, you leverage Playmaker a lot. Love/Hate’s Playmaker has everything you need to create factions at runtime. (Or you can use the C# methods if you prefer.)

Re: Faction Members belonging to multiple factions

Posted: Fri Dec 16, 2022 7:03 am
by NotVeryProfessional
Here's my solution, for others who find this thread later. Note that I use Odin Inspector, if you don't then you'll need to use a custom editor script like LoveHate itself does to get a nice dropdown list.

(@Tony: No, you mixed that. I don't use Playmaker at all)

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Sirenix.OdinInspector;
using PixelCrushers.LoveHate;


public class DynamicFactions : MonoBehaviour {

	[SerializeField] FactionManager factionManager;
	[SerializeField] FactionDatabase factionDatabase;

	private ValueDropdownList<int> GetAllFactions() {
		if (factionDatabase == null) SetReferences();
		ValueDropdownList<int> allFactions = new ValueDropdownList<int>();
		foreach (Faction f in factionDatabase.factions) {
			ValueDropdownItem<int> item = new ValueDropdownItem<int>(f.name, f.id);
			allFactions.Add(item);
		}
		return allFactions;
	}

	[ValueDropdown("GetAllFactions")]
	[SerializeField] List<int> myFactions;
	[ShowInInspector, ReadOnly] string myFactionName { get {
		string _factionName = "combined";
		foreach (int myFactionID in myFactions) {
			Faction myFaction = factionDatabase.GetFaction(myFactionID);
			_factionName += " - " + myFaction.name;
		}
		return _factionName;
	}}
	
	
	void OnReset() {
		SetReferences();
	}
	
	void Start() {
		UpdateFactions();
	}

	void SetReferences() {
		if (factionManager == null) {
			factionManager = FindObjectOfType<FactionManager>();
		}
		if (factionDatabase == null && factionManager != null) {
			factionDatabase = factionManager.factionDatabase;
		}		
	}
	
	[Button]
	void UpdateFactions() {
		if (myFactions.Count <= 1) {
			Debug.LogError("Must have at least 2 factions to create a combined faction.");
			return;
		}
		foreach (Faction faction in factionDatabase.factions) {
			if (myFactionName == faction.name) return;
		}
		
		// faction name doesn't exist (yet) - create
		int newFactionID = factionDatabase.CreateNewFaction(myFactionName, "(automatically created combined faction)");
		
		foreach (int parentFactionID in myFactions) {
			factionDatabase.AddFactionParent(newFactionID, parentFactionID);
		}
		factionDatabase.InheritTraitsFromParents(newFactionID);
	}
}

This will create new factions either if you press the button (doesn't have to be in play mode) or in Start(), so that it's always ensured that the faction exists at runtime.

This doesn't (yet) assign the faction to a faction member component, that'd be the next step.