HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

problem with jass loops

07-30-2006, 03:02 AM#1
Linera
I'm working on a script that takes a string a limits the number of character per line. The coding appears correct but it only displays the first 2 lines and stops.

Here is my script:
Hidden information:
Collapse JASS:
//Standard Functions
function MyBool takes nothing returns boolean
    return true
endfunction

function WaitForPlayerEvent_H2P takes handle h returns player
    return h
endfunction

function WaitForPlayerEvent_H2F takes handle h returns force
    return h
endfunction

function WaitForPlayerEvent_PE2I takes playerevent p returns integer
    if true then
        return p
    endif
    return 0
endfunction

function WaitForPlayerEvent_Enum takes nothing returns nothing
    call TriggerRegisterPlayerEvent(bj_delayedSuspendDecayTrig, GetEnumPlayer(), ConvertPlayerEvent(bj_forceCountPlayers))
endfunction

function WaitForPlayerEvent takes handle whichForceOrPlayer, playerevent whichPlayerEvent, boolexpr condition, real interval returns nothing
    local trigger bj_temp = bj_delayedSuspendDecayTrig
    local trigger t
    local triggercondition c
    local player whichPlayer = WaitForPlayerEvent_H2P(whichForceOrPlayer)
    local force whichForce = WaitForPlayerEvent_H2F(whichForceOrPlayer)
    if whichForceOrPlayer == null or whichPlayerEvent == null then
        set whichForce = null
        return
    elseif interval < 0 then
        set interval = 0
    endif
    set t = CreateTrigger()
    set bj_delayedSuspendDecayTrig = t
    set bj_forceCountPlayers = WaitForPlayerEvent_PE2I(whichPlayerEvent)
    call ForForce(whichForce, function WaitForPlayerEvent_Enum)
    call TriggerRegisterPlayerEvent(bj_delayedSuspendDecayTrig, whichPlayer, whichPlayerEvent)
    if condition != null then
        set c = TriggerAddCondition(bj_delayedSuspendDecayTrig, condition)
    endif
    set bj_delayedSuspendDecayTrig = bj_temp
    loop
        call TriggerSleepAction(interval)
        exitwhen GetTriggerExecCount(t) != 0
    endloop
    if condition != null then
        call TriggerRemoveCondition(t, c)
        set c = null
    endif
    call DestroyTrigger(t)
    set t = null
    set whichForce = null
endfunction

//End of Standard Functions

//=============================================
// The Parser (Takes a String, Seperates words, Returns word you wanted)
// by DKSlayer
//=============================================
function Parser takes string ChatMsg, integer Word returns string
   //Required Variables
   local string array Chkstr
   local integer Last = 0
   local integer A = 1
   local integer I = 0
   local integer Length = 1

   //Finds the Length of String
   loop
     exitwhen((SubStringBJ(ChatMsg,1,Length) == ChatMsg))
     set Length = Length + 1
   endloop

   //Pulls Words and places them each in there own Variable
   loop
     if(SubStringBJ(ChatMsg,A,A) == " ") then
       set Chkstr[i] = SubStringBJ(ChatMsg, (Last + 1), (A - 1))
       set Last = A
       set I = I + 1
     elseif(A == Length) then
       set Chkstr[i] = SubStringBJ(ChatMsg, (Last + 1), A)
     endif
     set A = A + 1
     exitwhen(A>Length)
     exitwhen((Word+1)==I)
   endloop

   //Returns wanted word
   return Chkstr[Word]

endfunction

//Set up a new quest
function SetupQuest takes string title, string description, string path returns quest
    local quest q
    
    set q = CreateQuest()
    call QuestSetTitle(q,title)
    call QuestSetCompleted(q, false)
    call QuestSetDiscovered(q, true)
    call QuestSetEnabled(q, false)
    call QuestSetRequired(q, true)
    call QuestSetDescription(q, description)
    call QuestSetIconPath(q, path)
return q
endfunction

//Sets Quest Objectives
function SetQuestObjectives takes quest q, string questrequirment returns questitem
    local questitem qi    

    set qi = QuestCreateItem(q)
    call QuestItemSetDescription(qi,questrequirment)
    call QuestItemSetCompleted(qi, false)
return qi
endfunction

function StartQuest takes player p, string t, integer wordcount returns nothing
    local integer lines = 16
    local integer currentline = 1
    local integer currentword = 1
    local string temp1 = ""
    local string temp2 = ""
    local integer done = 0
    
    loop
        exitwhen (currentword>wordcount)
        loop
            exitwhen (done==1)
        if (StringLength(temp1)<27) then
            set temp2 = temp1
            set temp1 = temp1 + Parser(t, currentword) + " "
            set currentword = currentword+1
        else
            set temp1 = temp2
            set done = 1
            set currentword = currentword-1
        endif
        endloop
    call DisplayTimedTextToForce( GetForceOfPlayer(p), 10000000000, temp1 )
    set currentline = currentline+1

    set temp1=""

    if (currentline == lines) then
        call DisplayTimedTextToPlayer( p, 0, 0, 1000000000.00, "(|c00FF0000Press ESC to continue.|r)")
        call WaitForPlayerEvent(p, EVENT_PLAYER_END_CINEMATIC, Condition(function MyBool), 1.00)

        set currentline = 1
    endif

    set done=0
    endloop
endfunction


This is the function in question:
Hidden information:
Collapse JASS:
function StartQuest takes player p, string t, integer wordcount returns nothing
    local integer lines = 16
    local integer currentline = 1
    local integer currentword = 1
    local string temp1 = ""
    local string temp2 = ""
    local integer done = 0
    
    loop
        exitwhen (currentword>wordcount)
        loop
            exitwhen (done==1)
        if (StringLength(temp1)<27) then
            set temp2 = temp1
            set temp1 = temp1 + Parser(t, currentword) + " "
            set currentword = currentword+1
        else
            set temp1 = temp2
            set done = 1
            set currentword = currentword-1
        endif
        endloop
    call DisplayTimedTextToForce( GetForceOfPlayer(p), 10000000000, temp1 )
    set currentline = currentline+1

    set temp1=""

    if (currentline == lines) then
        call DisplayTimedTextToPlayer( p, 0, 0, 1000000000.00, "(|c00FF0000Press ESC to continue.|r)")
        call WaitForPlayerEvent(p, EVENT_PLAYER_END_CINEMATIC, Condition(function MyBool), 1.00)

        set currentline = 1
    endif

    set done=0
    endloop
endfunctio


This is my current test string:
Hidden information:
A Threat Within I hope you strapped your belt on tight, young <Class>, because there is work to do here in Northshire.And I don't mean farming.The Stormwind guards are hard pressed to keep the peace here, with so many of us in distant lands and so many threats pressing close. And so we're enlisting the aid of anyone willing to defend their home. And their alliance.If you're here to answer the call, then speak with my superior, Marshal McBride. He's inside the abbey behind me.Quest Objectives Speak with Marshal McBride.
07-31-2006, 05:08 AM#2
Linera
bump, please help...
07-31-2006, 03:24 PM#3
Naakaloh
Erm, I'm not sure how you got it to run. The variable used for the index for Chkstr is not declared. Assuming you've already fixed that, however, I think the issue is that the thread is hitting it's execution limit. Throw a polled wait in after the second loop in Parser and it should be fine, after looping through what looks like more than 500 characters, for every word I'm not surprised if it's stopping. Also you can probably increase the number of characters per line since you won't be able to fit that many 16 lines. (27*16) = 432

Edit: What you should really do instead, is parse the entire thing once and then just pull the words you want. Give me a few minutes and I should be able to have that done easily enough.

Edit 2: Ok, I basically just stuck all the Parser code into the StartQuest function, so now it only loops through the text once saving processor time and not killing the thread; I left the Parser function as it is in case you still have a use for it.

Linera's Functions

Collapse JASS:
//Standard Functions
function MyBool takes nothing returns boolean
    return true
endfunction

function WaitForPlayerEvent_H2P takes handle h returns player
    return h
endfunction

function WaitForPlayerEvent_H2F takes handle h returns force
    return h
endfunction

function WaitForPlayerEvent_PE2I takes playerevent p returns integer
    if true then
        return p
    endif
    return 0
endfunction

function WaitForPlayerEvent_Enum takes nothing returns nothing
    call TriggerRegisterPlayerEvent(bj_delayedSuspendDecayTrig, GetEnumPlayer(), ConvertPlayerEvent(bj_forceCountPlayers))
endfunction

function WaitForPlayerEvent takes handle whichForceOrPlayer, playerevent whichPlayerEvent, boolexpr condition, real interval returns nothing
    local trigger bj_temp = bj_delayedSuspendDecayTrig
    local trigger t
    local triggercondition c
    local player whichPlayer = WaitForPlayerEvent_H2P(whichForceOrPlayer)
    local force whichForce = WaitForPlayerEvent_H2F(whichForceOrPlayer)
    if whichForceOrPlayer == null or whichPlayerEvent == null then
        set whichForce = null
        return
    elseif interval < 0 then
        set interval = 0
    endif
    set t = CreateTrigger()
    set bj_delayedSuspendDecayTrig = t
    set bj_forceCountPlayers = WaitForPlayerEvent_PE2I(whichPlayerEvent)
    call ForForce(whichForce, function WaitForPlayerEvent_Enum)
    call TriggerRegisterPlayerEvent(bj_delayedSuspendDecayTrig, whichPlayer, whichPlayerEvent)
    if condition != null then
        set c = TriggerAddCondition(bj_delayedSuspendDecayTrig, condition)
    endif
    set bj_delayedSuspendDecayTrig = bj_temp
    loop
        call TriggerSleepAction(interval)
        exitwhen GetTriggerExecCount(t) != 0
    endloop
    if condition != null then
        call TriggerRemoveCondition(t, c)
        set c = null
    endif
    call DestroyTrigger(t)
    set t = null
    set whichForce = null
endfunction

//End of Standard Functions

//=============================================
// The Parser (Takes a String, Seperates words, Returns word you wanted)
// by DKSlayer
//=============================================
function Parser takes string ChatMsg, integer Word returns string
   //Required Variables
   local string array Chkstr
   local integer Last = 0
   local integer A = 1
   local integer I = 0
   local integer Length = 1

   //Finds the Length of String
   loop
     exitwhen((SubStringBJ(ChatMsg,1,Length) == ChatMsg))
     set Length = Length + 1
   endloop

   //Pulls Words and places them each in there own Variable
   loop
     if(SubStringBJ(ChatMsg,A,A) == " ") then
       set Chkstr[i] = SubStringBJ(ChatMsg, (Last + 1), (A - 1))
       set Last = A
       set I = I + 1
     elseif(A == Length) then
       set Chkstr[i] = SubStringBJ(ChatMsg, (Last + 1), A)
     endif
     set A = A + 1
     exitwhen(A>Length)
     exitwhen((Word+1)==I)
   endloop

call TriggerSleepAction(0)

   //Returns wanted word
   return Chkstr[Word]

endfunction

//Set up a new quest
function SetupQuest takes string title, string description, string path returns quest
    local quest q
    
    set q = CreateQuest()
    call QuestSetTitle(q,title)
    call QuestSetCompleted(q, false)
    call QuestSetDiscovered(q, true)
    call QuestSetEnabled(q, false)
    call QuestSetRequired(q, true)
    call QuestSetDescription(q, description)
    call QuestSetIconPath(q, path)
return q
endfunction

//Sets Quest Objectives
function SetQuestObjectives takes quest q, string questrequirment returns questitem
    local questitem qi    

    set qi = QuestCreateItem(q)
    call QuestItemSetDescription(qi,questrequirment)
    call QuestItemSetCompleted(qi, false)
return qi
endfunction

function StartQuest takes player p, string t, integer wordcount returns nothing
    local integer lines = 16
    local integer currentline = 1
    local integer currentword = 1
    local string temp1 = ""
    local string temp2 = ""
    local integer done = 0


// BEGIN PARSER SCRIPT //

   local string array Chkstr
   local integer Last = 0
   local integer A = 1
   local integer I = 0
   local integer Length = 1

   //Finds the Length of String
   loop
     exitwhen((SubStringBJ(t,1,Length) == t))
     set Length = Length + 1
   endloop

   //Pulls Words and places them each in there own Variable
   loop
     if(SubStringBJ(t,A,A) == " ") then
       set Chkstr[i] = SubStringBJ(t, (Last + 1), (A - 1))
       set Last = A
       set I = I + 1
     elseif(A == Length) then
       set Chkstr[i] = SubStringBJ(t, (Last + 1), A)
     endif
     set A = A + 1
     exitwhen(A>Length)
     exitwhen((wordcount)==I)
   endloop
    
// END PARSER SCRIPT //


    loop
        exitwhen (currentword>wordcount)
        loop
            exitwhen (done==1)
        if (StringLength(temp1)<45) then
            set temp2 = temp1
            set temp1 = temp1 + Chkstr[currentword] + " "
            set currentword = currentword+1
        else
            set temp1 = temp2
            set done = 1
            set currentword = currentword-1
        endif
        endloop
    call DisplayTimedTextToForce( GetForceOfPlayer(p), 10000000000, temp1 )
    set currentline = currentline+1

    set temp1=""

    if (currentline == lines) then
        call DisplayTimedTextToPlayer( p, 0, 0, 1000000000.00, "(|c00FF0000Press ESC to continue.|r)")
        call WaitForPlayerEvent(p, EVENT_PLAYER_END_CINEMATIC, Condition(function MyBool), 1.00)

        set currentline = 1
    endif

    set done=0
    endloop
endfunction



Edit 3: Forget what I said earlier about the index not being declared I'm guessing that there's something causing the 'I' to be 'i' because it's trying to italicize the text. And about not having enough lines, I didn't realize it was supposed to allow you to get more text.

Edit 4: Regardless of unuse, Parser is modified to use TriggerSleepAction(0) as suggested by Blade.dk...
07-31-2006, 03:49 PM#4
Blade.dk
Don't ever use PolledWait(0.01), it is a horrible idea. Just use TriggerSleepAction(0).
07-31-2006, 03:51 PM#5
Naakaloh
Ok, my mistake, but after getting rid of calling Parser, it doesn't seem necessary anyway.
07-31-2006, 05:36 PM#6
Linera
thanks Naakaloh + rep