public static WitnessQueueItem GetNew(Deed deed, FactionMember witness, FactionMember actor, bool requiresSight, Dimension dimension) { var item = pool.Get(); if (deed != null) { deed.refCount++; } item.deed = deed; item.witness = witness; item.actor = actor; item.requiresSight = requiresSight; item.dimension = dimension; return(item); }
/// <summary> /// Unregisters a faction member. The faction member calls this in OnDestroy. /// </summary> /// <param name="member">Member.</param> public void UnregisterFactionMember(FactionMember member) { if (member == null) { return; } var faction = GetFaction(member.factionID); if (faction == null) { return; } if (m_members.ContainsKey(faction) && m_members[faction].Contains(member)) { m_members[faction].Remove(member); } }
/// <summary> /// Shares rumors with a member of some faction. Also shares affinity to the player. /// </summary> /// <param name="other">A member of a faction. Recipient who receives this member's rumors.</param> public void ShareRumors(FactionMember other) { if (!FindResources()) { return; } if (factionManager.debug) { Debug.Log("Love/Hate: " + name + ".ShareRumors with:" + other.name, this); } factionManager.ShareAffinity(factionID, other.factionID, FactionDatabase.PlayerFactionID); for (int i = 0; i < longTermMemory.Count; i++) { ShareRumor(longTermMemory[i], other); } ExecuteEvents.Execute <IShareRumorsEventHandler>(gameObject, null, (x, y) => x.OnShareRumors(other)); }
protected virtual void Gossip(FactionMember other) { if (m_self == null || other == null) { return; } UpdateLastGossipTime(other); var otherGossipTrigger = other.GetComponent <AbstractGossipTrigger>(); if (otherGossipTrigger != null) { otherGossipTrigger.UpdateLastGossipTime(m_self); } m_self.ShareRumors(other); other.ShareRumors(m_self); ExecuteEvents.Execute <IGossipEventHandler>(m_self.gameObject, null, (x, y) => x.OnGossip(other)); ExecuteEvents.Execute <IGossipEventHandler>(other.gameObject, null, (x, y) => x.OnGossip(m_self)); }
private bool IsWitnessInRange(FactionMember witness, FactionMember actor, Dimension dimension, float radius) { if (Mathf.Approximately(0, radius)) { return(true); } switch (dimension) { default: case Dimension.Is3D: var distance3D = Vector3.Distance(witness.transform.position, actor.transform.position); return(distance3D <= radius); case Dimension.Is2D: var distance2D = Vector2.Distance(new Vector2(witness.transform.position.x, witness.transform.position.y), new Vector2(actor.transform.position.x, actor.transform.position.y)); return(distance2D <= radius); } }
protected virtual void Affect(FactionMember other) { if (m_self == null || other == null || other.faction == null || other.gameObject == gameObject) { return; } lastTime[other] = GameTime.time; if (debug) { Debug.Log("Love/Hate: Applying aura effect " + name + " to " + other.name, this); } var alignment = Traits.Alignment(m_self.traits, other.faction.traits); var pleasureChange = alignment * impact; var arousalChange = Mathf.Max(-alignment * impact, -other.pad.arousal); var dominanceChange = alignment * (aggression / 100) * impact; other.pad.Modify(pleasureChange, pleasureChange, arousalChange, dominanceChange); ExecuteEvents.Execute <IAuraEventHandler>(gameObject, null, (x, y) => x.OnAura(other)); ExecuteEvents.Execute <IEnterAuraEventHandler>(other.gameObject, null, (x, y) => x.OnEnterAura(this)); }
public virtual bool CanSee(FactionMember actor, Dimension dimension) { if (actor == null || factionMember == null) { return(false); } this.dimension = dimension; hasCheckedEver = true; lastPointChecked = actor.transform.position; lastPointGizmoName = string.Empty; var seen = IsInFOVs(actor.transform, dimension) && IsInLineOfSight(actor.transform, dimension); if (seen && factionMember.factionDatabase != null) { var faction = factionMember.factionDatabase.GetFaction(actor.factionID); if (faction != null && faction.color < Faction.GizmoIconNames.Length) { lastPointGizmoName = Faction.GizmoIconNames[faction.color]; } } return(seen); }
private void Start() { if (debuggerCanvas == null) { enabled = false; return; } if (debuggerCanvas.onlyInDebugBuild && !Debug.isDebugBuild) { Destroy(this); return; } if (!debuggerCanvas.gameObject.activeInHierarchy) { debuggerCanvas = Instantiate(debuggerCanvas) as FactionMemberDebuggerCanvas; debuggerCanvas.transform.SetParent(transform); debuggerCanvas.transform.localPosition = new Vector3(0, verticalOffset, 0); } debuggerCanvas.gameObject.SetActive(visible); member = GetComponentInParent <FactionMember>() ?? GetComponentInChildren <FactionMember>(); UpdatePadText(); }
/// <summary> /// Reports that the faction member committed a deed. /// </summary> /// <param name="tag">Tag of the deed in the deed template library.</param> /// <param name="target">Target of the deed.</param> public virtual void ReportDeed(string tag, FactionMember target) { if (target == null) { Debug.LogWarning("Love/Hate: ReportDeed(" + tag + ") target is null", this); return; } if (deedTemplateLibrary == null) { Debug.LogWarning("Love/Hate: ReportDeed(" + tag + ") no Deed Template Library is assigned", this); return; } DeedTemplate deedTemplate; if (FindDeedTemplate(tag, out deedTemplate)) { var actorPowerLevel = (m_member == null) ? 0 : m_member.GetPowerLevel(); var deed = Deed.GetNew(deedTemplate.tag, m_member.factionID, target.factionID, deedTemplate.impact, deedTemplate.aggression, actorPowerLevel, deedTemplate.traits); m_member.factionManager.CommitDeed(m_member, deed, deedTemplate.requiresSight, dimension, deedTemplate.radius); Deed.Release(deed); } }
protected override void Greet(FactionMember other) { if (m_self == null || other == null || other == m_self || m_animator == null) { return; } base.Greet(other); var affinity = m_self.GetAffinity(other); for (int g = 0; g < greetings.Length; g++) { var greeting = greetings[g]; var isAppropriateGreeting = (greeting.min <= affinity && affinity <= greeting.max) && ((greeting.temperament & m_self.pad.GetTemperament()) != 0); if (isAppropriateGreeting) { if (!string.IsNullOrEmpty(greeting.triggerParameter)) { m_animator.SetTrigger(greeting.triggerParameter); } break; } } }
public void OnShareRumors(FactionMember other) { onShareRumors.Invoke(other); }
public void OnGreet(FactionMember other) { onGreet.Invoke(other); }
public void OnGossip(FactionMember other) { onGossip.Invoke(other); }
protected virtual void Awake() { m_self = GetComponentInChildren <FactionMember>() ?? GetComponentInParent <FactionMember>(); m_animator = GetComponentInChildren <Animator>() ?? GetComponentInParent <Animator>(); }
/// <summary> /// Gets the affinity to a subject, either personal affinity or using /// parent faction affinities. /// </summary> /// <returns>The affinity.</returns> /// <param name="subject">Subject.</param> public float GetAffinity(FactionMember subject) { return(GetAffinity(subject.factionID)); }
/// <summary> /// Commits the deed. This version has no distance restrictions. /// </summary> /// <param name="actor">Actor.</param> /// <param name="deed">Deed.</param> /// <param name="requiresSight">If set to <c>true</c> requires sight.</param> public void CommitDeed(FactionMember actor, Deed deed, bool requiresSight) { CommitDeed(actor, deed, requiresSight, Dimension.Is3D, 0); }
/// <summary> /// Returns the trust [-100,+100] that the faction member has in rumors reported /// by a source. /// </summary> /// <param name="source">Source.</param> /// <returns>The faction member's affinity to the source, or 100 if the source is self.</returns> public float DefaultGetTrustInSource(FactionMember source) { return((source == this) ? 100f : GetAffinity(source.factionID)); }
/// <summary> /// Reports that the faction member committed a deed. /// </summary> /// <param name="tag">Tag of the deed in the deed template library.</param> /// <param name="target">Target of the deed.</param> public virtual void ReportDeed(string tag, FactionMember target) { ReportDeedByActor(m_member, tag, target); }
protected virtual void Awake() { m_member = GetComponent <FactionMember>(); }
public void Awake() { m_member = GetComponent <FactionMember>(); }
private void Awake() { m_member = GetComponent <FactionMember>(); }
public void UpdateLastGossipTime(FactionMember other) { lastGossip[other] = GameTime.time; }
/// <summary> /// Evaluates a rumor and updates the faction's state. /// </summary> /// <returns>If this is a new type of deed, returns a new rumor if the impact is /// big enough to remember (otherwise `null`). If it's a repeat deed, returns /// the existing rumor.</returns> /// <param name="rumor">Rumor.</param> /// <param name="source">Source.</param> public Rumor DefaultEvaluateRumor(Rumor rumor, FactionMember source) { if ((rumor == null) || (source == null) || KnowsAboutDeed(rumor.deedGuid) || !FindResources()) { return(null); } // This is the big equation! // confidenceNorm[0,1]: The degree we trust this rumor is based on our affinity for its source: var trustInSource = GetTrustInSource(source); //[-100,+100] var trustInSourceNorm = Mathf.Clamp(trustInSource / 100, 0, 1); //[0,1] var confidence = rumor.confidence * trustInSourceNorm; //[0,+100] var confidenceNorm = confidence / 100; //[0,1] // affinityToTargetNorm[-1,+1]: How much we like the target of the rumor's deed: var affinityToTarget = GetAffinity(rumor.targetFactionID); //[-100,+100] var affinityToTargetNorm = affinityToTarget / 100; //[-1,+1] // changeInAffinityToActorNorm[-1,+1]: How much the deed changes our opinion of the actor who did it: // The base value is determined by the deed's impact, our confidence in the source, and our // affinity to the target: var impactNorm = rumor.impact / 100; //[-1,+1] var changeInAffinityToActorNorm = confidenceNorm * impactNorm * affinityToTargetNorm; //[-1,+1] // traitImpactNorm[-1,+1]: Modifies the opinion by how well the deed's traits align with our own: var traitAlignment = GetTraitAlignment(rumor.traits); //[-1,+1] var traitImpactNorm = Mathf.Approximately(0, traitAlignmentImportance) ? 0 : (traitAlignment * Mathf.Abs(changeInAffinityToActorNorm)) / (traitAlignmentImportance / 100); //[-1,+1] // arousalImpactNorm[-1,+1]: Modifies the opinion by our arousal level: var arousalImpactNorm = Mathf.Approximately(0, arousalImportance) ? 0 : changeInAffinityToActorNorm * (pad.arousal / 100) * (arousalImportance / 100); //[-0.5,+0.5] // Final change in affinity to actor: var changeInAffinityToActor = 100 * Mathf.Clamp(changeInAffinityToActorNorm + traitImpactNorm + arousalImpactNorm, -1, 1); //[-100,+100] // If it's a repeat, reduce the impact and update the old rumor: Rumor oldRumor; var isRepeat = FindOldRumor(rumor, out oldRumor); if (isRepeat) { oldRumor.count++; changeInAffinityToActor *= acclimatizationCurve.Evaluate(oldRumor.count); } // Values that affect PAD: var changeMagnitude = Mathf.Abs(changeInAffinityToActor); var myPowerLevel = GetSelfPerceivedPowerLevel(); var powerModifier = Mathf.Clamp(powerDifferenceCurve.Evaluate(myPowerLevel - rumor.actorPowerLevel), -1, 1); //[-1,+1] // Compute PAD change: var pleasure = changeInAffinityToActor; pleasure += pleasure * traitAlignment; // Nudge pleasure a little more based on trait alignment. var arousal = changeMagnitude * (arousalImportance / 100); var dominance = -rumor.aggression * changeMagnitude / 100; dominance += powerModifier * Mathf.Abs(dominance); var happiness = pleasure; // Compute impression on personality: var impressionFactor = 0f; var trustInActorNorm = 0f; var impressionable = !Mathf.Approximately(0, impressionability); if (impressionable) { trustInActorNorm = GetAffinity(rumor.actorFactionID) / 100; //[-1,+1] } impressionable = impressionable && (trustInActorNorm > 0); if (impressionable) { impressionFactor = (impressionability / 100) * trustInActorNorm; //[0,+1] ModifyPersonality(rumor.traits, impressionFactor); } if (debugEvalFunc) { var debugInfo = "Love/Hate: " + name + ".EvaluateRumor actor:" + factionManager.GetFaction(rumor.actorFactionID).name + " tag:" + rumor.tag + " target:" + factionManager.GetFaction(rumor.targetFactionID).name + "impact:" + rumor.impact + " aggression:" + rumor.aggression + " source:" + source.name + "\n confidence in source: " + confidence + "%" + "\n affinity to target: " + affinityToTarget + "\n change in affinity to actor based on impact, target & confidence: " + changeInAffinityToActorNorm * 100 + "\n + trait alignment modifier: " + traitImpactNorm * 100 + " (based on " + traitAlignment * 100 + "% alignment)" + "\n + arousal modifier: " + arousalImpactNorm * 100 + " (based on " + pad.arousal + " arousal)" + "\n <b>= final change in affinity to actor: " + changeInAffinityToActor + "</b>\n power difference: " + myPowerLevel + "(me) - " + rumor.actorPowerLevel + "(actor) = " + (myPowerLevel - rumor.actorPowerLevel) + " (adjust dominance change up by " + powerModifier * 100 + "%)" + "\n <b>P,A,D change: " + pleasure + ", " + arousal + ", " + dominance + "</b>"; if (impressionable) { debugInfo += "\n <b>align personality to match deed by: " + impressionFactor * 100 + "%</b>"; } Debug.Log(debugInfo, this); } // Apply PAD change: ModifyPAD(happiness, pleasure, arousal, dominance); // Update affinity: var oldAffinityToActor = GetAffinity(rumor.actorFactionID); var newAffinityToActor = Mathf.Clamp(oldAffinityToActor + pleasure, -100, 100); SetPersonalAffinity(rumor.actorFactionID, newAffinityToActor); // If the opinion is over the threshold we care about, remember the rumor: Rumor result = null; if (isRepeat) { if (factionManager.debug || debugEvalFunc) { Debug.Log(string.Format("Love/Hate: {0}.UpdateExistingRumor actor:{1} target:{2} affinityChange:{3:N2}", new object[] { name, factionManager.GetFaction(rumor.actorFactionID).name, factionManager.GetFaction(rumor.targetFactionID).name, pleasure }), this); } oldRumor.confidence = Mathf.Max(oldRumor.confidence, confidence); result = oldRumor; } else { var newRumor = Rumor.GetNew(rumor); newRumor.confidence = confidence; newRumor.pleasure = pleasure; newRumor.arousal = arousal; newRumor.dominance = dominance; newRumor.memorable = (changeMagnitude > deedImpactThreshold); if (!newRumor.memorable) { ModifyPAD(0, -pleasure, -arousal, -dominance); } result = newRumor; if (newRumor.memorable) { if (factionManager.debug || debugEvalFunc) { Debug.Log(string.Format("Love/Hate: {0}.RememberRumor actor:{1} target:{2} affinityChange:{3:N2}", new object[] { name, factionManager.GetFaction(rumor.actorFactionID).name, factionManager.GetFaction(rumor.targetFactionID).name, pleasure }), this); } AddRumorToMemory(newRumor); } else { if (factionManager.debug || debugEvalFunc) { Debug.Log(string.Format("Love/Hate: {0}.Rumor isn't memorable actor:{1} target:{2} affinityChange:{3:N2}", new object[] { name, factionManager.GetFaction(rumor.actorFactionID).name, factionManager.GetFaction(rumor.targetFactionID).name, pleasure }), this); } } } if (result != null) { result.shortTermExpiration = GameTime.time + (changeMagnitude * shortTermMemoryDuration); result.longTermExpiration = GameTime.time + (changeMagnitude * longTermMemoryDuration); } return(result); }
public override void Awake() { base.Awake(); m_member = GetComponent <FactionMember>(); }