the bigg Posted August 31, 2015 Share Posted August 31, 2015 Following a discussion via PM, it became evident that it is infeasible for the 10pp mod to be able to retroactively handle correctly all required script and dialogue changes for all possible mod scripts; it is far easier to edit the mods themselves, by introducing a facility in WeiDU to loop code (BAF, D, TRA) according to the registered Party Member Count. This is an example of such a facility (that should probably be added to the standard WeiDU library), implemented via a TP2 function, and a sample 10pp-aware mod: DEFINE_PATCH_FUNCTION ~tb#npp_make_aware~ INT_VAR number_of_players = 6 STR_VAR subroutine = ~~ BEGIN TEXT_SPRINT base_search ~_%subroutine%LOOP_PLAYER~ TEXT_SPRINT start_search ~%base_search%_\(M?\)\([0-9]*\)_\(M?\)\([0-9]*\)_BEGIN_~ SET offset = INDEX_BUFFER (~%start_search%~ 0) WHILE offset >= 0 BEGIN offset_end = INDEX_BUFFER (~_BEGIN_~ offset) length = offset_end + 7 - offset READ_ASCII offset buffer_to_parse (offset_end + 7 - offset) DELETE_BYTES offset (length) INNER_PATCH_SAVE end_search ~%buffer_to_parse%~ BEGIN REPLACE_EVALUATE ~%start_search%~ BEGIN PATCH_IF ~%MATCH1%~ STRING_EQUAL_CASE ~M~ THEN BEGIN start = number_of_players - MATCH2 END ELSE BEGIN start = MATCH2 END PATCH_IF ~%MATCH3%~ STRING_EQUAL_CASE ~M~ THEN BEGIN end = number_of_players - MATCH4 END ELSE BEGIN end = MATCH4 END END ~%MATCH0%~ REPLACE_TEXTUALLY ~_BEGIN_~ ~_END_~ END offset_end = INDEX_BUFFER (~%end_search%~ offset) DELETE_BYTES offset_end (STRING_LENGTH ~%end_search%~) READ_ASCII offset buffer_to_duplicate (offset_end - offset) DELETE_BYTES offset (offset_end - offset) TEXT_SPRINT result ~~ FOR (i = start; start < end ? i <= end : i >= end; i += start < end ? 1 : 0 - 1) BEGIN INNER_PATCH_SAVE addendum ~%buffer_to_duplicate%~ BEGIN REPLACE_EVALUATE ~_%subroutine%ITERATOR_\(M?\)\([0-9]*\)_~ BEGIN PATCH_IF ~%MATCH1%~ STRING_EQUAL_CASE ~M~ THEN BEGIN res = i + MATCH2 END ELSE BEGIN res = i - MATCH2 END END ~%res%~ REPLACE_EVALUATE ~_%subroutine%ITERATOR_\(M?\)\([0-9]*\)[*]\([0-9]*\)_~ BEGIN mult = MATCH3 PATCH_IF ~%MATCH1%~ STRING_EQUAL_CASE ~M~ THEN BEGIN res = i * mult + MATCH2 END ELSE BEGIN res = i * mult - MATCH2 END END ~%res%~ TEXT_SPRINT subsubroutine ~%subroutine%SUB~ LPF ~tb#npp_make_aware~ INT_VAR number_of_players = number_of_players STR_VAR subroutine = EVALUATE_BUFFER ~%subsubroutine%~ END END TEXT_SPRINT result ~%result%%addendum%~ END INSERT_BYTES offset (STRING_LENGTH ~%result%~) WRITE_ASCIIE offset ~%result%~ (STRING_LENGTH ~%result%~) offset = INDEX_BUFFER (~%start_search%~ offset) END END // This should be determined from Object.IDS OUTER_SET number_of_players = 10 <<<<<<<< 10pp-aware/tb#test.d BEGIN ~tb#test~ IF ~True()~ THEN start SAY @0 _LOOP_PLAYER_1_M0_BEGIN_ IF ~InParty(Player_ITERATOR_0_)~ THEN REPLY @10000_ITERATOR_0_ GOTO response_ITERATOR_0_ _LOOP_PLAYER_1_M0_END_ END _LOOP_PLAYER_1_M0_BEGIN_ IF ~~ THEN response_ITERATOR_0_ SAY @1 IF ~~ THEN DO ~SetGlobal("PlayerToHeal", "LOCALS", _ITERATOR_0_)~ EXIT END _LOOP_PLAYER_1_M0_END_ >>>>>>>> <<<<<<<< 10pp-aware/tb#test.tra @0 = ~Hello. Who do you want to heal?~ @1 = ~Done!~ _LOOP_PLAYER_1_M0_BEGIN_ @10000_ITERATOR_0_ = ~Heal <Player_ITERATOR_0_>, please!~ _LOOP_PLAYER_1_M0_END_ >>>>>>>> <<<<<<<< 10pp-aware/tb#test.baf _LOOP_PLAYER_M1_1_BEGIN_ IF Global("PlayerToHeal", "LOCALS", Player_ITERATOR_1_) InParty(Player_ITERATOR_1_) THEN RESPONSE #100 Spell(Player_ITERATOR_1_, CURE_LIGHT_WOUNDS) DisplayStringHead("Let me heal <Player_ITERATOR_0_> too, if he exists!") SetGlobal("PlayerToHeal", "LOCALS", Player_ITERATOR_1_)) END _LOOP_PLAYER_M1_1_END_ IF Global("PlayerToHeal", "LOCALS", 1) InParty(Player1) THEN RESPONSE #100 Spell(Player1, CURE_LIGHT_WOUNDS) DisplayStringHead("I already healed <Player1>. Let me stop the iteration!") SetGlobal("PlayerToHeal", "LOCALS", 0)) END _LOOP_PLAYER_1_M0_BEGIN_ IF NumberInParty(_ITERATOR_0_) THEN RESPONSE #100 // DoNothing() _SUBLOOP_PLAYER_1__ITERATOR_0__BEGIN_ RESPONSE #10 DisplayStringHead("Hello <Player_SUBITERATOR_0_>! Need healing?") _SUBLOOP_PLAYER_1__ITERATOR_0__END_ END _LOOP_PLAYER_1_M0_END_ _LOOP_PLAYER_M0_M0_BEGIN_ IF OR(_ITERATOR_3*2_) _SUBLOOP_PLAYER_1__ITERATOR_0__BEGIN_ Dead(Player_SUBITERATOR_0_) !InParty(Player_SUBITERATOR_0_) _SUBLOOP_PLAYER_1__ITERATOR_0__END_ Global("DoNotDisturb", "LOCALS", 0) Global("DoNotDisturb", "LOCALS", 1) Global("DoNotDisturb", "LOCALS", 2) THEN RESPONSE #100 DoSomething() END _LOOP_PLAYER_M0_M0_END_ >>>>>>>> COPY ~10pp-aware/tb#test.d~ ~10pp-aware/tb#test.d~ ~10pp-aware/tb#test.tra~ ~10pp-aware/tb#test.tra~ ~10pp-aware/tb#test.baf~ ~10pp-aware/tb#test.baf~ LPF ~tb#npp_make_aware~ INT_VAR number_of_players = number_of_players END This is still a rough draft, of course - hopefully, by exposing the code to the community, enhancements will me made faster than if made by a single developer. Known issues and other TODOs: - _LOOP_PLAYER... directives generate empty lines in the resulting file - OR() blocks must be encircled in a dummy LOOP_PLAYER_M0_M0_; ideally, after unrolling all LOOP_PLAYER, remaining _ITERATOR_xxx_ should be replaced by the correct values. - More test cases... - Document the synthax - Get somebody to write a meta-mod to convert unmaintained mods to the proposed _LOOP_PLAYER_ synthax (Similar to the BWP Fixpack / Trimpack / Textpack). Link to comment
Jarno Mikkola Posted August 31, 2015 Share Posted August 31, 2015 Can we set the name of the mod, aka set the parameter the mod_in_installed function shall contain, so I can use it to extend the scripts in the canse the 10pp mod is already installed ? I am thinking of kit specific script actions here, if you need a reference. Link to comment
the bigg Posted August 31, 2015 Author Share Posted August 31, 2015 That's the idea - 10pp is installed early, and the mod's script is coded using LOOP_PLAYER_1_M0_ and unrolled by calling tb#npp_make_aware (rather than the current solution, where mods manually iterate Player1..6 and 10pp must guess how to extend to Player7..10. Link to comment
lynx Posted September 1, 2015 Share Posted September 1, 2015 Thanks, I've added a link to this thread to the README (had a perfect modder section for this). Isn't the "RESPONSE #100" after "NumberInParty(_ITERATOR_0_)" extraneus? Link to comment
the bigg Posted September 1, 2015 Author Share Posted September 1, 2015 The resulting file would be: RESPONSE #100 // implied DoNothing() RESPONSE #10 // DisplayStringHead(Player1) RESPONSE #10 // DisplayStringHead(Player2) etc. I can see how the example wouldn't be completely obvious to understand, though. Link to comment
lynx Posted September 1, 2015 Share Posted September 1, 2015 Oh, so you intentionally put in a noop. Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.