Faction Members belonging to multiple factions

Announcements, support questions, and discussion for Love/Hate.
Post Reply
NotVeryProfessional
Posts: 148
Joined: Mon Nov 23, 2020 6:35 am

Faction Members belonging to multiple factions

Post 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?
User avatar
Tony Li
Posts: 22000
Joined: Thu Jul 18, 2013 1:27 pm

Re: Faction Members belonging to multiple factions

Post by Tony Li »

Hi,

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

loveHate1.png
loveHate1.png (27.75 KiB) Viewed 7772 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 7772 times

Add only one FactionMember component to the NPC's GameObject, and assign the character faction.
NotVeryProfessional
Posts: 148
Joined: Mon Nov 23, 2020 6:35 am

Re: Faction Members belonging to multiple factions

Post by NotVeryProfessional »

Got it. So the right answer is to use factions and inheritance. Even if it means having lots of factions.
User avatar
Tony Li
Posts: 22000
Joined: Thu Jul 18, 2013 1:27 pm

Re: Faction Members belonging to multiple factions

Post by Tony Li »

Yes. You can also create new factions at runtime if you need to.
NotVeryProfessional
Posts: 148
Joined: Mon Nov 23, 2020 6:35 am

Re: Faction Members belonging to multiple factions

Post 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.
User avatar
Tony Li
Posts: 22000
Joined: Thu Jul 18, 2013 1:27 pm

Re: Faction Members belonging to multiple factions

Post 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.)
NotVeryProfessional
Posts: 148
Joined: Mon Nov 23, 2020 6:35 am

Re: Faction Members belonging to multiple factions

Post 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.
Post Reply