Jump to content
Sign in to follow this  
DavidW

Enhanced ALTER_EFFECT functions

Recommended Posts

For various reasons I've been doing some coding recently where it's been convenient not to rely on SCS's function library, but to use the core WEIDU functions instead. In particular, I've been using ADD_[SPELL/ITEM]_EFFECT and [ALTER/CLONE/DELETE]_EFFECT. They're very nice but I found myself needing slightly more functionality, so I worked up a slightly modified version. They're available on the SCS repo in stratagems/lib/alter_effect.tpa.

There are four sets of changes, which I'll detail below.

Share this post


Link to post

1. flag matching and setting

Effects have flag data at 0x24-0x27 (the saving throw field) and 0x2c-0x2f (the 'special' field). The WEIDU functions only allow you to match or write these fields as LONG entries. My version gives you access to most of the main flags. Specifically, it defines the following variables:

	save_vs_spell
	save_vs_breath
	save_vs_poison
	save_vs_wand
	save_vs_polymorph
	ignore_primary
	ignore_secondary
	bypass_mirror_image
	ignore_difficulty
	drain_hp_to_caster
	transfer_hp_to_target
	fist_damage_only
	drain_to_max_hp
	suppress_feedback
	save_for_half
	made_save
	does_not_wake
	

along with the associated match_ variables (e.g., match_ignore_secondary, match_save_vs_spell).

Share this post


Link to post

2. Subfields of parameter2.

Certain opcodes (notably opcode 12, 'damage') split the parameter2 field into two subfields: each is a SHORT, located respectively at 0x8 and 0xa. My version lets you write to and match on these separately, via the variables 

	parameter2a
	parameter2b
	match_parameter2a
	match_parameter2b
	

Share this post


Link to post

3. Negative values of parameter1 and parameter2

This is minor - but for implementation reasons, in the original WEIDU versions of the functions, parameter1 and parameter2 have to take nonnegative values (otherwise they are ignored). My version lets them take negative values between -9 and -1. (The main application is if a parameter represents a string and you want to set it to -1.)

Share this post


Link to post

4. Function matching and patching

This one is very much for advanced users only! (If you're not happy defining your own functions, ignore this bit of the post.) It introduces two new STR variables:

	function (only for CLONE_EFFECT/ALTER_EFFECT)
	match_function (only for CLONE_EFFECT/ALTER_EFFECT/DELETE_EFFECT)
	

Each should be set to the name of a PATCH_FUNCTION that expects to execute on a length-0x30 file with the structure of an EFFv1. The match_function should have one return value, 'value', which can be equal to either 0 or 1. If match_function is set, the function is executed on each EFF block, and then the CLONE/ALTER/DELETE is performed on each block for which the function returns value=1. When it is executed, if function is set then that function is executed on the cloned or altered block.

This is easiest to illustrate through examples. Firstly, suppose you want to delete all damage-resistance effects (that is, all opcodes in the ranges 27-31 and 84-89). Of course you could do it with 11 DELETE_EFFECTs, but that's tedious to type and inefficient to execute if you're applying it to many items (which, ok, is unlikely in this case, but there are more realistic cases). You can do it like this. First, define a function that returns 1 if the opcode is in the desired range:

	DEFINE_PATCH_FUNCTION is_damage_resistance
	RET value
	BEGIN
	READ_BYTE 0x0 opcode
	PATCH_MATCH "%opcode%" WITH
	27 28 29 30 31 84 85 86 87 88 89 BEGIN
	SET value=1
	END
	DEFAULT
	SET value=0
	END
	END
	

Then do this patch on the item or spell you're working on

	LPF DELETE_EFFECT STR_VAR match_function=is_damage_resistance END
	

Secondly, suppose you instead want to halve the efficacy of all damage-resistance powers. Define another function:

	DEFINE_PATCH_FUNCTION halve_parameter2
	BEGIN
	WRITE_LONG 0x4  (LONG_AT 0x4) / 2
	END
	

Then just apply the patch

	LPF ALTER_EFFECT STR_VAR match_function=is_damage_resistance function=halve_parameter2 END
	

Share this post


Link to post

4a. More advanced function matching/patching

Instead of a function name, you can set function or match_function to a string

	function_name(args)
	

Function_name should still be the name of an appropriate patch function, but if that function has a STR_VAR 'arguments', 'args' will be fed into that variable. In my applications, I defined functions 'opcode_is' and 'opcode_is_not', each of which took as argument a space-separated string of integers and returned 1 if the opcode was /wasn't in the string.

Share this post


Link to post
Posted (edited)
On 5/11/2019 at 12:09 PM, DavidW said:

3. Negative values of parameter1 and parameter2

(The main application is if a parameter represents a string and you want to set it to -1.)

Moreover, there may be issues with signed integers (i.e., all those values for which BIT31 - 0x80000000 is set to 1). For instance:

LPF ALTER_EFFECT
INT_VAR
  match_opcode = 324 // Immunity from spell and message
  parameter1 = 0x80110FEF // the function won't write this value...
  parameter2 = 138 // STATE bit_eq specified value
END

 

Edited by Luke

Share this post


Link to post

Yes, but this fix won’t handle that case, because I didn’t need it. I wasn’t really aiming to do a systematic improvement of the toolset, just to share something I’d done for my own use.

Share this post


Link to post
On 5/11/2019 at 1:01 PM, DavidW said:

They're available on the SCS repo in stratagems/lib/alter_effect.tpa.

 

Fixed that for yöu. 

Share this post


Link to post
Guest
You are commenting as a guest. If you have an account, please sign in.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×