Skip to content

Instantly share code, notes, and snippets.

@LaughingLeader
Last active March 25, 2020 11:54
Show Gist options
  • Save LaughingLeader/018f044cadd2de1e4aa71dc9f5936c0e to your computer and use it in GitHub Desktop.
Save LaughingLeader/018f044cadd2de1e4aa71dc9f5936c0e to your computer and use it in GitHub Desktop.
A code snippet for making a status stack with story scripting, for Divinity: Original Sin 2 Classic and Definitive Edition.
Version 1
SubGoalCombiner SGC_AND
INITSECTION
MyMod_StackingStatuses_InitSettings();
KBSECTION
//REGION SETTINGS_INITIALIZING
PROC
MyMod_StackingStatuses_InitSettings()
THEN
// We clear any previously stored data to support older saves, for if you end up changing your stacking statuses.
MyMod_StackingStatuses_ClearRegistered("HASTED");
/* Stacking status registration.
Params:
1 - The status that gets applied to increase the stack.
2 - The stacking status that gets applied when the stack increases.
3 - (Optional) The duration of the stacking status. If omitted, -1.0 is used for a permanent status.
*/
MyMod_StackingStatuses_Register_Stack("HASTED", "FORTIFIED", 12.0);
MyMod_StackingStatuses_Register_Stack("HASTED", "MAGIC_SHELL", 12.0);
MyMod_StackingStatuses_Register_Stack("HASTED", "HOLY_FIRE", 12.0);
MyMod_StackingStatuses_Register_Stack("HASTED", "INF_POWER", 12.0);
/*
To test these placeholder statuses, simply open the ReCon with F11 in the editor,
then enter statusapply HASTED 0 in the console.
*/
//END_REGION
//REGION REGISTRATION
/* Set the initial stack index to 0 if it's never been set for this applying status. */
PROC
MyMod_StackingStatuses_Register_Stack((STRING)_ApplyStatus, (STRING)_StackingStatus, (REAL)_Duration)
AND
NOT DB_MyMod_StackingStatuses_Count(_ApplyStatus, _)
THEN
DB_MyMod_StackingStatuses_Count(_ApplyStatus, 0);
/* Register the status with an index, so it can be used later in status applying rules. */
PROC
MyMod_StackingStatuses_Register_Stack((STRING)_ApplyStatus, (STRING)_StackingStatus, (REAL)_Duration)
AND
DB_MyMod_StackingStatuses_Count(_ApplyStatus, _StackNumber)
AND
IntegerSum(_StackNumber, 1, _NextStackNumber)
THEN
DB_MyMod_StackingStatuses_Stacks(_ApplyStatus, _StackNumber, _StackingStatus, _Duration);
NOT DB_MyMod_StackingStatuses_Count(_ApplyStatus, _StackNumber);
DB_MyMod_StackingStatuses_Count(_ApplyStatus, _NextStackNumber);
/* The default duration if not set is -1.0. */
PROC
MyMod_StackingStatuses_Register_Stack((STRING)_ApplyStatus, (STRING)_StackingStatus)
THEN
MyMod_StackingStatuses_Register_Stack(_ApplyStatus, _StackingStatus, -1.0);
/* This proc is for clearing stored status settings data, for if/when you change stacks, names, durations, etc.
This data needs to be updated in older saves that used your mod. */
PROC
MyMod_StackingStatuses_ClearRegistered((STRING)_ApplyStatus)
AND
DB_MyMod_StackingStatuses_Count(_ApplyStatus, _StackNumber)
THEN
NOT DB_MyMod_StackingStatuses_Count(_ApplyStatus, _StackNumber);
PROC
MyMod_StackingStatuses_ClearRegistered((STRING)_ApplyStatus)
AND
DB_MyMod_StackingStatuses_Stacks(_ApplyStatus, _StackNumber, _StackingStatus, _Duration)
THEN
NOT DB_MyMod_StackingStatuses_Stacks(_ApplyStatus, _StackNumber, _StackingStatus, _Duration);
//END_REGION
//REGION DEBUG
PROC
MyMod_DebugMessage((STRING)_Message, (INTEGER)_StackNumber, (STRING)_Status)
AND
IntegertoString(_StackNumber, _StackNumStr)
AND
StringConcatenate("(", _StackNumStr, _StrA)
AND
StringConcatenate(_StrA, ") ", _StrB)
AND
StringConcatenate(_StrB, _Status, _StatusInfoStr)
AND
StringConcatenate(_Message, _StatusInfoStr, _DebugMessage)
THEN
DebugBreak(_DebugMessage);
//END_REGION
//REGION CLEAR_DATA
/* Procedures are custom script-defined rules that can be called in the THEN section.
They fully complete before the next line in the rule where they're called.
Here we're clearing these temporary databases since we only use these for if/else conditions in our rules.
*/
PROC
MyMod_StackingStatuses_ClearData((CHARACTERGUID)_Character, (STRING)_ApplyStatus)
AND
DB_MyMod_StackingStatuses_Temp_ActiveStack(_Character, _ApplyStatus, _StackNumber, _StackingStatus)
THEN
NOT DB_MyMod_StackingStatuses_Temp_ActiveStack(_Character, _ApplyStatus, _StackNumber, _StackingStatus);
PROC
MyMod_StackingStatuses_ClearData((CHARACTERGUID)_Character, (STRING)_ApplyStatus)
AND
DB_MyMod_StackingStatuses_Temp_StackChanged(_Character, _ApplyStatus, _StackingStatus)
THEN
NOT DB_MyMod_StackingStatuses_Temp_StackChanged(_Character, _ApplyStatus, _StackingStatus);
//END_REGION
//REGION QUERIES
/* Queries are custom script-defined rules.
If the query reaches the THEN section, the condition is "true".
They fully complete before the next line in the rule where they're called.
This query is for checking if a character has a stacking status, for future use.
*/
QRY
MyMod_StackingStatuses_QRY_HasStackingStatus((CHARACTERGUID)_Character, (STRING)_ApplyStatus)
AND
DB_MyMod_StackingStatuses_Stacks(_ApplyStatus, _StackNumber, _StackingStatus, _Duration)
AND
HasActiveStatus(_Character, _StackingStatus, 1)
THEN
DB_NOOP(1);
//END_REGION
//REGION STACK_STATUS_LOGIC
/* Here we're checking for the current stacking status, if any, to determine where we are in the stack count. */
PROC
MyMod_StackingStatuses_OnApplyStatus((CHARACTERGUID)_Character, (STRING)_ApplyStatus, (GUIDSTRING)_Source)
AND
DB_MyMod_StackingStatuses_Stacks(_ApplyStatus, _StackNumber, _StackingStatus, _Duration)
AND
HasActiveStatus(_Character, _StackingStatus, 1)
THEN
MyMod_StackingStatuses_ClearData(_Character, _ApplyStatus); // In case statuses from previous stacks are active.
DB_MyMod_StackingStatuses_Temp_ActiveStack(_Character, _ApplyStatus, _StackNumber, _StackingStatus);
/* If no stacking status is found for the applying status, we start at stack 0.
DB_MyMod_StackingStatuses_Temp_StackChanged is used to prevent the next rule, so we only increase the stack one at a time.
*/
PROC
MyMod_StackingStatuses_OnApplyStatus((CHARACTERGUID)_Character, (STRING)_ApplyStatus, (GUIDSTRING)_Source)
AND
NOT DB_MyMod_StackingStatuses_Temp_StackChanged(_Character, _ApplyStatus, _)
AND
NOT DB_MyMod_StackingStatuses_Temp_ActiveStack(_Character, _ApplyStatus, _, _)
AND
DB_MyMod_StackingStatuses_Stacks(_ApplyStatus, 0, _StackingStatus, _Duration)
THEN
DB_MyMod_StackingStatuses_Temp_StackChanged(_Character, _ApplyStatus, _StackingStatus);
ApplyStatus(_Character, _StackingStatus, _Duration, 1, _Source);
MyMod_DebugMessage("[MyMod:CharacterStatusApplied] Applying first status in stack: ", 0, _StackingStatus);
/* If a stacking status is found, we increase the stack count and get the next status to apply, if any. */
PROC
MyMod_StackingStatuses_OnApplyStatus((CHARACTERGUID)_Character, (STRING)_ApplyStatus, (GUIDSTRING)_Source)
AND
NOT DB_MyMod_StackingStatuses_Temp_StackChanged(_Character, _ApplyStatus, _)
AND
DB_MyMod_StackingStatuses_Temp_ActiveStack(_Character, _ApplyStatus, _StackNumber, _CurrentStackingStatus)
AND
IntegerSum(_StackNumber, 1, _NextStackNumber)
AND
DB_MyMod_StackingStatuses_Stacks(_ApplyStatus, _NextStackNumber, _StackingStatus, _Duration)
THEN
DB_MyMod_StackingStatuses_Temp_StackChanged(_Character, _ApplyStatus, _StackingStatus);
ApplyStatus(_Character, _StackingStatus, _Duration, 1, _Source);
MyMod_DebugMessage("[MyMod:CharacterStatusApplied] Increasing stack and applying status: ", _NextStackNumber, _StackingStatus);
/* Finally we clear DB_MyMod_StackingStatuses_Temp_ActiveStack and DB_MyMod_StackingStatuses_Temp_StackChanged. */
PROC
MyMod_StackingStatuses_OnApplyStatus((CHARACTERGUID)_Character, (STRING)_ApplyStatus, (GUIDSTRING)_Source)
THEN
MyMod_StackingStatuses_ClearData(_Character, _ApplyStatus);
//END_REGION
//REGION APPLY_STATUS_EVENTS
/* We listen for specific statuses here, instead of a generic status variable,
since hidden status are constantly applied while the game is running.
HIT, INSURFACE, aura statuses, etc. are always happening, so avoiding generic status events rules is a great way to avoid log spam / unnecessary rules from running.
For your actual statuses, simply replace HASTED with the status you apply to increase the stack, i.e. MYMOD_MISERY_APPLY
*/
IF
CharacterStatusApplied(_Character, "HASTED", _Source)
THEN
MyMod_StackingStatuses_OnApplyStatus(_Character, "HASTED", _Source);
//END_REGION
EXITSECTION
ENDEXITSECTION
ParentTargetEdge "__Start"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment