I have found some time for another subcomponent; this time it's Improved Encounters: not many problems with files being overwritten, but the way scripts were patched was completely broken.
Edit: in the end, there's something about other new subcomponents.
First of all, some functions I used, and why.
REPLACE_BCS_BLOCK, which would be the most obvious choice, fails if any detail inside the block is changed by any other mod.
REPLACE_TEXTUALLY, on the other hand, is only easy to use if you want to partially alter a trigger of action, and not if you want to completely change one block.
The following function looks for a small regexp (as REPLACE_TEXTUALLY), but replaces the whole block containing it, as R_BCS_BLOCK does
(actually, I've divided the function in two parts; the first one only looks for the string, the other performs the substitution after calling the first one):
DEFINE_PATCH_FUNCTION search_baf_block
INT_VAR exact = 0 instance = 1 logging = 1
STR_VAR search = ~~
RET block start
BEGIN
INNER_PATCH_SAVE search ~%search%~ BEGIN
EVALUATE_BUFFER
END
FOR ( start = 0
i = 0 ; (( %i% < %instance% ) AND ( %start% + 1 )) ; i += 1 ) BEGIN
PATCH_IF %start% BEGIN
start +=1
END
PATCH_IF %exact% BEGIN
start = INDEX_BUFFER ( CASE_INSENSITIVE EXACT_MATCH ~%search%~ %start% )
END ELSE BEGIN
start = INDEX_BUFFER ( CASE_INSENSITIVE EVALUATE_REGEXP ~%search%~ %start% )
END
END
PATCH_IF ( %start% + 1) BEGIN
stop = INDEX_BUFFER ( CASE_SENSITIVE EVALUATE_REGEXP ~^ *END *$~ %start%) + 4
READ_ASCII 0 file (%start%)
start = RINDEX (CASE_SENSITIVE EVALUATE_REGEXP ~^ *IF *$~ ~%file%~)
length = %stop% - %start%
READ_ASCII %start% block (%length%)
END ELSE BEGIN
PATCH_IF %logging% BEGIN
PATCH_LOG ~SEARCH_BAF_BLOCK: %INSTANCE% instances of search pattern "%search%" NOT FOUND in current string.~
END
SPRINT block ~~
END
END
DEFINE_PATCH_FUNCTION search_block_replace
INT_VAR exact = 0 position = 1 on_mismatch = 0
STR_VAR search = ~~ replace = ~~
BEGIN
//evaluate replace variable; search will be directly passed to subfunction
INNER_PATCH_SAVE replace ~%replace%~ BEGIN
EVALUATE_BUFFER
END
INNER_PATCH_SAVE search ~%search%~ BEGIN
EVALUATE_BUFFER
END
//detect if script is compiled
READ_ASCII 0 test (2)
PATCH_IF ~%test%~ STRING_EQUAL_CASE ~SC~ BEGIN
DECOMPILE_BCS_TO_BAF
is_bcs = 1
END ELSE BEGIN
is_bcs = 0
END
//delete all blocks above position
FOR (i=0
index = (0 - 1) ; ( %index% + 1 ) OR (i = 0) ; i += 1 ) BEGIN
PATCH_IF i <= position BEGIN
offset = %index%
END
LPF search_baf_block INT_VAR exact = %exact% logging = 0 STR_VAR search = EVALUATE_BUFFER ~%search%~ RET block=block index=start END
PATCH_IF ( %index% + 1) BEGIN
DELETE_BYTES %index% ( STRING_LENGTH ~%block%~ )
END
END //for
//now, there are no more blocks matching %search%. The index should point to the correct offset. If there IS a replace file, insert it.
PATCH_IF ( STRING_LENGTH ~%replace%~ ) BEGIN
INNER_ACTION BEGIN
COPY - ~%replace%~ ~inlined/search_block_replace.baf~
READ_ASCII 0 test (2)
PATCH_IF ~%test%~ STRING_EQUAL_CASE ~SC~ BEGIN
DECOMPILE_BCS_TO_BAF
END
END
PATCH_IF ( %offset% + 1) BEGIN
INSERT_FILE %offset% ~inlined/search_block_replace.baf~
PATCH_IF i < position BEGIN
PATCH_LOG ~search_block_replace: only %i% instances of the search pattern "%search%" were found. "%replace%" file replaced instance %i% instead of %position%.~
END
END ELSE BEGIN //the search pattern was not found
PATCH_MATCH on_mismatch WITH
1 BEGIN
APPEND_FILE ~inlined/search_block_replace.baf~
END
2 BEGIN
INSERT_FILE 0 ~inlined/search_block_replace.baf~
END
DEFAULT
PATCH_WARN ~WARNING: search_block_replace: search pattern "%search%" NOT FOUND!~
END
END
END
//recompile script if needed
PATCH_IF is_bcs BEGIN
COMPILE_BAF_TO_BCS
END
END
Do you have any suggestion to improve these functions? I think they could be useful for other mods as well
And here's the subcomponent (requires
WeiDU 23000; thanks to the bigg for his flash-fix on ASSOCIATIVE arrays).
I usually put all function definitions into a separate file and then INCLUDE it, but of course, you can put them wherever you want...
//////Improved Encounters--Gebhard Blucher and Kensai Ryu//////
BEGIN @399
INCLUDE ~BPv180/lib.tph~ //DEFINITIONS for FUNCTIONS posted above
COPY ~BPv180/GBENC/COPY~ ~override~
COMPILE ~BPv180/GBENC/COMPILE~
ACTION_DEFINE_ASSOCIATIVE_ARRAY bcs BEGIN
ar0041 , ~CreateCreature("REBAND01",[488.558],10)~ , ~~ => 1
ar0042 , ~CreateCreature("REBAND01",[488.558],10)~ , ~~ => 1
ar0042 , ~CreateCreature("RERAK01",[488.558],10)~ , nar0042 => 1
ar0043 , ~CreateCreature("REBAND01",[488.558],10)~ , ~~ => 1
ar0043 , ~CreateCreature("RERAK01",[488.558],10)~ , nar0043 => 1
ar0044 , ~CreateCreature("REBAND01",[488.558],10)~ , ~~ => 1
ar0044 , ~CreateCreature("RERAK01",[488.558],10)~ , nar0044 => 1
ar0045 , ~CreateCreature("REBAND01",[488.558],10)~ , ~~ => 1
amntrp01 , ~DisplayString(Myself,[0-9]+).*%LNL%.*CreateCreatureObjectEffect("JOLUS","",.+)~ , ~~ => 0
amntrp01 , ~SetGlobalTimer("RepTrap","GLOBAL",.+).*%LNL%.*Wait([0-9]+).*%LNL%.*DisplayString(Myself,[0-9]+).*%LNL%.*CreateCreatureObject("AMNCEN1",.+,[0-9]+,[0-9]+,[0-9]+)~ , ~namntrp1~ => 0
END
ACTION_PHP_EACH bcs AS replace => exact BEGIN
COPY_EXISTING ~%replace_0%.bcs~ ~override~
PATCH_IF ( STRING_LENGTH ~%replace_2%~ ) BEGIN
SPRINT replace_2 ~BPv180/GBENC/SNIP/%replace_2%.bcs~
END
LPF search_block_replace INT_VAR exact = %exact% STR_VAR search = ~%replace_1%~ replace = ~%replace_2%~ END
BUT_ONLY
END
ACTION_BASH_FOR ~BPv180/GBENC/SNIP~ ~^b.*\.bcs~ BEGIN
OUTER_INNER_PATCH_SAVE resource ~%BASH_FOR_FILE%~ BEGIN
DELETE_BYTES 0 1 // "b" prefix
END
EXTEND_BOTTOM ~%resource%~ ~%BASH_FOR_FILESPEC%~
END
EXTEND_BOTTOM ~BODHITRP.BCS~ ~BPv180/GBENC/BODHITRP.BAF~
Finally, here's the GBENC folder as I have reorganized it. There are some resources which can be removed from other BP folders (such as BP/SNIP and BP/BAF):
gbenc.7z 16.16K
170 downloadsother subcomponentsEdit: I haven't forgotten about KR's Gnome fighter/illusionist, but that's all right. Actually, I think we could remove 2 or 3 lines:
////////////Gnome Fighter/Illusionist, by Kensai Ryu///////////
BEGIN @398
COPY ~BPv180/KRGNOME/KRFAM01.cre~ ~override/KRFAM01.cre~
COPY ~BPv180/KRGNOME/KRFAM02.cre~ ~override/KRFAM02.cre~
COPY ~BPv180/KRGNOME/KRGNOME.cre~ ~override/KRGNOME.cre~
COMPILE ~BPv180/KRGNOME/COMPILE~
EXTEND_BOTTOM ~AR0326.BCS~ ~BPv180/KRGNOME/AR0326.BAF~
since, from what I have experimented, EXTEND_BOTTOM automatically falls back to COMPILE if the game resource doesn't exist yet.
Same for Lich in the Docks subcomponent.
Kuroisan does not require any modification (EXTENDING_TOP baldur.bcs should not be an issue)
Red Badge:
1. A (correctly prefixed) area is added, which uses, thugh, the wed, tis, mos,... of an existing area (ar0418). Can we leave it like that or is it better to duplicate all resources?
2. The ar3000 area script is EXTENDED_TOP. In order not to break any OnCreation() blocks, I'd put a Continue() after the first block (the other two blocks require a timer set by the first one to expire, so they shouldn't trigger until all OnCreation blocks have triggered).
Edited by Turambar, 19 September 2011 - 12:30 PM.