Status Effects
Status Effects are used for both active items and passive buffs/debuffs applied to the player.
Levels
Set the max level of a status with numLevels
:
1 2 3 | { "numLevels":3, } |
Levels can be used however you want. In the official Chippy levels, they represent the quantity of an item you have, but it could instead represent the strength of the item.
Player Modifiers
Player modifiers are easy ways to change certain properties of the player while a status is active.
The modifiers can be expressed as a simple value or as a script func that is constantly updated.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | { "modifiers": { // multiplier to player's movement speed "moveSpeedMultiplier": 1.5, // multiplier to player's movement friction "frictionMultiplier":0.5, // amount added to `playerDamageBonus` property, which bullets can add to their damage "damageAmount": "level * 0.38f", // multiplier to player's opacity "opacityMultiplier":"map(playerGrazePercent, 0f, 1f, 0.5f, 1f, 'SineOut')", // while true, player can safely move through bullets, pixels, and lasers "intangible": "dist(playerVel) < 0.1f", // amount to add to player's bullet avoidance strength "avoidBulletsAmount":0.6, // how much to reverse player's move/aim input (0-1) "reverseInputPercent":"0.5f + sin(stageTime * 2f) * 0.5f", }, } |
Items
Selectable
The isSelectable
property differentiates items from passive effects.
1 2 3 | { "isSelectable":true, } |
If isSelectable
is true, an item will show up in the player's item bar and can be selected.
Activation
For a status effect intended to be used as an active item, you should define the onActivate
handler. This handler is triggered when the player presses the "use item" button while this status effect is selected.
1 2 3 4 5 6 7 8 9 | { "onActivate": [ // your item's effect: { "action": "CallMethod", "target":"stage", "method": "ShakeCamera", "params": { "strength":0.5, "time":0.75, }}, // typically, you want to remove one of the item stack when you use it { "action": "CallMethod", "method": "LevelDown" }, ], } |
Charge
The charge
properties are a convenient way to do time-based effects, though more complicated functionality can be done with custom variables and the onUpdate
handler.
The following is from an unused powerup that repelled nearby bullets after you closely graze a bullet long enough:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { // this func is added to "charge" each frame (in this case, it's how closely a player is grazing bullets, from 0-1) "chargeIncrease":"playerGrazePercent", // when charge reaches this amount, "onExecute" is triggered, "chargeRequired":2.8, // apply this friction amount (0-1 value) to "charge" each frame (0.2 reduces charge by 20% each frame), "chargeDecay":0.2, "onExecute": [ { "action": "CallMethod", "target":"stage", "method": "RepelBullets", "params": { "pos":"playerPos", "radius":100, "freezeTime":0.5, "color":"color(0.66f, 0.66f, 1f) * 1.15f", "strength":100, "effectBullet":"misc/bullet/effect/repel", "easingType":"QuadIn", }}, { "action": "CallMethod", "method": "Disable" }, ], } |
Handlers
You may want to call Actions at certain points during a status effect.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | { "onEnable":[ // called when status effect is started (gains its first level) { "action": "CallMethod", "target":"stage", "method": "ShakeCamera", "params": { "strength": 3, "time": 0.5, "easingType": "QuadOut" }}, ], "onLevelUp":[ /* called when status effect gains a level */ ], "onMaxedOut":[ /* called when status effect gains a level but is already at max level */ ], "onLevelDown":[ /* called when status effect loses a level */ ], "onPreventDeath":[ /* called when status effect level is lost to prevent player death */ ], "onDisable":[ /* called when status effect is finished */ ], "onUpdate":[ /* called each frame the status effect is active */ ], "onActivate":[ /* called when player uses item when status effect is selected */ ], "onSelect":[ /* called when player selects status effect */ ], "onDeselect":[ /* called when player selects a different status effect, deselecting this one */ ], "onExecute":[ /* called when charge hits required amount */ ], "onPlayerHit":[ /* called when player is hit but does not die */ ], }, |
Icon
Aux Text
The auxText
is the little number on the upper right corner of a status icon.
Generally it indicates the level (quantity) of an item, but it could potentially be used as a countdown timer, show the number of enemies around you, things like that.
1 2 3 4 | { "auxText": "${level > 1 ? level.ToString() : ''}", "auxTextColor": "#707c7f", } |
Category
The category
of a status effect just affects the colors of its icon background.
1 2 3 | { "category": "categories.offensive", } |
You can define a new category wherever you want.
1 2 3 4 5 6 | "category": ".red", "red": { "color1":"color(1f, 0f, 0f) * 1.5f", "color2":"color(1f, 0f, 0f) * 0.1f", }, |
Tip
If you want to replace a powerup with your own tweaked version, you can simply copy it to the same relative path and edit it, and your edited version will be loaded instead of the original.
For example, status/repel
is the path of the original. Placing your edited version at your_campaign_folder/status/repel
will cause your version of the powerup to override the original.
Name & Description
1 2 3 4 | { "displayName":"Shield", "description":"Prevent death ${level} ${level > 1 ? 'times' : 'time'}", } |
Indicator Bullet
The items in chippy each show a different visual indicator on your ship while you have them selected.
The onSelect
and onDeselect
handlers are used to accomplish this.
1 2 3 4 5 6 7 8 9 10 11 12 | { "onSelect": [ { "action": "CallMethod", "method": "DespawnAddedBullets", }, { "action": "CallMethod", "method": "AddBullet", "params": { "path": ".effectBullet", "pos":"playerPos", "level":"level", }}, { "action": "CallMethod", "target": "stage", "method": "PlaySfx", "params": { "sfxType":"PowerupSlowmoSelect", "pos":"playerPos", }}, ], "onDeselect": [ { "action": "CallMethod", "method": "DespawnAddedBullets", }, ], } |
Custom Variables
Much like other json object types, status effects can declare custom properties.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { "properties": { "aimer": { "type": "Bullet" }, "aimer2": { "type": "Bullet" }, }, "onSelect": [ { "action": "CallMethod", "method": "DespawnAddedBullets", }, { "action": "CallMethod", "method": "AddBullet", "params": { "path": ".aimer", "pos": "stage.IsRaycastHit(playerGunPos, playerGunPos + playerGunDir * 60f) ? stage.Raycast(playerGunPos, playerGunPos + playerGunDir * 60f) : playerGunPos + playerGunDir * 8f", "level":"level", }, "return": "aimer" }, { "action": "CallMethod", "method": "AddBullet", "params": { "path": ".aimer2", "pos": "playerPos", "level":"level", }, "return": "aimer2" }, { "action": "CallMethod", "target": "stage", "method": "PlaySfx", "params": { "sfxType":"PowerupCannonSelect", "pos":"playerPos", }}, ], "onDeselect": [ { "action": "CallMethod", "method": "DespawnAddedBullets", }, ], "onUpdate": [ { "action": "Condition", "condition": "isSelected && aimer2 != null && aimer != null", "true": [ { "action": "CallMethod", "target": "aimer2", "method": "SetVectorVar", "params": { "var":"aimer.Position - playerPos", }}, ],}, ], } |
Script Parameters
These parameters can be used inside any scriptfunc by a Status Effect.
Info
Debugging
debugVector
: draws a 2d vector from the player's position
debugText
: displays a string above the player's position (use ${NAME}
for properties)