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));
 }
Exemple #4
0
        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);
            }
        }
Exemple #6
0
        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));
        }
Exemple #7
0
        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);
            }
        }
Exemple #10
0
        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));
 }
Exemple #18
0
 /// <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);
 }
Exemple #19
0
 protected virtual void Awake()
 {
     m_member = GetComponent <FactionMember>();
 }
Exemple #20
0
 public void Awake()
 {
     m_member = GetComponent <FactionMember>();
 }
Exemple #21
0
 private void Awake()
 {
     m_member = GetComponent <FactionMember>();
 }
Exemple #22
0
 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);
        }
Exemple #24
0
 public override void Awake()
 {
     base.Awake();
     m_member = GetComponent <FactionMember>();
 }