Jump to content

Making mods 10 Party Members aware - DRAFT


the bigg

Recommended Posts

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

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

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

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

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...