Creating Content ‐ Guns - FlansMods/FlansModReloaded GitHub Wiki

How to Create Content - Guns

As with all FM:R content, the files are written in Json.
"Guns" are actually more versatile than you would think. They can have a completely custom set of actions on primary and secondary, including repair tools and vanilla block harvesting actions.
See Vender's Game Gun Definitions for some practical examples.

Item Settings

See Shared Elements
Note that Guns can only stack to 1.

Paints

See Paints

Action Groups

The core of any Gun (or Gun-like tool) is its ActionGroups. Each group contains an array of actions to perform and other settings such as how often the action group can be retriggered.
actionGroups is a JSON array of JSON objects, each one being a single ActionGroup.

  • key: The identifier of this group. This is used to trigger the group from InputHandlers or Triggers.
  • canActUnderwater: If false, and the ShootOrigin is inside a Water block, the ActionGroup will fail.
  • canActUnderOtherLiquid: As above, for any other liquid.
  • canBeOverriden: If true, an attachment can replace this action. (Not currently tested)
  • twoHanded: If true, and this Gun is held by a LivingEntity with both hands full, the ActionGroup will fail.
  • repeatMode: One of the following:
    • "SemiAuto": The player must press, release and press again to fire multiple shots.
    • "FullAuto": The player may hold, and the ActionGroup will try to retrigger using repeatDelay.
    • "BurstFire": Like SemiAuto, but it triggers a number of times equal to repeatCount.
    • "Minigun": Like FullAuto, but it builds a charge while the player holds and only begins to trigger after spinUpDuration.
    • "Toggle": Like SemiAuto, but pressing the input a second time will cancel any current instances of this ActionGroup.
    • "WaitUntilNextAction": Like Toggle, but it cancels when any other ActionGroup starts.
  • repeatDelay: How long, in seconds, between retriggering FullAuto, Minigun and BurstFire modes.
  • repeatCount: How many times to trigger, only for BurstFire mode.
  • spinUpDuration: How many seconds from first pressing the input to triggers starting, only for Minigun mode.
  • loudness: How far away, in blocks, can this ActionGroup be "heard"? Not just for sound effects, this tells the multiplayer systems how far away to send out shot data and render effects.
  • autoCancelIfNotInMode: A mode check, in the format ":". If this is non-empty and the Gun is no longer in the specified mode, this ActionGroup will be cancelled.
  • actions: A JSON array of ActionDefinitions, detailed in the next section.
    "actionGroups": [
        {
            "key": "primary_fire",
            "canActUnderwater": true,
            "canActUnderOtherLiquid": false,
            "canBeOverriden": true,
            "twoHanded": true,
            "repeatMode": "SemiAuto",
            "repeatDelay": 0.05,
            "repeatCount": 3,
            "spinUpDuration": 1.5,
            "loudness": 150.0,
            "autoCancelIfNotInMode": "",
            "actions": [
                {
                }
             ]
         }
     ]

ActionDefinitions

Each of these represents one Action in a group. For example, an ActionGroup might contain a Shoot action, a PlaySound action and a DropItem action.

  • actionType: The type of Action to create. One of the following:
    • Shoot: The most complex action, it tries to consume one bullet from a magazine, then creates a hitscan or projectile entity and synchronises to the server. See Magazines (TODO) and Reloads (TODO).
    • PlaySound: Plays one or more sounds at the Shooter's location.
    • Animation: Plays an animation on the Gun if it has an animation set applied and that animation set contains the specified animation.
    • AimDownSights: Holds the Gun up to the Shooter's eye-line.
    • Scope: Same as AimDownSights, with an additional scope texture over the whole screen.
    • CookGrenade: Triggers another ActionGroup when it finishes, reducing that Group's fuse time, if relevant.
    • Drop: Creates an Item entity [TODO: Doc]
    • Raycast: Calculates what is on the Shooter's trajectory. Does nothing alone, should be paired with a Trigger.
    • Melee, Shield, Pickaxe, Axe, Shovel, Hoe, Till, Strip, Shear, Flatten: Vanilla actions, these are handled slightly differently.
    • AttachEffect: Coming soon, should be used to create muzzle flash and other temporary meshes or effects
    • Laser: While active, a laser is rendered from the Gun.
    • SwitchMode: Sets the selected value of one of the Gun's modes, such as "gadget:On" or "angled_sight:45"
  • duration: Relevant for some Actions (e.g. Animation), defines how long the Action should be active.
  • sounds: A JSON array of SoundDefinitions, used for PlaySound Actions.
  • itemStack: A Minecraft formatted item with optional tags, some Actions will use this field.
  • modifiers: A JSON array of ModifierDefinitions. See TODO
  • scopeOverlay: The ID of a texture to render when looking down the scope.
  • anim: The animation sequence name to play, only used by Animation Action.

Input Handlers

InputHandlers are the way in which a Gun turns player inputs into actions that the gun should perform. A handler should take a player input, such as "Fire1" (key mapping is handled for you) and give a list of potential actions to perform. This allows the handler to specify how attachment actions get included in the calculation (if at all) and to define things like "pressing Fire1 while empty will automatically initiate a reload".
This is a JSON array of JSON objects, each one being referred to as an InputHandler.
An InputHandler has the following elements:

  • inputType: Which input triggers this handler?
  • nodes: A JSON array of the InputHandlerNode objects that tell us what to do with the input. These are evaluated from top to bottom in order.

InputHandlerNode

  • actionGroupToTrigger: The key of the ActionGroup you want to trigger
  • modalCheck: If this is non-empty, the Gun will check if it is in this mode. Otherwise, this node will be skipped.
  • canTriggerWhileReloading: Do reloads block this? It is somewhat special case because reloads are complicated multi-actions.
  • deferToAttachment: If true, this node represents us passing the input to the specified attachment. If the attachment is not present, or does not do anything with this input, this node will be skipped.
  • attachmentType: The attachment type, only used if deferToAttachment is set.
  • attachmentIndex: The attachment index, only used if deferToAttachment is set. If you have two attachment slots of one type, this differentiates them.
  • andContinueEvaluating: If this node does something with the input, should we check the further nodes anyway? If this node was skipped, we proceed anyway.
    "inputHandlers": [
        {
            "inputType": "Fire1",
            "nodes": [
                {
                    "canTriggerWhileReloading": false,
                    "deferToAttachment": true,
                    "attachmentType": "Barrel",
                    "attachmentIndex": 0,
                },
                {
                    "actionGroupToTrigger": "safety_click_sound",
                    "modalCheck": "safety:On",
                    "canTriggerWhileReloading": false
                },
                {
                    "actionGroupToTrigger": "primary_fire",
                    "canTriggerWhileReloading": false
                },
                {
                    "actionGroupToTrigger": "reload_primary_start",
                    "canTriggerWhileReloading": false
                }
            ]
        }
    ]

Reloads

A "Reload" is a set of 4 actions that use the built-in reloading logic in Flan's Mod.
Depending on the Magazine, Bullet and Gun setup, start, eject, loadOne and end will trigger a varying number of times each.

    "reloads": [
        {
            "key": "primary_fire",
            "manualReloadAllowed": true,
            "autoReloadWhenEmpty": true,
            "startActionKey": "reload_primary_start",
            "ejectActionKey": "reload_primary_eject",
            "loadOneActionKey": "reload_primary_load_one",
            "endActionKey": "reload_primary_end"
        }
    ],

Worked Example: In the above example JSON, we are responding to the player pressing "Fire1", generally assigned to left mouse.

  1. If we have a barrel attachment (index 0 if multiple barrel attachments) AND it has a "Fire1" handler, run that handler. If it exits, we EXIT.
  2. Then we check if the gun has its "safety" mode set to "On", and if so, we trigger an action group keyed as "safety_click_sound" and EXIT.
  3. Then we try to fire the gun (the "primary_fire" action group might tell us it couldn't start, if we have no bullets loaded for example) and EXIT.
  4. Then we try to start a reload. Note: We only get here if all the previous nodes didn't run.
⚠️ **GitHub.com Fallback** ⚠️