Crime system - mganzarcik/fabulae GitHub Wiki
Fabulae tracks several types of crimes:
- Theft – occurs if an item that belongs to another character or faction is picked up while being seen
- Assault – occurs if a non hostile character is attacked unprovoked
- Murder – occurs if a non hostile character is killed unprovoked
- Trespass – occurs if a lock in a faction owned location is picked while being seen.
All crimes track the following information: who committed the crime, who witnessed the crime, the object of the crime (item stolen, person assaulted, etc), the base fine associated with the crime and the faction disposition penalty for the crime. Note that some crimes, like murder, cannot by paid off by a fine.
Every time a new crime is committed, the following occurs:
Any faction penalties associated with the crime are applied to the faction of the victim. If this turns the faction hostile, that's it.
If the faction remains non hostile, the game checks whether the crime can be paid off with a fine. If yes, a random witness (who cannot be in the same faction as the criminal) initiates a dialogue with the criminal. The criminal will have an option to pay the fine or resist arrest. The fine amount may be modified by the current disposition of the victim's faction towards the player.
If he pays the fine, any items stolen during the crime will be removed from his possession in addition to the gold. These items will be returned back to where they were taken from. Any attacked characters will stop being hostile. The crime will be canceled and no longer tracked after that.
If the crime cannot by paid off by a fine, if the character does not have enough money or if he chooses to actively resist arrest, all witnesses of the crime will immediately turn hostile and the dialogue will end. The crime will get registered with the factions of all witnesses and of the victim. Half the disposition penalty of the crime will also be applied to the witnesses factions. If the player attacks and hurts any of the hostile witnesses, a separate assault crime will be raised and registered for each attacked witness, this time without the option of paying the fine. If he kills any during the ensuing combat, a separate murder crime will be raised and registered as well. If he chooses to escape and succeeds, the witnesses will stop being hostile after 24 hours of game time, but the crimes will stay registered.
The fines and faction disposition penalties should be configurable.
Every item in the world can have an owner defined. Owner can either be an NPC, a Faction, or both.
Owned items can be freely picked up with no crime penalty as long as the owner does not witness it. If the stealing PC is currently sneaking, she has to make a stealth check if picking it up in the radius of the owner. If the PC isn’t sneaking, the crime is witnessed automatically if it is in the radius of the owner.
Owned items are clearly marked on the map as owned, therefore the player must make a conscious choice to steal. Owner information is also visible in the Inventory UI so that the player can track which items are stolen and from whom. Whenever a PC tries to sell any item, the owner of the item is checked against the buyer. If they are the same, the item cannot be sold to the vendor.
Sold stolen items that do not have a "fixed" owner lose the owner information (become “laundered”) and can be subsequently repurchased. Fixed items never lose Owner information. This is something that can be configured per item.
Every attack on a character from a non hostile faction is considered an assault. If the assaulted character dies as a result of the assault or later during the combat started by the assault, a separate murder crime will also be registered. For the purposes of crime, only spells that deal damage are considered as attacks – putting a non - hostile NPC to sleep will not be considered as a crime. This can be used by the player for his advantage – for example by putting a shopkeeper to sleep and then stealing his merchandise.
Murder can never by paid off by a fine.
If a crime is witnessed, the crime is recorded with the Faction of the owner. All members of the Faction will instantly become aware of the crime and all its details (what was stolen or who was murdered). Player’s reputation with the faction will be instantly lowered by the penalty for the given crime which might result in the Faction turning hostile.
Once the Crime is registered with a Faction, Faction members start spreading information about the Crime to neighboring friendly (with non-negative disposition) Factions. This is done by traveling characters on the world map. If a Faction becomes aware of a new crime this way, it will lower it's disposition towards the perpetrator's faction by one half of the crime's disposition penalty.
Propagation pseudocode for agents:
onLocationEnter(Location loc) {
Faction locationFaction = loc.getFaction();
if (getFaction().isFriendlyTo(locationFaction)) {
spreadCrimeInfoTo(locationFaction);
}
}
Some faction members can be designated as law enforcers (guards, sheriffs, judges, etc.). These members, if they spot a character who has committed a known crime, will automatically initiate a dialogue that would follow the same flow as a the dialogue initiated by a direct witness (i.e. pay a fine or resist). Paying the fine will remove the crime from the list of tracked crimes for all factions. The fine amount will be multiplied by the number of factions that are aware of the crime.
As mentioned above, non-player characters can react to crimes performed around them in various ways - they can initiate a dialogue asking for a fine either as a witness, or as a law enforcer. Defaults for these dialogues need to be configured in the module configuration and defined. Individual characters can also override these default dialogues and define their own.
In all cases, the dialogues must always end with the player being presented with the option of paying or not, where the paying option has to be marked as the "yes" option. In all of the dialogue texts, it is possible to access a special <fine>
property to display the current fine amount.
Examples:
https://github.com/mganzarcik/fabulae-showcase/blob/master/showcase/dialogues/FineDialogue.xml