Bonusable Values

Modding Guide
4 May 2019, 12:19 p.m.

Bonuses are a system in Airships used to give players access to new modules, armours and constructions, and change their stats. You can use them to add new technologies, heraldic charges, and monster nest rewards.

Note that you should first read the basic post on modding for this to make more sense. Like last time, there's also an example mod for you to download, which adds one tech that increases rifle accuracy through a bonus.

In conquest, a player has a set of bonuses, which are provided by:

  • The main heraldic charge on their coat of arms
  • Technologies they researched
  • Special monster nest rewards

Outside conquest, the standard set of bonuses are all bonuses that are provided by technologies that don't have multiple choices.

Creating and providing bonuses

Bonuses are a loadable entity. You can find a list of them in data/Bonus/bonuses.json, and add new ones by creating a JSON file in a Bonuses folder in your mod. They have no information associated with them except for their name.

To create a new charge that gives a bonus, add the graphic for the charge to a SpritesheetBundle and add a new Charge entity with the "bonus" field pointing to the bonus.

{
    "name": "BAT",
    "bonus": "BAT_TROOPS",
    "appearance": { "src": "bat_troops_sprites", "x": 10, "y": 0 },
    "unlitAppearance": { "src": "bat_troops_sprites", "x": 10, "y": 0 },
}

To create a new technology, add a tech graphic and add a new Tech entity like this:

{
    "name": "BAT_CORPS",
    "sort": 2250,
    "tier": 2,
    "bonuses": [ "BAT_TROOPS" ],
    "dependencies": [ "AERIAL_CORPS" ],
    "img": { "src": "bat_troops_sprites", "x": 0, "y": 0, "w": 64, "h": 64 }
}

To give the bonus as a monster nest reward, add a reward to your monster nest like this:

{
    "name": "batmanInspiration",
    "spawnWeight": 3,
    "bonus": "BAT_TROOPS"
}

(Yes, in this example scenario you defeat Batman and then decide that he was on to something.)

Bonus effects

Bonuses can do the following:

  • Grant access to modules, e.g Heavy Cannons and armours, e.g. Steel Armour.
  • Grant access to special constructions, e.g Dragons.
  • Change module and armour stats, e.g. increasing explosive damage by 30%.
  • Change empire stats, e.g. increasing spy action success rate by 50%.

Module types and armour types can have a "required" field that references a bonus that unlocks them.

To grant access to a special construction, put it into data/bonusConstructions/BONUS_NAME. In the game, dragons and fleshcrackers are unlocked like this.

Finally, to change stat values based on bonuses, you use "bonusable values", which are data structures that describe how the value changes depending on what bonuses are active.

There are a number of different ways to write bonusable values depending on what you need:

No bonus changes

"something": 3

If a value doesn't change based on bonuses, you can always just write the value itself.

Simple

"something": { "base": 3, "SOME_BONUS": 4 }

Here, "something" is 3 unless you've got SOME_BONUS in which case it's 4.

Deltas

"something": {
    "base": 3,
    "deltas": { "SOME_BONUS": 1, "ANOTHER_BONUS": -1 }
}

The value is 3, but if you have SOME_BONUS, it's 4, and if you have ANOTHER_BONUS it's 2, and if you have both, it's 3 again. Deltas are only available for integer and floating-point numbers.

Multiple Bonuses

"something": {
    "base": {"r": 0, "g": 0, "b": 0 },
    "SOME_BONUS": {"r": 255, "g": 0, "b": 0 },
    "ANOTHER_BONUS: {"r": 0, "g": 255, "b": 0 }
}

Here, "something" is black by default, red if SOME_BONUS is active, and green if ANOTHER_BONUS is active. But wait - what if both are active? Then it's green - the alphabetically first bonus is chosen. So this is mostly useful if you have mutually exclusive bonuses, e.g. from techs that offer a choice.

Multiple Cases

"something": {
    "base": 3,
    "cases": [
        { "bonuses": ["SOME_BONUS", "ANOTHER_BONUS"], "value": 8 },
        { "bonuses": ["SOME_BONUS"], "value": 5 },
        { "bonuses": ["ANOTHER_BONUS"], "value": 4 }
    ]
}

So now, the value is 3 by default, 5 if SOME_BONUS is active but ANOTHER_BONUS isn't, 4 if ANOTHER_BONUS is active but SOME_BONUS isn't, and 8 if both are active. The code goes through each case in the list and uses the value of the first case that matches.

Where can you use bonusable values?

Nearly all values in ModuleType and ArmourType are bonusable, with the exception of a few things that change shape and connectivity.

A great example module to look at is rockets, which you can find in data/ModuleType/ROCKETS.json. Rockets:

  • Require a bonus to unlock.
  • Change appearance based on bonuses.
  • Have two different bonuses that affect their damage, so this is handled with a multiple case bonusable value.

Finally, if you want to change empire stats like research cost or the amount of repair done, look at data/EmpireStat/stats.json.

Here's what you can make bonusable in ModuleType:

  • hp - HP
  • destroyedHP - The HP amount at which it's destroyed
  • destructionLength - How long its destruction takes
  • destructionParticle - Custom destruction particle
  • destructionParticleDensity - Custom destruction particle density
  • destructionSound - Destruction sound
  • destructionParticle - Particle it emits when hit
  • runningLoop - Sound loop that plays while it's running
  • fireHP - At what HP it may catch fire
  • explodeHP - At what HP it may explode
  • explodeDmg - Explosion damage
  • explodeRadius - Explosion radius
  • explodeFuzeLength - Explosion time delay
  • moveDelay - How long it takes for a crew member to move through it
  • weight - Weight
  • coal - Coal storage
  • ammo - Ammo storage
  • repair - Repair tools storage
  • water - Water storage
  • sickbay - Sickbay effect
  • quarters - Number of crew quartered
  • quartersType - Type of crew quartered
  • command - Command points generated
  • lift - Lift generated
  • propulsion - Propulsion generated
  • coalReload - Time between needing a unit of coal to run
  • crew - Crew required to operate
  • optionalCrew - Additional crew to station in the module of available
  • recommendedCrew - Total number of crew recommended to operate and supply the module
  • recommendedGuards - Number of guards to station if possible
  • fixedGuards - Number of guards to station as a priority
  • cost - Cost
  • maintenanceCost - maintenance cost
  • shipHPBonus - HP bonus spread over all ship modules
  • accuracyBonus - Accuracy bonus to all weapons
  • app - Appearance
  • emitters, damagedEmitters, destroyedEmitters - Particle emitters for different states the module is in
  • externalApps - External appearances
  • adjacencyBonusStrength - How much this module counts for adjacency HP bonus
  • structuralStressAmount - Structural stress provided
  • hardness - Multiplier for damage inflicted in collisions
  • collisionDamageReceivedMult - Multiplier for damage received in collisions
  • lights - Light emitters
  • mask - Outline mask for module collision and armour

And for weapons:

  • reload - Reload time
  • ammoPerClip - Ammo needed to reload
  • clip - Clip size
  • clipReloadTime - Clip reload time
  • inaccuracy - Inaccuracy
  • fixedInaccuracyVsTroops - Additional naccuracy vs troops
  • blastDmg - Blast damage
  • blastSplashRadius - Blast damage radius
  • penDmg - Piercing damage
  • directDmg - Direct damage
  • numShots - Number of shots fired
  • shootTroopsRange - Maximum distance at which it shoots at troops
  • multiShotJitter - Additional inaccuracy applied to each projectile when firing multiple shots at once
  • shotSpeed - Shot speed
  • shotSpeedvariation - Shot speed variation
  • recoilForce - Recoil force
  • fireArc - Fire arc
  • muzzleCenterX, muzzleCenterY - Center of fire arc
  • muzzleLength - Distance from muzzle center where shot appears
  • muzzleFlash - Whether to show a muzzle flash
  • weaponAppearance - Weapon appearance, including barrel, shot, and particle effects
  • tether - Tether created when hitting target
  • maxXRange - Maximum horizontal range
  • minXRange - Minimum horizontal range
  • maxUpRange - Maximum range upwards
  • maxRange - Maximum range
  • fireSound - Sound effect when firing
  • hitSound - Sound effect when shot hits
  • soundEvery - How often to play the fireSound
  • optimumRange - Optimum range for AI
  • jitterMerge - Degree to which deviation of the previous shot is used for the next one

Here's a list of what you can't:

  • name - Name
  • categories - Category membership
  • flippeFrom - Flipped version
  • w, h - Width and height
  • availableFor - Which construction types (airship, landship, building) it's available for
  • instantlyDestroyed - Whether it's instantly destroyed rather than having a destruction sequence
  • destroyEntireShipOnDestruction - Whether the entire ship should be destroyed when this module is destroyed
  • hasGenericDestructionFragments - Whether it has standard destruction fragments
  • fragmentsDensity, fragmentsSpeedMult, fragmentsFireMult - Density, speed, and flammability of destruction fragments
  • obeysFireMode - Whether selecting rapid fire / aimed fire affects it
  • frontOnly, backOnly, topOnly, bottomOnly - Obstruction beams
  • countsAsActiveCrew - Whether it counts as active crew for purposes of being in combat
  • preventsBoarding - Whether it prevents boarding
  • preventsSurrender - Whether it prevents AI surrender
  • isRam - Whether it's treated as a ram by the AI
  • isSail - Whether it makes sail noises
  • isWeapon - Whether it's a weapon
  • required - What bonus is required to unlock it
  • leftDoors, rightDoors, upDoors - Left, right and up doors
  • external - Whether it's an external module
  • armourType - Its default armour type
  • drawDoors - Whether to draw the door indicators
  • framesAreVariants - Whether appearance frames should be treated as visual variants rather than animation frames
  • externalDrawPriority, drawExternalsBelowDecals - High, low external draw priority
  • doesCreak - Whether it creaks
  • canParticlesStick - Whether particles can stick to it
  • tentacleDeathSpasms - Whether its tentacles have animated death spasms
  • springs, wheels, legs, tentacles - Wheels, legs, and tentacles
  • createsExceptionalCombatEventAfterMs - Whether it should trigger a combat event for a portrait message at the bottom left
  • aiMaxY - Restriction on how far down the AI will move a ship with this module in
  • externalSubColor - The color in the spritesheet that gets substituted when re-coloring the module
  • externalSubBaseColor - The base color to mix the paint with when re-coloring the module
  • drawAppearanceInside - Whether to draw the appearance when looking at the inside of the ship
  • producesHorizontalDrag - Whether it produces horizontal drag
  • playDestructionSoundAtStartOfDestruction - Whether its destruction sounds should be played at the start instead of at the end of its destruction
  • runsWhenDestroyed - Whether it should continue running while its destruction is happening
  • windows - Window positions
  • canOccupy - Which tiles can be occupied
  • hangarPositions - Hangar positions for planes

With armour types, you can apply bonuses to these:

  • windowApp - Window appearance
  • damagedApps - Appearance in various states of damage
  • cost - cost
  • hp - HP
  • weight - Weight
  • lift - Lift generated
  • blastDmgAbsorb - Blast damage absorbed before any damage is applied
  • penDmgAbsorb - Piercing damage absorbed before any damage is applied
  • brokenSound - Sound played when the armour reaches 0 HP
  • largeHitSound - Sound played when the armour takes major damage
  • smallHitSound - Sound played on small hits

But not to these:

  • name - Name
  • required - Required bonus
  • placeSound - Sound to play when placing
  • placePitch - Pitch of placement sound
  • hidden - Whether to hide it in the list of armours in the editor

Finally, the following bonusable values are available as EmpireStats:

  • CITY_INCOME_PERCENTAGE_BONUS - Adjusts income in cities and towns
  • TAKEOVER_NEEDED - Whether this empire needs to take over cities and towns it's conquered
  • FIRE_QUENCH_AMOUNT - Amount of fire quenched by one bucket of water
  • REPAIR_AMOUNT - HP repaired with one set of repair tools
  • ESPIONAGE_SUCCESS_PERCENTAGE_BONUS - Adjusts spy action success
  • ESPIONAGE_COST_PERCENTAGE_BONUS - Adjusts spy action cost
  • PRODUCTION_PERCENTAGE_BONUS - Adjusts production in towns and cities
  • REVOLTING_CITIES_JOIN_EMPIRE - Whether a city incited to revolt joins this empire rather than becoming independent
  • BASE_RESEARCH_COST - Research point cost of a level 0 tech
  • RESEARCH_COST_EXPONENT - Factor by which each level of tech becomes more expensive
  • BIO_MONSTER_RESEARCH_MULT - Multiplier for research gained from monster rewards of biological monsters (eg dragons but not pirates)
  • BIO_MONSTER_MONEY_MULT - Multiplier for money gained from monster rewards of biological monsters (eg dragons but not pirates)