Temporary Modifiers
Modifiers are temporary effects that alter how relationship changes are processed. They can buff, debuff, or completely override changes for a duration.
Modifier Types
+10Adds/subtracts fixed amount from every change
+25%Multiplies the change by a percentage
=50Replaces all changes with a fixed value
Stacking Order
Modifiers are processed in order: Override → Percentage → Flat. An Override modifier stops further processing.
// Add a 2-hour reputation boost
manager.AddModifier(new RelationshipModifier {
ModifierId = "guild_bonus",
Source = "Guild Membership",
Type = ModifierType.Percentage,
Value = 0.25f, // +25% to all gains
Duration = 7200f, // 2 hours
AffectsGainOnly = true
});
// Add a reputation penalty (only affects losses)
manager.AddModifier(new RelationshipModifier {
ModifierId = "curse_penalty",
Source = "Witch's Curse",
Type = ModifierType.Flat,
Value = -5f, // Extra -5 to all losses
Duration = 3600f,
AffectsLossOnly = true
});AffectsGainOnly and AffectsLossOnly to create asymmetric modifiers that only affect positive or negative changes.Relationship History
The HistoryTracker maintains a circular buffer audit log of all relationship changes. Useful for debugging, analytics, and "recently changed" UI.
// Get history for a relationship
var entries = manager.GetHistory("player", "merchant");
foreach (var entry in entries) {
Debug.Log($"{entry.Timestamp}: {entry.OldValue} → {entry.NewValue} ({entry.Source})");
}
// Configure history size (default: 50 entries per relationship)
manager.SetHistoryCapacity(100);Reputation Caps
Caps constrain relationship values within boundaries. They are processed by the CapProcessor after every modification. When a modification is constrained, the OnCapReached event fires.
// Cap merchant reputation at 50 until "Guild Membership" quest is complete:
manager.AddCap("player", "merchant", new RelationshipCap {
CapId = "guild_membership_gate",
Source = "Guild Quest",
MaxValue = 50f,
MinValue = null // No floor
});
// Player completes quest → remove cap:
manager.RemoveCap("player", "merchant", "guild_membership_gate");
// Reputation can now grow beyond 50OnCapReached to show UI hints like "Complete Quest X to improve this relationship further."Cap Registrar Component
The CapRegistrar component provides a visual way to register caps without code. Place it on a GameObject and configure:
- Entity A / Entity B — The entities to cap (GC2 PropertyGet)
- Relationship Definition — Optional definition scope
- Cap ID — Unique identifier for removal
- Min/Max Values — The cap boundaries
- Auto-Register — Register on Start
Directional Caps (v1.1)
New in v1.1: Caps now use directional clamping instead of absolute clamping. This means caps only prevent crossing a boundary, not being outside it.
Why Directional?
Scenario: You want players to lose reputation on death, but not below 40. With absolute capping, a new player at 0 reputation would be lifted to 40 — not intended!
❌ Absolute (Old)
Clamp(value, min, max) forces value into range.
Player at 10 → becomes 40 ❌
✓ Directional (New)
Only prevents crossing the boundary.
Player at 10 → stays at 10 ✓
Player at 50, loses 20 → stops at 40 ✓
Behavior Table
| Old Value | Delta | New Value | Result | Reason |
|---|---|---|---|---|
| 0 | +10 | 10 | 10 | Below min, but rising — allowed |
| 50 | -20 | 30 | 40 | Would cross min — capped |
| 50 | +60 | 110 | 100 | Would cross max — capped |
| 110 | -20 | 90 | 90 | Above max, but falling — allowed |
// Death penalty floor - prevents dropping below 40, but allows starting lower
manager.AddCap("player", "guild", new RelationshipCap {
CapId = "death_penalty_floor",
Source = "Death Mechanic",
MinValue = 40f, // Can't DROP below 40
MaxValue = null // No ceiling
});
// New players at 0 can still gain reputation normally
// But established players can't fall below 40 on deathRelationshipDefinition.minValue and maxValue properties instead. Caps are for conditional boundaries.Diplomacy States
The DiplomacyManager adds discrete state-machine behavior to faction-to-faction relationships. States apply modifiers to relationship changes and can auto-transition based on value thresholds.
Available States
| State | Rep Gain | Rep Loss | Trade | Travel |
|---|---|---|---|---|
| War | ×0.5 | ×2.0 | ×0 | No |
| Hostile | ×0.75 | ×1.5 | ×0.25 | No |
| Ceasefire | ×1.0 | ×1.0 | ×0.5 | Limited |
| Neutral | ×1.0 | ×1.0 | ×1.0 | Yes |
| Friendly | ×1.25 | ×0.75 | ×1.25 | Yes |
| Alliance | ×1.5 | ×0.5 | ×1.5 | Yes |
// Set war state between two factions
manager.SetDiplomacyState(factionA.EntityId, factionB.EntityId, warState);
// Check current state
var currentState = manager.GetDiplomacyState(factionA.EntityId, factionB.EntityId);
// Auto-transition: When relationship > 60, transition to Alliance
warState.autoTransitionAbove = 60f;
warState.transitionAboveTo = allianceState;Advanced Decay
Relationships can decay toward a target value over time. Configure decay in the RelationshipDefinition.
Decay Modes
Constant rate per second
0.5f/sec → value decreases steadilyAnimationCurve for custom decay
Fast at extremes, slow at neutralDifferent rates for positive/negative
Positive decays fast, negative slow// In RelationshipDefinition asset:
enableDecay = true;
decayMode = DecayMode.Asymmetric;
decayTarget = 0f; // Neutral
positiveDecayRate = 0.5f; // Fast decay from positive
negativeDecayRate = 0.1f; // Slow decay from negativeRuntime Factions
Create factions dynamically at runtime for player-created guilds, procedural content, or multiplayer.
// Create a player guild
var playerGuild = manager.CreateRuntimeFaction(
name: "Dragon Slayers",
parentFaction: adventurersGuild, // Optional parent
inheritanceRate: 0.5f
);
// Add members
manager.AddToFaction(playerId, playerGuild);
// Dissolve when empty
manager.DissolveRuntimeFaction(playerGuild);