Authoring Reputations

Standing with a faction or one character, kept by the game and named by the library

A reputation is how a faction, or one character, thinks of a player. The number is Hytale's own: the game keeps one per player for each reputation, saves it with the character, and keeps it through death and across worlds. ZiggfreedCommon adds what the game leaves out: a name and a picture, a cap, its own word for each rank, standing for kills, gear that makes every gain bigger while it is worn, rewards past the top rank, the Reputation tab on the shared menu, a bar that moves with standing, and a notice when a rank goes up.

Seasons of Orbis ships the first two, and both are quoted on this page: Old Jack's Favor, standing with one character, and the Hallowed (id Hallows_Eve_Hallowed), a reputation with no characters in it.

Where the files go

One reputation is up to four files under Server/, and only the reputation group is required.

MyFactionPack/
├── manifest.json                                      # "IncludesAssetPack": true
└── Server/
    ├── NPC/Reputation/Groups/Your_Traders.json        # the reputation itself
    ├── NPC/Groups/Your_Traders.json                   # the characters whose attitude follows it
    ├── Entity/Stats/ReputationGain_Your_Traders.json  # the stat gear speeds gains on
    └── ZiggfreedCommon/Reputations/MyStudio/Your_Traders.json

A reputation group with no companion file still works: it reads by its id, with no cap and no kills, and the page names it by its id. The game reads reputation groups and ranks once at start, so a change to either needs a restart.

The reputation group

Content pack assetServer/NPC/Reputation/Groups/<Id>.json

A native Hytale asset. Its filename is the reputation's id everywhere else: the companion file, a reward, a factor and an objective step all name it.

Server/NPC/Reputation/Groups/Hallows_Eve_Old_Jack.json (Seasons of Orbis)
{
  "NPCGroups": [ "Hallows_Eve_Old_Jack" ],
  "InitialReputationValue": 0
}
FieldTypeDefaultDescription
NPCGroups*string[] (NPC group ids)-The native NPC groups (Server/NPC/Groups/, each listing roles under IncludeRoles) whose characters treat a player by the rank that player holds here. A reputation nobody stands behind writes an empty list.
InitialReputationValueint0Where every player starts. A player who has never touched the reputation reads this value.
* required

Keep the NPCGroups key, even when it is empty

A reputation group with no NPCGroups key, or one naming an NPC group that is not loaded, makes the game throw on every NPC that spawns, in every world. The Hallowed's reputation group writes "NPCGroups": [] for exactly this reason.

The rank ladder

Every reputation on a server climbs one ladder of seven ranks, which the library ships in Server/NPC/Reputation/Ranks/. A rank runs from its floor up to the next rank's floor, and its attitude is how the characters in a reputation's NPC groups treat a player who holds it.

RankFromAttitude
Hated-30,000, the bottomHostile
Unfriendly-3,000Neutral
Neutral0Neutral
Friendly1,000Friendly
Honored3,000Friendly
Revered9,000Revered
Exalted21,000, open-endedRevered

To retune a rank, ship a file of the same name (MinValue, MaxValue, Attitude) in your own pack. The ladder is server-wide, so a mod that ships ranks of its own changes every reputation, and the game logs a warning at start when two ranks overlap or leave a gap. A rank holds its MinValue and stops short of its MaxValue, so give each rank the next one's floor as its MaxValue. Each reputation can still call a rank by a name of its own: see Ranks below.

The companion file

Content pack assetServer/ZiggfreedCommon/Reputations/<Namespace>/<Id>.jsonReputations/

The filename is the id of the reputation group it describes, matched without regard to case; the folders are your own grouping. Every leaf is inherited through Parent. The owner layer is mods/ziggfreedcommon/reputation.json.

defaults<pack<owner
FieldTypeDefaultDescription
Text{TitleKey, FlavorKey}the idWhat the reputation is called and its description, as keys in your own lang file.
Iconstring (item id)noneThe item whose picture stands for the reputation on its page row, its bar and its rank notice.
Orderint0Where it sorts on the page and among the bars: lower first, then by id.
Capintthe whole ladderThe most standing a player can earn here through rewards and kills. A gain past it is cut to it, after any boost from gear, and a loss is never cut.
Ranks{<Rank>: {Name, From}}the library's wordsWhat this reputation calls each rank, keyed by rank id (Neutral, Friendly, ...), each Name a key in your own lang file. A rank left out reads with the library's own word. An id that is not one of the server's ranks, written with a From, is a rank of this reputation's own above the top one (Exalted): it starts at that much standing, above the top rank's floor, and lasts until the next one's From. Seasons of Orbis's Festival Favor climbs on to Exalted II, III and IV this way. A From on one of the server's own ranks is reported and ignored, since their floors are the same for every reputation. Under Parent the map merges by rank id.
Kills[{NPCGroups, Amount, Season}]noneStanding for each kill of an NPC whose role is in one of the listed NPC groups. A negative Amount costs standing. A row with a Season, a calendar event's id such as Hallows_Eve, counts kills only while that event runs: the rest of the time it counts nothing, as if it were not written, and the reputation's other rows still count. Leave it out for a row that counts all year. Under Parent this list replaces the parent's whole.
Beyond{Every, Rewards, Collect}pays nothingRewards for standing earned past the top rank's floor (its own highest rank, when Ranks adds some): each time earned standing crosses another multiple of Every above it, the player earns Rewards once, in the same entries a quest pays. With Collect true (the default) each one waits on the reputation's page until the player presses Collect, which pays up to 20 at a press and leaves the rest waiting; a press whose item rewards would not fit pays nothing and keeps them all waiting (a Lootable or Currency reward is never held back for room); with Collect false it pays on the crossing. Each step is earned once: falling below it and earning it back pays nothing again. An Every of zero or less pays nothing.
Earn{Lines}what the library can seeHow a player earns it, in your own words, for the How to earn block on the Reputation page: Lines is a list of keys in your own lang file, one line each, in the order the page lists them ("Take contracts from his board."). Left out, the page says only what the library can see (kills that count right now, so a row out of its Season says nothing), or a plain "their quests and requests raise it" when it sees none. Either way, while the player's gear changes what they earn, a last line says by how much. Under Parent the list replaces the parent's whole.
EnabledbooltrueFalse takes the reputation off this server: its readings answer nothing, so a gate on it stays shut, rewards naming it refuse to pay, and the page leaves it out. The standing players hold is kept.
* required
Server/ZiggfreedCommon/Reputations/HallowsEvePack/Hallows_Eve_Old_Jack.json
{
  "Text": {
    "TitleKey": "reputation.hallows_eve_old_jack.name",
    "FlavorKey": "reputation.hallows_eve_old_jack.flavor"
  },
  "Icon": "Hallows_Eve_Jack_Helm",
  "Order": 10,
  "Cap": 21000,
  "Ranks": {
    "Neutral":  { "Name": "reputation.hallows_eve_old_jack.rank.neutral" },
    "Friendly": { "Name": "reputation.hallows_eve_old_jack.rank.friendly" },
    "Honored":  { "Name": "reputation.hallows_eve_old_jack.rank.honored" },
    "Revered":  { "Name": "reputation.hallows_eve_old_jack.rank.revered" },
    "Exalted":  { "Name": "reputation.hallows_eve_old_jack.rank.exalted" }
  },
  "Earn": {
    "Lines": [
      "reputation.hallows_eve_old_jack.earn.quests",
      "reputation.hallows_eve_old_jack.earn.board",
      "reputation.hallows_eve_old_jack.earn.talk",
      "reputation.hallows_eve_old_jack.earn.gear"
    ]
  }
}

Old Jack's favor stops at Exalted's floor, and his ranks read Stranger, Regular, Trusted, Confidant and Jack's Own. His four earn lines read "Do his errands and his daily jobs.", "Take contracts from his board.", "Stop by for a word once a day." and "Wear a Jack Helm, and everything you do for him earns more favor while you have it on." The Hallowed has no cap. It counts kills of the season's creatures and pays a loot table every 5,000 past Exalted:

Server/ZiggfreedCommon/Reputations/HallowsEvePack/Hallows_Eve_Hallowed.json
{
  "Text": {
    "TitleKey": "reputation.hallows_eve_hallowed.name",
    "FlavorKey": "reputation.hallows_eve_hallowed.flavor"
  },
  "Icon": "Hallows_Eve_Hollow_Lantern",
  "Order": 20,
  "Kills": [
    { "NPCGroups": [ "Hallows_Eve_Event_Mobs" ], "Amount": 2 }
  ],
  "Beyond": {
    "Every": 5000,
    "Rewards": [ { "Kind": "Lootable", "Params": { "Lootable": "Hallows_Eve_Hallowed_Cache" } } ]
  },
  "Earn": {
    "Lines": [
      "reputation.hallows_eve_hallowed.earn.kills",
      "reputation.hallows_eve_hallowed.earn.jack",
      "reputation.hallows_eve_hallowed.earn.treats",
      "reputation.hallows_eve_hallowed.earn.gear"
    ]
  }
}

Gear that speeds gains

Gear never adds standing. It makes each gain bigger, by a percent, through two stats: the library's ReputationGain, which counts for every reputation, and ReputationGain_<Id>, which counts for one. The library ships the first. For gear that favors one reputation, ship the second yourself, with <Id> spelled as the reputation group's file name, a base Max of 0 and a Min of -100. The companion file needs no leaf for it: the library finds the stat by its name.

Server/Entity/Stats/ReputationGain_Hallows_Eve_Old_Jack.json
{
  "InitialValue": 0.0,
  "Min": -100.0,
  "Max": 0.0,
  "Shared": false,
  "HideFromTooltip": false
}

Give each item a modifier on the stat's Max, in whole percent points: 10 is +10%. The game applies and clears it as the item goes on and off. Armor names the stat in Armor.StatModifiers, a shield in Utility.StatModifiers, and a gear set's tier in its own.

The Jack Helm's Armor.StatModifiers (Seasons of Orbis)
"StatModifiers": {
  "ReputationGain_Hallows_Eve_Old_Jack": [ { "Amount": 10, "CalculationType": "Additive", "Target": "Max" } ]
}

The library adds the two stats together and multiplies every gain by that much, rounded, never to less than 1: with the Jack Helm on, a 250 reward pays 275. A kill, a quest, a contract, a daily line and a reward collected from a boss's chest or a dungeon's clear all count, and so does standing past the top rank. A loss is never changed, and the Cap cuts the gain after the boost. The total counts from -100% to +1,000%. The item's tooltip line reads the client.lang key itemTooltip.stats.<Stat> ("Old Jack's Favor Gain: 10%"), and the reputation's page ends How to earn on "Your gear raises what you earn here by 10%." while it is worn.

Standing is what was earned

Every gate, the rank shown, the page, the bar, the rank notice, the attitude of the reputation's characters and the Beyond payouts read the standing the player has earned. Putting gear on never opens a lock or reaches a rank by itself, and taking it off never lowers standing.

Earning standing

  • Rewards. The Reputation reward kind moves standing by a whole Amount, negative to cost standing, anywhere a reward pays: a quest, a contract, a shop offer, an achievement, a loot table, a conversation line's Grant. In a reward list it reads "+250 Old Jack's Favor". See Rewards.
  • Kills, through the companion's Kills table. The standing lands a moment after the kill. A row with a Season counts only while that calendar event runs, the same Season leaf shops, boards, quests and dungeons use, so a reputation can pay a little more during an event and go back to its usual rows when the event ends.
  • A word each day. A Start beat with a daily Once can pay a little standing the first time each day a player stops to talk: see Beats that pay.
A quest reward
{ "Kind": "Reputation", "Params": { "Reputation": "Hallows_Eve_Old_Jack", "Amount": 250 } }
Kills, one row all year and one only while an event runs (placeholder ids)
"Kills": [
  { "NPCGroups": [ "Your_Bandits" ], "Amount": 5 },
  { "NPCGroups": [ "Your_Night_Creatures" ], "Amount": 1, "Season": "Your_Event" }
]

Reading standing

Two readings join the shared factor vocabulary, so a Requires block, a conversation condition or a loot roll can ask about any reputation:

FactorParamReads
ziggfreedcommon:reputation<Id>The standing the player has earned
ziggfreedcommon:reputation_rank<Id>/<Rank>1 at or above that rank's floor, 0 below it

Each one fails closed: a reputation the server lacks or has switched off, a rank not on the ladder, or no live player answers nothing, and the gate stays shut. A player who has never touched a reputation reads its starting value. Write a Min on every condition. The worked spellings are on Shared Schemas.

The Jack Shield on Old Jack's stall, for players Honored with him
"Requires": {
  "Factors": [
    { "Factor": "ziggfreedcommon:reputation_rank", "Param": "Hallows_Eve_Old_Jack/Honored", "Min": 1 }
  ]
}

How a lock reads

A lock on a rank names the rank and the reputation by itself: the rank's name (its Ranks name, else the library's word) with the reputation's own name, so a gate on Town_Guard/Honored reads "Requires Honored with Town Guard". A board slot, a contract and a shop offer all read it this way. A shop offer that asks for several things lists each on a line of its own, and one with more than one way in reads "Unlocked by:" with each way; hovering the offer, or pressing Buy, says the same. The generic line ("a rank with a reputation") reads only when the reputation names itself nowhere or the rank is not on its ladder.

To word a lock your own way, such as "Requires Trusted with Old Jack" in place of "Trusted with Old Jack's Favor", ship a naming overlay with a ParamNames.Keys entry for each exact Param you gate on, each pointing at a full lang key. An overlay entry is asked first and wins:

Server/ZiggfreedCommon/Factors/HallowsEvePack/Hallows_Eve_Old_Jack_Favor.json
{
  "Factor": "ziggfreedcommon:reputation_rank",
  "ParamNames": {
    "Keys": {
      "Hallows_Eve_Old_Jack/Friendly": "hallowseve.progression.factor.hallows_eve_old_jack.friendly",
      "Hallows_Eve_Old_Jack/Honored": "hallowseve.progression.factor.hallows_eve_old_jack.honored"
    }
  }
}

Those two keys read "Regular with Old Jack" and "Trusted with Old Jack". A gate on a rank the overlay does not list reads the library's own line, the rank's name with the reputation's.

A step on a rank

The REPUTATION_RANK objective kind counts holding a rank: Target is the rank id and Qualifier the reputation id (leave it out to count any reputation). Every rank from the reputation's starting rank up to the one held is credited, at login and after every reward or kill, so a jump never misses a rank. Below the starting rank, only the ranks reached going down are credited. A quest step and an achievement's criterion both take it. Jack's Confidant in Seasons of Orbis is an achievement whose one criterion is reaching Revered with Old Jack:

Server/ZiggfreedCommon/Achievements/HallowsEvePack/_Hallows_Eve/Jacks_Confidant.json (Seasons of Orbis, Criteria only)
"Criteria": {
  "reach-confidant": {
    "Kind": "REPUTATION_RANK",
    "Target": "Revered",
    "MatchMode": "EXACT",
    "Qualifier": "Hallows_Eve_Old_Jack",
    "Amount": 1,
    "TextKey": "objective.hallows_eve.jack_confidant"
  }
}

Write MatchMode EXACT

A target matches under CONTAINS by default, and Friendly is inside Unfriendly. EXACT counts the rank you named and nothing else.

What a player sees

  • The Reputation tab on the shared menu, once they have any standing with a reputation. A line at the top says what reputation is for, then one row per reputation they have met ("Who knows you"): its rank, and how far it is to the next rank or, past the top, to the next reward when the reputation pays one.
  • The page of the one they pick: their rank and a bar toward the next one, the description whole, then How to earn (your Earn lines, and a last line with how much their gear raises or lowers each gain, while it does), Ranks (every rank from the starting one to the top, plus the one they hold if it is below the start, each with the standing it takes, what it opens and the achievement it earns with what that pays), Past the top rank when Beyond pays, with what is waiting and the Collect button, and Your standing (what they have earned and the most they can earn).
  • What a rank opens is read from the content itself, with nothing to author: every shop offer and every board slot whose Requires asks for that rank, by its name and where it is ("Burning Jack Helm at Old Jack's Stall", "An extra Night Work contract at Old Jack's Board"). It lists them all year, so a seasonal stall that is packed away still shows what each rank holds.
  • A bar on the World bars panel each time a reward or a kill out in the world moves their standing, beside the skill XP bars. It reads the reputation's name and picture alone with the gain, and fills through the rank held; the rank shows on the Reputation tab and in the rank-up notice.
  • Standing earned inside a menu (collecting a reward, buying something, taking a quest that pays out at once or picking a line in a conversation) is listed in the notice that pops up in that menu, with the rest of what they got, such as "+250 Town Guard". When a reputation's Cap held part of it back, the notice shows the part they got. It does not play again as a bar once the menu closes, so the Settings tab has no "Reputation changes in menus" switch any more.
  • A notice when a rank goes up during play: the Reputation_Rank feedback moment, which a pack or a server owner replaces by shipping a file of the same name. A fall raises no notice, and logging in raises none.

A conversation line or a placement opens the page through the Reputation destination: "Open": "Reputation" opens on the first reputation the player has met, and { "Type": "Reputation", "Reputation": "<Id>" } on that one. Old Jack's "How do we stand?" uses the second form.

Switching off and retuning

Override configmods/ziggfreedcommon/reputation.json

$Enabled is the switch over every reputation. Every other top-level key is a reputation id, merged leaf by leaf over what the packs ship.

json
{ "$Enabled": false }                                    // every reputation off
{ "Hallows_Eve_Old_Jack": { "Cap": 9000 } }              // retune one, leaf by leaf
{ "Hallows_Eve_Hallowed": { "Enabled": false } }         // switch one off

A reputation switched off is gone from the server: its readings answer nothing, rewards naming it refuse to pay, and the page leaves it out. Nobody's standing is touched, so switching it back on picks up where every player left off. Hytale's own /reputation command sets a player's standing directly: every reading sees the new number, but the Cap does not apply and no bar, notice or Beyond reward follows.

Checking your work

The library audits every reputation at boot and logs its errors once, so a server without MMO Skill Tree still hears them. The whole audit, warnings included, runs at boot on a server started with the environment variable ZIGGFREEDCOMMON_AUDIT_ON_BOOT=1, under [reputation] audit beside the library's other passes, and each error is still printed once. On an MMO Skill Tree server, /mmoconfig validate lists the findings under reputation with the rest of the content audit.

FindingSeverityMeans
TOO_FEW_RANKSerrorFewer than two ranks are loaded, so the game cannot bound standing. Something replaced or removed the library's ladder.
GROUP_WITHOUT_NPC_GROUPSerrorA reputation group has no NPCGroups key. Write "NPCGroups": [].
KILL_WITHOUT_GROUPSerrorA Kills row lists no NPC groups, so it never counts a kill.
FROM_ON_SHARED_RANKerrorA From sits on one of the server's own ranks, whose floors are the same for every reputation. It is ignored; a rank above the top needs an id of the reputation's own.
TIER_OUT_OF_RANGEerrorA rank of the reputation's own has a From that is not above the top rank's floor and below its ceiling, so it is left off this reputation's ladder.
TIER_SHARES_FLOORerrorTwo of the reputation's own ranks have the same From, so one could never be reached and is left off.
TIER_SHARES_IDerrorA rank of its own is written twice in two cases. Ids match without regard to case, so only the first by floor stands.
NO_NATIVE_GROUPwarningA companion file matches no reputation group, so nothing reads it.
UNKNOWN_NPC_GROUPwarningA reputation group names an NPC group that is not loaded, and the game throws on every NPC added while it is missing.
UNKNOWN_KILL_GROUPwarningA Kills row names an NPC group that is not loaded, so that group counts nothing.
UNKNOWN_ICONwarningIcon is no loaded item, so the picture is missing.
UNKNOWN_RANKwarningRanks names a rank that is not on the ladder, so that name never shows.
CAP_BELOW_LADDERwarningCap sits below the ladder's bottom, so every gain is cut to nothing.
TIER_ABOVE_CAPwarningCap sits below the floor of one of the reputation's own ranks, so rewards and kills never reach it.
TIER_WITHOUT_NAMEwarningA rank of the reputation's own has a From but no Name, so players read its id where its name belongs.
UNKNOWN_SEASONwarningA Kills row's Season names no calendar event on this server, so that row never counts. Add the event's calendar file, or correct the id.

The library's own words live in ziggfreedcommon.reputation.lang: the seven rank names, the generic factor names, the page, the bar and the notice. A reputation's name, description and rank names are keys in your own lang file.

See also