Jump to content

Patch vs action


Recommended Posts

This may be a bit elementary, but is there an easy rule of thumb to differentiate between using DEFINE_ACTION_FUNCTION or DEFINE_PATCH FUNCTION?

From what I understand WeiDU goes from patch and action context depending on the command it encounters. For instance, I wrote this bit of code below to ensure that all liches in my game receive their undead immunities through RING95.ITM. 

//// liches should have undead immunities

DEFINE_ACTION_FUNCTION minor_lich
	STR_VAR race=""

BEGIN 
	COPY_EXISTING_REGEXP ".*\.cre" ~override~ 
	 PATCH_IF ~%race%~ STRING_EQUAL_CASE LICH BEGIN
	   ADD_CRE_ITEM ~RING95~ #0 #0 #0 ~IDENTIFIED~ ~RING~
	END
  BUT_ONLY
END

I used DAF here so I can easily append the top of this setup file with: 

Quote

ACTION_FOR_EACH func IN compound grove cult talos elemental nyalee lava muggers lich BEGIN
         LAF ~minor_%func%~ END
      END

Could I just have easily used DPF in this instance? I've see plenty examples of mods using patch functions like COPY_EXISTING under both. 

Edited by WanderingScholar
Link to comment

An action does something to files; patches happen within files. 

ACTION_IF (sky = blue) BEGIN
  COPY_EXISTING ~file.itm~ ~override~
    SAY NAME1 ~thisfile~
  BUT_ONLY_IF_IT_CHANGES
END

…vs.

COPY_EXISTING ~file.itm~ ~override~
  PATCH_IF (sky = blue) BEGIN
    SAY NAME1 ~thisfile~
  END
BUT_ONLY_IF_IT_CHANGES
Edited by subtledoctor
Link to comment

Action = you don't have a file loaded right now

Patch = you have a file loaded

COPY_EXISTING is an action in itself - an action that transitions you to the patch environment.

If you try to use an action while you currently have a file loaded, that will tell WeiDU that you're done modifying that file so it can get back to the action environment. If you try to use a patch while you don't have a file loaded, WeiDU will throw an error.

Your example there is definitely an action function - go through all the creature files and modify the liches. You don't want to have something loaded when you do it. It also doesn't work; your usage there would simply do nothing, as "~~ STRING_EQUAL_CASE ~lich~" always returns false. And if you fixed the issue with the unnecessary parameter, you'd have to watch out for liches that had both their ring slots filled; this would bump one of their equipped rings out and cause issues. Plus it would add extra copies of the lich immunity item to liches that already had it, which isn't good. That function needs considerably more complex code to work properly.

In addition, as something that is only run at most once per component, I probably wouldn't do it as a function at all. Instead, it would be a separate .tph file that I'd INCLUDE when needed.

Link to comment

@jmerryOK, are you saying that DEFINE_PATCH_FUNCTION would break the above? 

29 minutes ago, jmerry said:

watch out for liches that had both their ring slots filled; this would bump one of their equipped rings out and cause issues.

I was a bit worried about this. At a cursory glance most creatures with race=lich already have either LICH.ITM as their only ring, or both. I wasn't sure how to write this to check for RING95.ITM (possibly READ_ some offsets), but I figured I should be safe about the bumping since BUT_ONLY should prevent liches with RING95.ITM from being patched at all? 

Neither here nor there but did they ever fix this in the EE editions? I don't have them installed but you can check if you look at HLSHANG.CRE or HLKANG.CRE. It's rather embarrassing to die from poison as a lich. 

Edited by WanderingScholar
Link to comment

The very first lich I checked? Zhadroth from SoD. He's absolutely one that you'd want to do this for, as he lacks any sort of poison immunity once the spectacles remove his invulnerability. And he has both ring slots filled; the left with a ring of regeneration and the right with the BDLICH immunity item. Run this, and the ring of regeneration gets bumped to the inventory.

Also, running that ADD_CRE_ITEM will add an instance of the item even if one's already present. Changes will be made, period. BUT_ONLY doesn't help with that.

Link to comment
28 minutes ago, jmerry said:

The very first lich I checked? Zhadroth from SoD. He's absolutely one that you'd want to do this for, as he lacks any sort of poison immunity once the spectacles remove his invulnerability. And he has both ring slots filled; the left with a ring of regeneration and the right with the BDLICH immunity item. Run this, and the ring of regeneration gets bumped to the inventory.

Also, running that ADD_CRE_ITEM will add an instance of the item even if one's already present. Changes will be made, period. BUT_ONLY doesn't help with that.

Well I play the original BGT so no SoD, but it looks like I'll have to read both of the ring slots and use patch if neither of them contain RING95.ITM since ADD_CRE_ITEM is going to put it in regardless. I guess there are other ways I could do this like patching the opcodes for poison immunities, which are probably the most urgently needed, directly into the creatures. 

Edit: Scratch that, it's probably better if I just list out the individual creatures that are missing it. I just found a lich with 2 rings so it's not going to work the other way

Edited by WanderingScholar
Link to comment

This should do it

ACTION_FOR_EACH ~file~ IN
	~AMLICH01~
	~CEDELICH~
	~D0LICH02~
	~DW#LICH1~
	~DW#LICH2~
	~DW#LICH3~
	~DW#LICH4~
	~DW#LICH5~
	~DW#LICH6~
	~DW#LICH7~
	~DW#LICH8~
	~DW#LICH9~
	~FIRLCH01~
	~GRVLCH01~
	~HLKANG~
	~HLLICH~
	~HLSHADE~
	~HLSHANG~
	~JARLICH~
	~LICHEL01~
	~SENLICH~
	~UDTRAP04~
	~CELICH~
BEGIN                                                                              
ACTION_IF FILE_EXISTS_IN_GAME ~%file%.cre~ BEGIN             
COPY_EXISTING ~%file%.cre~ ~override~
	ADD_CRE_ITEM ~RING95~ #0 #0 #0 ~IDENTIFIED~ ~RING~
	END
  BUT_ONLY
END

I checked each for an empty ring slot

Edited by WanderingScholar
Link to comment

One little trick that you can use to streamline the code further: the "if this exists" check can be moved to where you close the copy operation.

ACTION_IF FILE_EXISTS_IN_GAME ~%file%.cre~ BEGIN             
  COPY_EXISTING ~%file%.cre~ ~override~
	ADD_CRE_ITEM ~RING95~ #0 #0 #0 ~IDENTIFIED~ ~RING~
  BUT_ONLY
END

can be simplified to

COPY_EXISTING ~%file%.cre~ ~override~
  ADD_CRE_ITEM ~RING95~ #0 #0 #0 ~IDENTIFIED~ ~RING~
BUT_ONLY IF_EXISTS

(Also, you haven't placed the ENDs quite right. As you posted it, the END associated with the FILE_EXISTS_IN_GAME block is before the BUT_ONLY ... which means that the copy operation is closed at that END, and the BUT_ONLY when clause is now orphaned in an action environment and throws an error.

Edited by jmerry
Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
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.

×
×
  • Create New...