EFFECTPLAY2.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. namespace OpenVIII.Fields.Scripts.Instructions
  2. {
  3. /// <summary>
  4. /// <para>Play sound effect</para>
  5. /// <para>Plays a sound effect through the given sound channel. The channel is important because it's the parameter used in SESTOP to halt a specific sound effect (and to prevent multiple counds from silencing each other). AFAIK Channels go up to 2^20 (which is 1048576), so you can theoretically have 20 sounds playing at once. 0 doesn't seem like it's a usable channel, but this is untested.</para>
  6. /// <para>Note: It seems each area can have a maximum of 32 sounds predefined(meaning sound ID 31 is the highest you can play with this). You have to use EFFECTPLAY to use more than 32 sounds.</para>
  7. /// </summary>
  8. /// <see cref="http://wiki.ffrtt.ru/index.php?title=FF8/Field/Script/Opcodes/021_EFFECTPLAY2"/>
  9. public sealed class EFFECTPLAY2 : JsmInstruction
  10. {
  11. #region Fields
  12. /// <summary>
  13. /// Channel (must be a power of 2)
  14. /// </summary>
  15. private readonly IJsmExpression _channel;
  16. private readonly int _fieldSoundIndex;
  17. /// <summary>
  18. /// Pan (0=left, 255=right)
  19. /// </summary>
  20. private readonly IJsmExpression _pan;
  21. /// <summary>
  22. /// Volume (0-127)
  23. /// </summary>
  24. private readonly IJsmExpression _volume;
  25. #endregion Fields
  26. #region Constructors
  27. public EFFECTPLAY2(int fieldSoundIndex, IJsmExpression pan, IJsmExpression volume, IJsmExpression channel)
  28. {
  29. _fieldSoundIndex = fieldSoundIndex;
  30. _pan = pan;
  31. _volume = volume;
  32. _channel = channel;
  33. }
  34. public EFFECTPLAY2(int parameter, IStack<IJsmExpression> stack)
  35. : this(parameter,
  36. channel: stack.Pop(),
  37. volume: stack.Pop(),
  38. pan: stack.Pop())
  39. {
  40. }
  41. #endregion Constructors
  42. #region Methods
  43. public override void Format(ScriptWriter sw, IScriptFormatterContext formatterContext, IServices services)
  44. {
  45. var formatter = sw.Format(formatterContext, services);
  46. formatter
  47. .StaticType(nameof(ISoundService))
  48. .Method(nameof(ISoundService.PlaySound))
  49. .Argument("fieldSoundIndex", _fieldSoundIndex)
  50. .Argument("pan", _pan)
  51. .Argument("volume", _volume)
  52. .Argument("channel", _channel)
  53. .Comment(nameof(MUSICLOAD));
  54. }
  55. public override IAwaitable TestExecute(IServices services)
  56. {
  57. ServiceId.Sound[services].PlaySound(_fieldSoundIndex,
  58. _pan.Int32(services),
  59. _volume.Int32(services),
  60. _channel.Int32(services));
  61. return DummyAwaitable.Instance;
  62. }
  63. public override string ToString() => $"{nameof(EFFECTPLAY2)}({nameof(_fieldSoundIndex)}: {_fieldSoundIndex}, {nameof(_pan)}: {_pan}, {nameof(_volume)}: {_volume}, {nameof(_channel)}: {_channel})";
  64. #endregion Methods
  65. }
  66. }