(solved) Variable game speed, consistent portrait speed

Started by Radiant, Tue 08/10/2013 13:58:05

Previous topic - Next topic

Radiant

The game I'm working on has a speed slider that allows the player to SetGameSpeed from 30 to 100. However, at higher speeds, portrait animation starts to look odd, and it has been suggested to me to keep the portrait animation speed constant even as the game speed changes. I believe this is possible by setting game.talkanim_speed to a value dependent on game speed.

However, I'm not sure how talkanim_speed actually works, and the manual doesn't specify. Can someone make a suggestion on how to do this properly? Thanks!

monkey0506

#1
Well without actually testing it, the seemingly obvious way of using the hidden, undocumented property would be to simply tie it to the game speed proportionally so that the effective display is always the same.

Code: ags
function ChangeGameSpeed(int speed)
{
  SetGameSpeed(speed); // you must call this FIRST before the other code makes sense ;)
  int defaultTalkAnimSpeed = game.talkanim_speed; // make this global if you have any OTHER cause to access it (otherwise it's superfluous anyway)
  game.talkanim_speed = (defaultTalkAnimSpeed * GetGameSpeed()) / 40; // update setting to relative game speed
}

function sldSpeed_OnChange(GUIControl *control)
{
  ChangeGameSpeed(sldSpeed.Value);
}


At a game speed of 1000, this updates talkanim_speed to 125, which is exactly 12.5% of 1000, just as the default value of 5 is 12.5% of the default game speed of 40. Assuming this property works how and for what you intend, this should create the effect you're looking for.

Edit: I updated the example to better reflect the usage you're employing.

Radiant

That's more or less what I have been doing: I first do SetGameSpeed(value), then game.talkanim_speed = value / 7. However, this doesn't work; compared to the default of gamespeed 50, talkanim 7, portrait animation becomes markedly faster I drag the slider to gamespeed 100, talkanim 14; and it becomes very slow if I drag the slider to gamespeed 30, talkanim 4. So I figured that talkanim_speed might not work the way I think it does (in fact, current behavior makes it seem like setting game.talkanim_speed has no effect).

monkey0506

#3
Well, taking the time to actually open up Visual Studio, it looks like I've found the problem.

Code: cpp
int GetCharacterSpeechAnimationDelay(CharacterInfo *cha)
{
    if (game.options[OPT_OLDTALKANIMSPD])
    {
        // The talkanim property only applies to Lucasarts style speech.
        // Sierra style speech has a fixed delay of 5.
        if (game.options[OPT_SPEECHTYPE] == 0)
            return play.talkanim_speed;
        else
            return 5;
    }
    else
        return cha->speech_anim_speed;
}


game.talkanim_speed not only was applied exclusively to LucasArts-style speech, but it was also superseded in newer versions of AGS:

QuoteSpeechAnimationDelay property
int Character.SpeechAnimationDelay;

Gets/sets the character's speech animation delay, as set in the editor. This specifies how many game loops each frame of the character's speech animation is shown for.

NOTE: This property is ignored if lip sync is enabled.

NOTE: This property cannot be used if the backwards compatibility option "Old-style game-wide speech animation speed" is enabled in the General Settings. In that case, the legacy game.talkanim_speed setting is used instead.

It looks like characters are automatically assigned a SpeechAnimationDelay of 5 by default, which was the default for the old game.talkanim_speed property. So, based on that you could try something like:

Code: ags
void ChangeGameSpeed(int speed)
{
  SetGameSpeed(speed);
  int i = 0;
  while (i < Game.CharacterCount)
  {
    // optional: int offset = character[i].GetProperty("SpeechAnimationDelay"); // to continue allowing per-character settings, default 0
    character[i].SpeechAnimationDelay = (speed / 7); // optional: + offset
    i++;
  }
}

function sldSpeed_OnChange(GUIControl *control)
{
  ChangeGameSpeed(sldSpeed.Value);
}

Radiant

Thank you, I'll try that. Does that "Old-style game-wide" property have a game.foo equivalent variable?

monkey0506

Well the engine's SetGameOption and GetGameOption directly correlate to the internal game.options array (NOTE: This is the C++ GameSetupStruct game, not the AGScript GameState game; there is no AGScript game.options array). The OPT_OLDTALKANIMSPD is not defined for AGScript, but it should be perfectly safe to use its value. You can do this:

Code: ags
#ifndef OPT_OLDTALKANIMSPD
#define OPT_OLDTALKANIMSPD 39
#endif

function game_start()
{
  SetGameOption(OPT_OLDTALKANIMSPD, 1); // FORCE per-character speed setting, 0 to force game-wide
}


Bear in mind that Sierra-style speech always ignores the game-wide setting, but respects the per-character setting. I'd have half a mind to change that behavior, but it would technically be breaking backwards compatibility for a feature that exists for the purpose of enabling backwards compatibility. Perhaps instead a new property could be added to the Speech struct to allow a game-wide setting (overriding the per-character setting) that Sierra speech could be made to respect. It seems that would likely be useful to you so you don't have to loop through every character when the game speed is updated. I'll look into it.

Radiant

Good point. Personally I don't see any reason why you would want to set this value differently for various characters.

SMF spam blocked by CleanTalk