private void StdSpeak(Compact target, uint textNum, uint animNum) { animNum += (uint)(target.Core.megaSet / NEXT_MEGA_SET); animNum &= 0xFF; var talkTable = new UShortAccess(_skyCompact.FetchCptRaw((ushort)CptIds.TalkTableList), 0); target.Core.grafixProgId = talkTable[(int)animNum]; target.Core.grafixProgPos = 0; var animPtr = _skyCompact.GetGrafixPtr(target); if (animPtr != null) { target.Core.offset = animPtr[0]; animPtr.Offset += 2; target.Core.getToFlag = animPtr[0]; animPtr.Offset += 2; target.Core.grafixProgPos += 2; } else { target.Core.grafixProgId = 0; } bool speechFileFound = false; if (SkyEngine.IsCDVersion) { speechFileFound = _skySound.StartSpeech((ushort)textNum); } // Set the focus region to that area // Calculate the point where the character is int x = target.Core.xcood - TOP_LEFT_X; int y = target.Core.ycood - TOP_LEFT_Y; // TODO: Make the box size change based on the object that has the focus _skyScreen.SetFocusRectangle(new Rect(x, y, 192, 128)); if (SystemVars.Instance.SystemFlags.HasFlag(SystemFlags.AllowText) || !speechFileFound) { // form the text sprite, if player wants subtitles or // if we couldn't find the speech file var textInfo = _skyText.LowTextManager(textNum, FIXED_TEXT_WIDTH, 0, (byte)target.Core.spColor, true); var textCompact = _skyCompact.FetchCpt(textInfo.CompactNum); target.Core.spTextId = textInfo.CompactNum; //So we know what text to kill var textGfxHeader = ServiceLocator.Platform.ToStructure <DataFileHeader>(textInfo.TextData, 0); textCompact.Core.screen = target.Core.screen; //put it on our screen if (_scriptVariables[SCREEN] == target.Core.screen) { // Only use coordinates if we are on the current screen //talking on-screen //create the x coordinate for the speech text //we need the talkers sprite information var targetGfx = SkyEngine.ItemList[target.Core.frame >> 6]; var header = ServiceLocator.Platform.ToStructure <DataFileHeader>(targetGfx, 0); ushort xPos = (ushort)(target.Core.xcood + header.s_offset_x); ushort width = (ushort)(header.s_width >> 1); xPos += (ushort)(width - FIXED_TEXT_WIDTH / 2); //middle of talker if (xPos < TOP_LEFT_X) { xPos = TOP_LEFT_X; } width = (ushort)(xPos + FIXED_TEXT_WIDTH); if (TOP_LEFT_X + FULL_SCREEN_WIDTH <= width) { xPos = TOP_LEFT_X + FULL_SCREEN_WIDTH; xPos -= FIXED_TEXT_WIDTH; } textCompact.Core.xcood = xPos; ushort yPos = (ushort)(target.Core.ycood + (header.s_offset_y - 6 - textGfxHeader.s_height)); if (yPos < TOP_LEFT_Y) { yPos = TOP_LEFT_Y; } textCompact.Core.ycood = yPos; } else { //talking off-screen target.Core.spTextId = 0; //don't kill any text 'cos none was made textCompact.Core.status = 0; //don't display text } // In CD version, we're doing the timing by checking when the VOC has stopped playing. // Setting spTime to 10 thus means that we're doing a pause of 10 gamecycles between // each sentence. if (speechFileFound) { target.Core.spTime = 10; } else { target.Core.spTime = (ushort)(_skyText.NumLetters + 5); } } else { target.Core.spTime = 10; target.Core.spTextId = 0; } target.Core.logic = L_TALK; }