Effect Tutorial: Difference between revisions

From Gothongs Wiki
Jump to navigationJump to search
Panda (talk | contribs)
Panda (talk | contribs)
No edit summary
 
(One intermediate revision by the same user not shown)
Line 266: Line 266:
|0x40
|0x40
|Run as an area effect. Max targets will not work with this.
|Run as an area effect. Max targets will not work with this.
|}
=== Event flags ===
{| class="wikitable"
|+
!Name
!Value
!Description
|-
|FXEVT$PF_OVERRIDE_PROC_BLOCK
|0x2
|This event is still allowed to trigger when the fx$F_NO_PROCS effect flag is active on the player.
|}
|}


Line 351: Line 363:
);
);
</pre>
</pre>
[[Category:Tutorials]]

Latest revision as of 14:50, 29 July 2023

Effects (FX) are the backbone of the game. They are the buffs that you see on your HUD and also used by direct damage and things behind the scenes like cutscenes.

Relevant scripts:

Script Description
_lib_fx.lsl Stores all the effect types and explains the effect types. Also stores a list of default values for passive effects (not to be confused with the passives system which is different). Also conditions and tags.
classes/got FX.lsl Has the methods, macros, and building tools for making effects.
classes/got FXCompiler.lsl Compiles effects into cached values and triggers LSL and RLV functions when effects are added or removed.

The structure of an effect

The effect data is a JSON array with the following spect:

  • (array) wrapper. An all or nothing container of multiple effect packages and stacks of packages.
    • (int) wrapper_flags - WF_* flags. See below.
    • (int) min_packages - Minimum packages to apply (all or nothing).
    • (int) max_packages - Max packages to apply (applies the N first viable packages). Use 0 for ALL.
    • (...strided) (int) package_stacks, (array) package - After max_packages the remaining elements are two-strided with nr stacks and the package to add said stacks of. Anything below 1 becomes 1.
      • (float) Package duration - Duration to apply the package
      • (int) Package flags - PF_* flags. See below.
      • (str) Package name - Name of the package (unique). If the effect has a 0 duration you can use "" or 0 because it is only used in duration effects.
      • (array) Effects - An array of FX arrays
        • (int) Effect type - An effect integer from _lib_fx.lsl
        • ...effect data - ...followed by data based on that effect.
      • (array) Conditions - An array of condition arrays
        • (int) Type of condition - Condition identifier from _lib_fx.lsl
        • ...condition data - Data based on the condition identifier.
      • (array) Events - An array of effect arrays.
        • (int) event_type - An event type. You can use any relevant event from any of the header files in got/classes.lsl
        • (str) event_script - The name of the script that raised the event. If the event was raised by got FX.lsl then use "" instead.
        • (int) targ_flags - A TARG_* flag. See below.
        • (int) max_targets - Max nr of targets to apply to. Not very useful. Leave at 0 for all viable.
        • (array) wrapper (nested wrapper) - The wrapper to apply when the effect is raised. This is a nested wrapper.
        • (array) event_params - An array of values that must match the event values. See below.
        • (float) proc_chance - Adds a random chance that the event is raised. Between 0 (no chance) and 1 (100%).
        • (int) event_flags - Event flags. See below.
        • (float) max_range - Max range of event target from the victim of the package. In whole meters.
        • (float) cooldown - Cooldown between procing the event.
      • (array) tags - An array of fx$TAG_* constants from _lib_fx.lsl
      • (int) min_conditions - Minimum conditions that must be met for the package to apply.
      • (int) max_stacks - Max stacks that this package can have.
      • (float) tick - When set to anything above 0 it will trigger all the effects this often. In whole seconds.

Here is a JSON encoded version of the above:

[
	(int)wrapper_flags,
	(int)min_packages,
	(int)max_packages,
	(int)stacks_package0,
	[
		(float)package_duration,
		(int)package_flags,
		(str)package_name,
		[
			[
				(int)effect_type,
				(var)effect_data0,
				...
			]
			...
		],
		[
			[
				(int)condition_type,
				(var)condition_data0,
				...
			]
			...
		],
		[
			[
				(int)event_type,
				(str)event_script,
				(int)targ_flags,
				(int)max_targets,
				(arr)wrapper,
				(arr)event_params,
				(float)proc_chance,
				(int)event_flags,
				(float)max_range,
				(float)cooldown
			],
			...
		],
		[
			(int)tag0,
			...
		],
		(int)min_conditions,
		(int)max_stacks,
		(float)tick
	],
	(int)stacks_package1,
	(arr)package1
	...
]

Wrapper flags

Flag Value Description
WF_DETRIMENTAL 0x1 Causes NPCs to become hostile when cast on and players to enter combat when cast on. By default blocked on defeat/grapple/invul.
WF_ALLOW_WHEN_DEAD 0x2 Allows this wrapper to be used when target is defeated.
WF_ALLOW_WHEN_QUICKRAPE 0x4 Allows this wrapper to be used when target is grappled.
WF_NO_DODGE 0x8 Cannot be dodged (only detrimental can be dodged).
WF_ALLOW_WHEN_RAPED 0x10 Allow while player is in a monster scene.
WF_REQUIRE_LOS 0x20 Requires sender to have line of sight to target. Useful for AoE.
WF_ENEMY_ONLY 0x40 Wrapper is ignored unless target has a different team than sender. By default player team is 1 and NPC team is 0. Any team that is not the same as yours is considered hostile.


Package

A package is a collection of effects, conditions and events. Packages can be instant or happen over time. A package that happens over time typically has an icon that shows on your HUD below the resource bars.

A wrapper can apply multiple packages, and a package can contain multiple effects.

Package flags:

Flag Value Description
PF_DETRIMENTAL 0x1 Sets package as detrimental. Receiving a detrimental package activates the combat timer. Sending a detrimental package to an NPC will make it attack you. Invulnerability block receiving detrimental packages.
PF_CANNIBALIZE 0x2 If a package with the same name already exists, replace it with this one and add its stacks. Default behavior is to keep the original wrapper and add the incoming package's stacks because it is faster.
PF_EVENT_ON_OVERWRITE 0x4 Raises the INTEVENT_ON_REMOVE event when PF_CANNIBALIZE is set and a spell is overwritten.
PF_ALLOW_WHEN_DEAD 0x8 By default a player is not allowed to receive ANY packages when defeated. This flag overrides that. Useful for resurrect.
PF_ALLOW_WHEN_QUICKRAPE 0x10 By default when caught on a trap or grapple, NPCs cannot apply packages to you. This overrides that.
PF_NO_STACK_MULTIPLY 0x20 Many effect values are multiplied by nr of stacks of a package a player has. This prevents that multiplication.
PF_FULL_UNIQUE 0x40 By default, packages are unique by name and by sender. This makes them only unique by name. When set you may only have one package active with this name no matter how many senders.
PF_TRIGGER_IMMEDIATE 0x80 By default the non-passive effects (like damage) are only triggered when a package with a duration "ticks". Setting this will make it tick instantly when the package is added also. This flag is used a lot.
PF_NO_DISPEL 0x100 Prevents the package from being dispelled.
PF_STACK_TIME 0x200 When a package with the same name is received, it adds that package's duration instead of its stacks. Tank mitigation abilities usually use this.
PF_FULL_VIS 0x400 By default you may only see your own spells on the target bar. This forces the spell icon to show up no matter who cast it.

Effects

Effects tell the HUD what do to. Such as add HP or play an animation. Each effect is an array where the first value is the effect ID (see _lib_fx.lsl for a list of all effects and what they do) and is followed by any data values relevant to the effect ID.

Examples:

[1,10] // Deal 10 damage
[7,"sit",1] // Start the sitting animation

Conditions

Conditions use a similar syntax to effects. The first value is a condition ID (outlined in _lib_fx.lsl). It may be followed by additional values based on the condition type.

Example:

[0,1] // Only apply the package if the target is not on the player team
[12,4] // Only apply the package if the target has breasts

Events

The event system is advanced. It allows you to apply wrappers when something happens based on XOBJ events that are raised. We can explain it by using an example of an event array. This event will deal 3 damage to your target when you finish casing spell 4 but only if spell 4 is detrimental. Note: In LSL you need to escape the nested JSON array with llList2Json.

[
	SpellManEvt$complete,	// Event that we are listening for
	"got SpellMan",		// Script that raised that event
	"<1>",			// Target to apply the wrapper to. <1> = event value at index 1 (target of spell)
	0,			// Max target (0 = ALL)	[0,0,0,0,[0,1,0,1,10]],	// Wrapper that deals 10 damage directly
	[
		4,		// First value of event (spell index) must be 4 (spell 4). Note that spell 5 is index 0.
		"",		// Ignore the second event value by using ""
		1		// Third value of event (deterimental) must be 1.
	],
	1.0,			// Proc chance. 1 = 100%
	0,			// No flags
	0,			// Range (0 = unlimited)
	5			// Cooldown (5 seconds) 
]

TARG_* target constants

Name Value Description
TARG_CASTER 0x1 Target the player that applied the package.
TARG_VICTIM 0x2 Victim of the package (the person who has the package that the event is attached to)
TARG_PC 0x4 Not used in events
TARG_NPC 0x8 Not used in events
TARG_DISPELLER 0x10 Only used in dispel events. The player that dispelled the package that the event was attached to.
TARG_REQUIRE_NO_FACING 0x20 Not used in events
TARG_AOE 0x40 Run as an area effect. Max targets will not work with this.

Event flags

Name Value Description
FXEVT$PF_OVERRIDE_PROC_BLOCK 0x2 This event is still allowed to trigger when the fx$F_NO_PROCS effect flag is active on the player.

Tags

Tags are an array of tag constants (see _lib_fx.lsl). They only contain metadata. The only important one is the fx$TAG_ACTIVE_MITIGATION for tanks.

Examples

It is recommended that you use the FX_build* functions to create your wrappers while you are new to this. Here are some examples:

Wrapper that deals 10 damage to the recipient and triggers the take hit animation and sound:

string wrapper = FX_buildWrapper(
    WF_DETRIMENTAL, // Flags
    0, // Min packages (ANY)
    0, // Max package (ALL)
    [
        0,  // Stacks. Anything below 1 will become 1
        FX_buildPackage( 
            0, // No duration. Fire and forget.
            PF_DETRIMENTAL, // Flags
            "", // Name of package. Not usually needed when package is instant.
            [ // FX arrays
                FX_buildFX(fx$DAMAGE_DURABILITY, [10]), // Do 10 HP damage
                FX_buildFX(fx$HITFX, [ // Trigger the take hit animation and sound
                    fxhfColor$phys, // Color the thong briefly to indicate damage
                    fxhfFlag$PAIN_HEAVY // Flags for RP addons
                ])
            ], 
            [], // Conditions: None used
            [], // Events: None used
            [], // Tags: none used
            0, // Minimum conditions needed
            0, // Max stacks: Not used
            0 // Ticking: Not used
        )
    ]
);

// Method to send a wrapper to a player or NPC
FX$send(
    llGetOwner(),   // Target of wrapper
    llGetKey(),     // Sender of wrapper
    wrapper,        // Wrapper
    TEAM_NPC        // Team of sender
);

Add a duration effect for 10 seconds that increases haste by 10% per stack.

string wrapper = FX_buildWrapper(
    0, // Flags
    0, // Min packages (ANY)
    0, // Max package (ALL)
    [
        0,  // Stacks. Anything below 1 will become 1
        FX_buildPackage( 
            10, // Last 10 seconds.
            0, // Flags
            "testBuff", // Name of package. Unique by sender and name.
            [ // FX arrays
                FX_buildFX(fx$CASTTIME_MULTI, [-0.1]), // Multiply cast time by 0.9 (1-0.1)
                FX_buildFX(fx$COOLDOWN_MULTI, [-0.1]), // Multiply cooldown time by 0.9 (1-0.1)
                FX_buildFX(fx$ICON, [ // Add an icon to the HUD
                    "5dc76285-eabe-9f08-fb7e-70f40ea1db2e", // Icon UUID
                    "Haste increased by 25%" // Click description
                ])
            ],
            [], // Conditions: None used
            [], // Events: None used
            [], // Tags: none used
            0, // Minimum conditions needed
            3, // Max stacks 3
            0 // Ticking: Not used
        )
    ]
);

// Method to send a wrapper to a player or NPC
FX$send(
    llGetOwner(),   // Target of wrapper
    llGetKey(),     // Sender of wrapper
    wrapper,        // Wrapper
    TEAM_NPC        // Team of sender
);