• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Speech System Bug

Status
Not open for further replies.
Level 16
Joined
Mar 27, 2011
Messages
1,349
I'm using a talk system in my cinematic that uses floating text to display the dialogue, displaying 1 character at a time. It's very buggy at the moment. Sometimes a unit's speech will stop halfway through (without finishing what the unit was suppose to say). Sometimes when a unit talks, it will instantly display what the previous unit said. Here is my system:

  • Talk Start
    • Events
    • Conditions
    • Actions
      • -------- ------- --------
      • -------- Setup Variables --------
      • -------- ------- --------
      • Set Talk_Index = (Talk_Index + 1)
      • Set Talk_Message[Talk_Index] = TalkV_Message
      • Set Talk_Unit[Talk_Index] = TalkV_Unit
      • Set Talk_Offset[Talk_Index] = TalkV_Offset
      • Set Talk_Angle[Talk_Index] = TalkV_Angle
      • Set Talk_Speed[Talk_Index] = 0.06
      • Set Talk_DurationBuffer[Talk_Index] = 0.75
      • Set Talk_Duration[Talk_Index] = ((Talk_Speed[Talk_Index] x (Real((Length of Talk_Message[Talk_Index])))) + Talk_DurationBuffer[Talk_Index])
      • Set Talk_MessagePartial[Talk_Index] = |n|n|cffffcc00
      • Set Talk_CharacterPosition[Talk_Index] = 1
      • Set Talk_NextCharacter[Talk_Index] = (Substring(Talk_Message[Talk_Index], Talk_CharacterPosition[Talk_Index], Talk_CharacterPosition[Talk_Index]))
      • -------- ------- --------
      • -------- Perform Actions --------
      • -------- ------- --------
      • Set TempPoint = (Position of Talk_Unit[Talk_Index])
      • Set TempPoint2 = (TempPoint offset by Talk_Offset[Talk_Index] towards Talk_Angle[Talk_Index] degrees)
      • Floating Text - Create floating text that reads Talk_MessagePartial[Talk_Index] at TempPoint2 with Z offset 0.00, using font size SpeechFontSizeModifier, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
      • Set Talk_FloatingText[Talk_Index] = (Last created floating text)
      • Floating Text - Change Talk_FloatingText[Talk_Index]: Disable permanence
      • Floating Text - Change the fading age of Talk_FloatingText[Talk_Index] to Talk_Duration[Talk_Index] seconds
      • Floating Text - Change the lifespan of Talk_FloatingText[Talk_Index] to (Talk_Duration[Talk_Index] + 1.00) seconds
      • Cinematic - Flash a speech indicator for Talk_Unit[Talk_Index] of color (100.00%, 100.00%, 100.00%) with 0.00% transparency
      • Custom script: call RemoveLocation (udg_TempPoint)
      • Custom script: call RemoveLocation (udg_TempPoint2)
      • -------- ------- --------
      • -------- Turn on Loop --------
      • -------- ------- --------
      • Set Talk_LoopCounter[Talk_Index] = 0.00
      • Set Talk_CharacterTimer[Talk_Index] = 0.00
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Talk_Index Equal to 1
        • Then - Actions
          • Trigger - Turn on Talk Loop <gen>
        • Else - Actions
  • Talk Loop
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • -------- Loops for all instances of talk --------
      • For each (Integer Talk_LoopInteger) from 1 to Talk_Index, do (Actions)
        • Loop - Actions
          • -------- Increments talk counters --------
          • Set Talk_LoopCounter[Talk_LoopInteger] = (Talk_LoopCounter[Talk_LoopInteger] + 0.01)
          • Set Talk_CharacterTimer[Talk_LoopInteger] = (Talk_CharacterTimer[Talk_LoopInteger] + 0.01)
          • -------- Update Floating Text Position --------
          • Set TempPoint = (Position of Talk_Unit[Talk_LoopInteger])
          • Set TempPoint2 = (TempPoint offset by Talk_Offset[Talk_LoopInteger] towards Talk_Angle[Talk_LoopInteger] degrees)
          • Floating Text - Change the position of Talk_FloatingText[Talk_LoopInteger] to TempPoint2 with Z offset 0.00
          • Custom script: call RemoveLocation (udg_TempPoint)
          • Custom script: call RemoveLocation (udg_TempPoint2)
          • -------- Checks if its time to display the next character --------
          • -------- 0.06 timer for characters --------
          • -------- 0.01 wait for spaces (loop cycle) --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • Talk_NextCharacter[Talk_LoopInteger] Equal to
                  • And - All (Conditions) are true
                    • Conditions
                      • Talk_NextCharacter[Talk_LoopInteger] Not equal to
                      • Talk_CharacterTimer[Talk_LoopInteger] Greater than or equal to Talk_Speed[Talk_LoopInteger]
            • Then - Actions
              • -------- Appends the next character to the Speech --------
              • Set Talk_MessagePartial[Talk_LoopInteger] = (Talk_MessagePartial[Talk_LoopInteger] + Talk_NextCharacter[Talk_LoopInteger])
              • Floating Text - Change text of Talk_FloatingText[Talk_LoopInteger] to Talk_MessagePartial[Talk_LoopInteger] using font size 10.00
              • -------- Resets the timer and counts 1 position in the String --------
              • Set Talk_CharacterTimer[Talk_LoopInteger] = 0.00
              • Set Talk_CharacterPosition[Talk_LoopInteger] = (Talk_CharacterPosition[Talk_LoopInteger] + 1)
              • -------- Previews Next Character --------
              • Set Talk_NextCharacter[Talk_LoopInteger] = (Substring(Talk_Message[Talk_LoopInteger], Talk_CharacterPosition[Talk_LoopInteger], Talk_CharacterPosition[Talk_LoopInteger]))
              • -------- Checks if time has ended --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Talk_LoopCounter[Talk_LoopInteger] Greater than or equal to (Talk_Duration[Talk_LoopInteger] + 1.50)
                • Then - Actions
                  • -------- All Talk instances are re-indexed --------
                  • Set Talk_Unit[Talk_LoopInteger] = Talk_Unit[Talk_Index]
                  • Set Talk_Unit[Talk_Index] = No unit
                  • Set Talk_FloatingText[Talk_LoopInteger] = Talk_FloatingText[Talk_Index]
                  • Set Talk_MessagePartial[Talk_LoopInteger] = Talk_MessagePartial[Talk_Index]
                  • Set Talk_Message[Talk_LoopInteger] = Talk_Message[Talk_Index]
                  • Set Talk_NextCharacter[Talk_LoopInteger] = Talk_NextCharacter[Talk_Index]
                  • Set Talk_CharacterPosition[Talk_LoopInteger] = Talk_CharacterPosition[Talk_Index]
                  • Set Talk_LoopCounter[Talk_LoopInteger] = Talk_LoopCounter[Talk_Index]
                  • Set Talk_CharacterTimer[Talk_LoopInteger] = Talk_CharacterTimer[Talk_Index]
                  • Set Talk_Speed[Talk_LoopInteger] = Talk_Offset[Talk_Index]
                  • Set Talk_Duration[Talk_LoopInteger] = Talk_Duration[Talk_Index]
                  • Set Talk_DurationBuffer[Talk_LoopInteger] = Talk_DurationBuffer[Talk_Index]
                  • Set Talk_Offset[Talk_LoopInteger] = Talk_Offset[Talk_Index]
                  • Set Talk_Angle[Talk_LoopInteger] = Talk_Angle[Talk_Index]
                  • Set Talk_Index = (Talk_Index - 1)
                  • Set Talk_LoopInteger = (Talk_LoopInteger - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Talk_Index Equal to 0
                    • Then - Actions
                      • Trigger - Turn off (This trigger)
                    • Else - Actions
                • Else - Actions
            • Else - Actions
  • test talkk
    • Events
    • Conditions
    • Actions
      • Set TalkV_Message = John:|r Let's Move!
      • Set TalkV_Unit = Commander 0006 <gen>
      • Set TalkV_Offset = 330.00
      • Set TalkV_Angle = 0.00
      • Trigger - Run Talk Start <gen> (ignoring conditions)
      • Set TempReal = (0.07 x (Real((Length of TalkV_Message))))
      • Wait TempReal seconds
I cannot send my map publically sorry, but if you ask I will pivately message you the map.
 
Last edited:
Level 12
Joined
Mar 24, 2011
Messages
1,082
Ok, to begin with "Wait"s are not exact, they always add some time to the value up to ~0.3 seconds. Of course, this could not make a unit end the speech earlier but exactly the opposite, it will make it longer. First thing I would change is that, I guess it can be done with timers or else.

Second thing, the way you set the speech data... I find it weird, you are doing:
A = Data
B[index] = A
Use B
A = Data2
B[index] = A
Use B

Instead you can do:
B[index] = Data
Use B
B[index] = Data
Use B

If you can post a test map so I can test it it would be great. Otherwise I guess it has something to do with the last part of the "Talk Loop" where you are messing with the loop index.
 
Level 16
Joined
Mar 27, 2011
Messages
1,349
"Wait"s are not exact, they always add some time to the value up to ~0.3 seconds. Of course, this could not make a unit end the speech earlier but exactly the opposite, it will make it longer.

I'm not too concerned with inaccuracies with the waits (unless of course its bugging my system). I just need to fix the bugs. I've changed it so the variables are set more directly.

Still no luck. I'll send you my map privately. I can't publicly post it sorry.

Edit:
I've reverted back to the old variable referencing. Will change back if need be.
 
Last edited:
Level 16
Joined
Mar 27, 2011
Messages
1,349
Yes I'm aware. I don't need to wait until the text has been removed, I just need to wait the amount of time it takes the system to display the message. In my cinematic I often add a second polled wait of a second or so depending on what I'm doing, sometimes no extra wait.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Oh this might be the problem xD on init, the array element needs to be Talk_Index, not LoopInteger. This would mean that you aren't resetting the values of a certain instance, meaning that they would end instantly since they meet the deindex condition.

  • Set Talk_LoopCounter[Talk_LoopInteger] = 0.00
  • Set Talk_CharacterTimer[Talk_LoopInteger] = 0.00
 
Level 16
Joined
Mar 27, 2011
Messages
1,349
Thanks for looking into this. I'm submitting this cinematic towards the cinematic contest which is due on January 1st. I'm running short of time! lol.

If you want, I can privately send you my map via email if your willing to take a look? I can't post it here I'm sorry.
 
Last edited:
Hmmm, maybe a screenshot of the buggy text might help. I'm thinking it is just not finishing before a command is given to start something new. I don't quite follow the triggers, but it sounds like they are getting overlapped.

Why are you changing the text instead of creating a new one for each unit? Also, why do you need to loop every 0.01? That's a bit fast. 0.03 is recommended. I'm not sure I understand why it needs a talk system, but I assume it has to do with making the cinemagraphic easier to orchestrate. Creating new floating text with an expiration timer might be easier than changing the same floating text's position and text all the time.
 
Level 16
Joined
Mar 27, 2011
Messages
1,349
Will do. I'll get back to you all soon.

Edit: I've uploaded a demo map.

Edit 2: Here is a youtube video of a demo. The footman repeats the phrase: "There is an abandoned command center here within the eastern quadrant." He should say something new the second time.

Also, the Footman asks "Any Q", which is incomplete. He should continue to say "Any Questions?"

 

Attachments

  • Talk System.w3x
    22.5 KB · Views: 54
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,198
Error with instance destruction.
  • Set Talk_Speed[Talk_LoopInteger] = Talk_Offset[Talk_Index]
DOH?!
  • Set Talk_Speed[Talk_LoopInteger] = Talk_Speed[Talk_Index]
That's better! Such mistakes happen to everyone and is probably one of the most common causes of bugs in real programming. Attached is the fixed version.

There is also a logical error as far as text production and instance destruction goes. You need to always test if the instance has expired (not just when advancing characters). You must also not advance characters if the next character is null (pointless operation). This is also applied in the attached version.

  • Talk Loop
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • -------- Loops for all instances of talk --------
      • For each (Integer Talk_LoopInteger) from 1 to Talk_Index, do (Actions)
        • Loop - Actions
          • -------- Increments talk counters --------
          • Set Talk_LoopCounter[Talk_LoopInteger] = (Talk_LoopCounter[Talk_LoopInteger] + 0.01)
          • Set Talk_CharacterTimer[Talk_LoopInteger] = (Talk_CharacterTimer[Talk_LoopInteger] + 0.01)
          • -------- Update Floating Text Position --------
          • Set TempPoint = (Position of Talk_Unit[Talk_LoopInteger])
          • Set TempPoint2 = (TempPoint offset by Talk_Offset[Talk_LoopInteger] towards Talk_Angle[Talk_LoopInteger] degrees)
          • Floating Text - Change the position of Talk_FloatingText[Talk_LoopInteger] to TempPoint2 with Z offset 0.00
          • Custom script: call RemoveLocation (udg_TempPoint)
          • Custom script: call RemoveLocation (udg_TempPoint2)
          • -------- Checks if its time to display the next character --------
          • -------- 0.06 timer for characters --------
          • -------- 0.01 wait for spaces (loop cycle) --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Talk_NextCharacter[Talk_LoopInteger] Not equal to <Empty String>
              • Or - Any (Conditions) are true
                • Conditions
                  • Talk_NextCharacter[Talk_LoopInteger] Equal to
                  • And - All (Conditions) are true
                    • Conditions
                      • Talk_NextCharacter[Talk_LoopInteger] Not equal to
                      • Talk_CharacterTimer[Talk_LoopInteger] Greater than or equal to Talk_Speed[Talk_LoopInteger]
            • Then - Actions
              • -------- Appends the next character to the Speech --------
              • Set Talk_MessagePartial[Talk_LoopInteger] = (Talk_MessagePartial[Talk_LoopInteger] + Talk_NextCharacter[Talk_LoopInteger])
              • Floating Text - Change text of Talk_FloatingText[Talk_LoopInteger] to Talk_MessagePartial[Talk_LoopInteger] using font size 10.00
              • -------- Resets the timer and counts 1 position in the String --------
              • Set Talk_CharacterTimer[Talk_LoopInteger] = 0.00
              • Set Talk_CharacterPosition[Talk_LoopInteger] = (Talk_CharacterPosition[Talk_LoopInteger] + 1)
              • -------- Previews Next Character --------
              • Set Talk_NextCharacter[Talk_LoopInteger] = (Substring(Talk_Message[Talk_LoopInteger], Talk_CharacterPosition[Talk_LoopInteger], Talk_CharacterPosition[Talk_LoopInteger]))
            • Else - Actions
          • -------- Checks if time has ended --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Talk_LoopCounter[Talk_LoopInteger] Greater than or equal to (Talk_Duration[Talk_LoopInteger] + 1.50)
            • Then - Actions
              • -------- All Talk instances are re-indexed --------
              • Set Talk_Unit[Talk_LoopInteger] = Talk_Unit[Talk_Index]
              • Set Talk_Unit[Talk_Index] = No unit
              • Set Talk_FloatingText[Talk_LoopInteger] = Talk_FloatingText[Talk_Index]
              • Set Talk_MessagePartial[Talk_LoopInteger] = Talk_MessagePartial[Talk_Index]
              • Set Talk_Message[Talk_LoopInteger] = Talk_Message[Talk_Index]
              • Set Talk_NextCharacter[Talk_LoopInteger] = Talk_NextCharacter[Talk_Index]
              • Set Talk_CharacterPosition[Talk_LoopInteger] = Talk_CharacterPosition[Talk_Index]
              • Set Talk_LoopCounter[Talk_LoopInteger] = Talk_LoopCounter[Talk_Index]
              • Set Talk_CharacterTimer[Talk_LoopInteger] = Talk_CharacterTimer[Talk_Index]
              • Set Talk_Speed[Talk_LoopInteger] = Talk_Speed[Talk_Index]
              • Set Talk_Duration[Talk_LoopInteger] = Talk_Duration[Talk_Index]
              • Set Talk_DurationBuffer[Talk_LoopInteger] = Talk_DurationBuffer[Talk_Index]
              • Set Talk_Offset[Talk_LoopInteger] = Talk_Offset[Talk_Index]
              • Set Talk_Angle[Talk_LoopInteger] = Talk_Angle[Talk_Index]
              • Set Talk_Index = (Talk_Index - 1)
              • Set Talk_LoopInteger = (Talk_LoopInteger - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Talk_Index Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
 

Attachments

  • Radicool_Talk System_Fixed.w3x
    22.6 KB · Views: 38
Status
Not open for further replies.
Top