Setup
Add sVisual as a dependency by adding it to the requiredAddons inside your
config.cpp
class CfgPatches {
class NAME_OF_YOUR_MOD {
requiredAddons[] = {
"sVisual"
};
};
};
If you don't plan to use sVisual, you could just specify sFramework as
requiredAddons.
Defining an effect
sVisual currently supports 3 types of effect:
SPPEffectSPPEffectAnimatedSPPEffectTimed
Use a SPPEffect if you want to define a normal effect
class MyStaticEffect : SPPEffect {
override void onInit() {
setVignetteIntensity(0.69);
setVignetteColor(SColor.rgb(RGBColors.BLACK)); // SColor: https://simonvic.github.io/sUDE/tutorials/9
//...
}
}
Use a SPPEffectAnimated if you want to define an animated effect which will be
animated until explicitly deactivated
class MyAnimatedEffect : SPPEffectAnimated {
override void onInit() {
// set vignette color to red
setVignetteColor(SColor.rgb(RGBColors.RED));
}
override void onAnimate(float deltaTime) {
// we set the vignette intensity to follow a Sine function as the time passes
setVignetteIntensity(Math.Sin(getTime()));
}
}
TheonInitmethod gets called only once when the effect gets initialized, while theonAnimatemethod gets called every frame. Choose wisely what to put insideonAnimate
Use a SPPEffectTimed if you want to define an animated effect which will be
animated but must terminate after a certain amount of time
class MyTimedEffect : SPPEffectTimed {
override void onInit() {
setDuration(5.0); // 5 seconds
setOverlayColor(SColor.rgb(RGBColors.GREEN));
}
override void onAnimate(float deltaTime) {
setOverlayFactor(Math.Sin(getTime()));
}
}
Register the effect
You've defined your effect. Before being able to use and activate it, you need to
register its classname into the PPERequesterBank, which holds the
definitions of all PPEffects.
modded class PPERequesterRegistrations {
void PPERequesterRegistrations() {
PPERequesterBank.RegisterRequester(MyStaticEffect);
PPERequesterBank.RegisterRequester(MyAnimatedEffect);
PPERequesterBank.RegisterRequester(MyTimedEffect);
}
}
Using the effect
We can now retrieve the effect from the bank and use it.
Let's say we want to activate our effects when the player jumps.
modded class PlayerBase {
MyStaticEffect myStaticEffect;
MyAnimatedEffect myAnimatedEffect;
MyTimedEffect myTimedEffect;
void PlayerBase() {
Class.CastTo(myStaticEffect, PPERequesterBank.GetRequester(MyStaticEffect));
Class.CastTo(myAnimatedEffect, PPERequesterBank.GetRequester(MyAnimatedEffect));
Class.CastTo(myTimedEffect, PPERequesterBank.GetRequester(MyTimedEffect));
}
override void OnJumpStart(){
super.OnJumpStart();
myStaticEffect.activate();
myAnimatedEffect.activate();
myTimedEffect.activate();
}
}
You have access to some other methods, such as
myStaticEffect.isActive(); // returns true if active, false otherwise
myStaticEffect.deactivate(); // deactivates the effect
myStaticEffect.toggle(); // toggle between activated and deactivated
Animated (and timed) effects have some more methods:
myAnimatedEffect.start(); // start the animation from the beginning
myAnimatedEffect.pause(); // pause the animation
myAnimatedEffect.resume(); // resume the animation from the paused state
myAnimatedEffect.stop();
myAnimatedEffect.getTime(); // returns the time (seconds) that the animation has been playing for
myAnimatedEffect.isPlaying();
myAnimatedEffect.isPaused();
myAnimatedEffect.hasStopped();
Timed effects have some more methods related to timing:
myAnimatedEffect.getDuration(); // returns duration in seconds
myAnimatedEffect.getRemaining(); // returns how many seconds left to deactivation
Advanced definition
Normalization
Some effect could accept values in the -1,1 range, some other in the -2,2 range, while
some other in the 0,1000 range.
To avoid having to deal with these ranges, you can specify to use a normalized
value in the range of 0.00,1.00, where 0.00 is the minimum (0%) and 1.00 is the maximum
(100%)
class SomeEffect : SPPEffect {
override void onInit() {
normalized(true);
setOverlayFactor(0.50); // 50%
}
}
By default, normalization is set to false for backward compatibility reasons.
I highly recommend using normalization.
If you're interested in the actual value ranges, you can find them in game scripts.
Priority and Operator
You may be wondering what would happen when two different PPEffects are active at the
same time, and they both set the same effect parameter (e.g. vignette intensity,
chromatic aberration, radial blur etc.) to different values.
Each parameter you set in your PPEffect can be seen as a layer (like on Photoshop).
These "layers" (parameters) are put on top of each other, and they will interact with
the underlying (active) layer.
Which PPEffect takes precendence and how it interacts with other PPEffects is up to you
to define via two parameters:
- Priority: defines the order of the layer.
Higher priority, means it will be on top of those with lower priority
- Operator: defines the way it will interact with the underlying layer
The "first layer", the one at the bottom of the stack, is the default one defined by DayZ itself.
| Priority | Operator | Value | |
|---|---|---|---|
| default | 0 | SET | 0 |
Let's see a practical example with code
For the tutorial sake, I chose low priorities; it's advised to choose higher priorities value (e.g. 100, 200, 500) so that it will be easier to interoperate with other mods.
-
Let's pretend the player got hurt; we activate a
PainEffect
ThePainEffectwillADD0.70to the current vignette intensity.class PainEffect : SPPEffect { override void onInit() { normalized(true); priority(1); op(PPOperators.ADD); setVignetteIntensity(0.70); } }Priority Operator Value final result 0.70 PainEffect 1 ADD 0.70 default 0 SET 0 -
Now the player assumed a pain killer and we activate a
PainKillerEffect.
ThePainKillerEffectwillSUBTRACT0.30from the vignette intensity.class PainKillerEffect : SPPEffect { override void onInit() { normalized(true); priority(2); op(PPOperators.SUBSTRACT); setVignetteIntensity(0.30); } }Priority Operator Value final result 0.40 PainKillerEffect 2 SUBTRACT 0.30 PainEffect 1 ADD 0.70 default 0 SET 0 -
Now the player got inside a bunker and it's dark; we activate a
DarknessEffect.
TheDarknessEffectwillMULTIPLYby2.0
class DarknessEffect : SPPEffect { override void onInit() { normalized(true); priority(3); op(PPOperators.MULTIPLICATION); setVignetteIntensity(2); } }Priority Operator Value final result 0.80 DarknessEffect 3 MULTIPLICATIVE 2 PainKillerEffect 2 SUBTRACT 0.30 PainEffect 1 ADD 0.70 default 0 SET 0 -
Now pain killer effectiveness has vanished (but the player is still in pain and in the bunker).
So we deactivate thePainKillerEffectPriority Operator Value final result 1.40 DarknessEffect 3 MULTIPLICATIVE 2 PainEffect 1 ADD 0.70 default 0 SET 0 -
The player is no longer in pain.
We deactivate thePainEffectPriority Operator Value final result 0.00 DarknessEffect 3 MULTIPLICATIVE 2 default 0 SET 0 Currently the
DarknessEffectis not affecting the vignette intensity at all; that's because of its operator (2 * 0 = 0).
As you can see, the priority and the operator play a major role in definining how the final resul will be.
Be mindful when choosing them, as they could affect other mods too.
For backward compatibility reasons, the default priority is 1000 and the default operator is SET if they're not specified.
If you're upgrading your mod, it's highly recommended to choose the appropriate priority and operator for your PPEffects.
Operator types
Not every operator is applicable to all parameters type.
Some may work only for color parameters or for float parameters etc.
ADDLinear addition between the current value and the value you set.
ADD_RELATIVELinear addition between the current value and the value you set, but it's relative to difference between current and the max, where applicable. Otherwise it will be a normal addition
SUBTRACTLinear subtraction. Subtract the value you set from the current value.
SUBTRACT_RELATIVELinear subtraction. Subtract the value you set from the current value, but it's relative to difference between current and the min, where applicable. Otherwise it will be a normal subtraction
SUBTRACT_REVERSELinear subtraction. Subtract the current value from the value you set
SUBTRACT_REVERSE_RELATIVELinear subtraction. Subtract the current value from the value you set, but it's relative to difference between current and the min, where applicable. Otherwise it will be a normal subtraction
MULTIPLICATIVELinear multiplication between the current value the the value you set
HIGHESTOnly the highest betweem the current value and the value you set
LOWESTOnly the lowest betweem the current value and the value you set
SETIt ignores underlying layers and will set the value you specified
Unless strictly required, other operators are recommended, since this could possibly "hide" other effects
OVERRIDEIt ignores all other layers and set the value you specified
Highly discouraged; use less destructive operators.
Multiple parameters in the same PPEffect
A PPEffect can "request" multiple parameters at the same time.
You're free to set a different priority and a different operator for each parameter,
since each parameter will "affect its own stack of layers".
Altough most of the time it's recommended to use the same for the sake of simplicity.
class Effect_A : SPPEffect {
override void onInit() {
normalized(true);
priority(1);
op(PPOperators.ADD);
setVignetteIntensity(0.50);
priority(420);
op(PPOperators.MULTIPLICATIVE);
setOverlayFactor(2.0);
}
}
class Effect_B : SPPEffect {
override void onInit() {
normalized(true);
priority(69);
op(PPOperators.SUBTRACT);
setVignetteIntensity(0.20);
priority(1);
op(PPOperators.ADD);
setOverlayFactor(0.40);
}
}
| (vignette) | Priority | Operator | Value |
|---|---|---|---|
| final result | 0.30 | ||
| Effect_B | 69 | SUBTRACT | 0.20 |
| Effect_A | 1 | ADD | 0.50 |
| default | 0 | SET | 0 |
| (overlay) | Priority | Operator | Value |
|---|---|---|---|
| final result | 0.80 | ||
| Effect_A | 420 | MULTIPLICATIVE | 2.00 |
| Effect_B | 1 | ADD | 0.40 |
| default | 0 | SET | 0 |
Effects intensity option
Some players may enjoy more intense effects for immersion, while some other may find
them too distracting.
With sVisual, the players can change an option to specify their preferred "effects
intensity".
You can get the player preference by invoking the getEffectsIntensity()
method, which will return a value between 0 and 2 (inclusive)
How this value will affect your effects it's up to you; you may want a specific effect to scale differently based on the player preference.
As a rule of thumb:
- An effect intensity value of 0, means that the player want the least possible effects on the screen
- Effect intensity of 1 is the default
- An effect intensity of 2, means the player like very strong effects
This method is only available if you're using sVisual; so make sure to have specified
sVisual in the requiredAddons
Let's see an example
class PainEffect : SPPEffect {
override void onInit() {
normalized(true);
priority(1);
op(PPOperators.ADD);
setVignetteIntensity(0.20 * getEffectsIntensity());
}
}