Beispiel #1
0
        private int fnISpeak(SwordObject cpt, int id, int cdt, int textNo, int spr, int f, int z, int x)
        {
            _speechClickDelay = 3;
            if (((textNo & ~1) == 0x3f0012) && (cdt == 0) && (spr == 0))
            {
                cdt = SwordRes.GEOSTDLCDT; // workaround for missing animation when examining
                spr = SwordRes.GEOSTDL;    // the conductor on the train roof
            }
            cpt.logic = LOGIC_speech;

            // first setup the talk animation
            if (cdt != 0 && (spr == 0))
            { // if 'cdt' is non-zero but 'spr' is zero - 'cdt' is an anim table tag
                var animTabData = _resMan.OpenFetchRes((uint)cdt);
                var anim = new AnimSet(animTabData, Header.Size + cpt.dir * AnimSet.Size);

                cpt.anim_resource = (int)_resMan.ReadUInt32(anim.cdt);
                if (anim.cdt != 0)
                    cpt.resource = (int)_resMan.ReadUInt32(anim.spr);
                _resMan.ResClose((uint)cdt);
            }
            else
            {
                cpt.anim_resource = cdt;
                if (cdt != 0)
                    cpt.resource = spr;
            }
            cpt.anim_pc = 0; // start anim from first frame
            if (cpt.anim_resource != 0)
            {
                if (cpt.resource == 0)
                    throw new InvalidOperationException($"ID {id}: Can't run anim with cdt={cdt}, spr={spr}");

                FrameHeader frameHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes((uint)cpt.resource), 0));
                if (frameHead.offsetX != 0 && frameHead.offsetY != 0)
                { // is this a boxed mega?
                    cpt.status |= STAT_SHRINK;
                    cpt.anim_x = cpt.xcoord;
                    cpt.anim_y = cpt.ycoord;
                }
                else
                    cpt.status &= ~STAT_SHRINK;

                _resMan.ResClose((uint)cpt.resource);
            }
            if (SystemVars.PlaySpeech != 0)
                _speechRunning = _sound.StartSpeech((ushort)(textNo >> 16), (ushort)(textNo & 0xFFFF));
            else
                _speechRunning = false;
            _speechFinished = false;
            if (SystemVars.ShowText != 0 || (!_speechRunning))
            {
                _textRunning = true;

                var text = _objMan.LockText((uint) textNo);
                cpt.speech_time = GetTextLength(text) + 5;
                uint textCptId = _textMan.LowTextManager(text, cpt.speech_width, (byte)cpt.speech_pen);
                _objMan.UnlockText((uint) textNo);

                SwordObject textCpt = _objMan.FetchObject(textCptId);
                textCpt.screen = cpt.screen;
                textCpt.target = (int)textCptId;

                // the graphic is a property of Text, so we don't lock/unlock it.
                ushort textSpriteWidth = _resMan.ReadUInt16(new FrameHeader(_textMan.GiveSpriteData((byte)textCpt.target)).width);
                ushort textSpriteHeight = _resMan.ReadUInt16(new FrameHeader(_textMan.GiveSpriteData((byte)textCpt.target)).height);

                cpt.text_id = (int)textCptId;

                // now set text coords, above the player, usually

                const int TEXT_MARGIN = 3; // distance kept from edges of screen
                const int ABOVE_HEAD = 20; // distance kept above talking sprite
                ushort textX, textY;
                if (((id == GEORGE) || ((id == NICO) && (ScriptVars[(int)ScriptVariableNames.SCREEN] == 10))) && (cpt.anim_resource == 0))
                {
                    // if George is doing Voice-Over text (centered at the bottom of the screen)
                    textX = (ushort)(ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_X] + 128 + (640 / 2) - textSpriteWidth / 2);
                    textY = (ushort)(ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_Y] + 128 + 400);
                }
                else
                {
                    if ((id == GEORGE) && (ScriptVars[(int)ScriptVariableNames.SCREEN] == 79))
                        textX = (ushort)cpt.mouse_x2; // move it off george's head
                    else
                        textX = (ushort)((cpt.mouse_x1 + cpt.mouse_x2) / 2 - textSpriteWidth / 2);

                    textY = (ushort)(cpt.mouse_y1 - textSpriteHeight - ABOVE_HEAD);
                }
                // now ensure text is within visible screen
                ushort textLeftMargin, textRightMargin, textTopMargin, textBottomMargin;
                textLeftMargin = (ushort)(Screen.SCREEN_LEFT_EDGE + TEXT_MARGIN + ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_X]);
                textRightMargin = (ushort)(Screen.SCREEN_RIGHT_EDGE - TEXT_MARGIN + ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_X] - textSpriteWidth);
                textTopMargin = (ushort)(Screen.SCREEN_TOP_EDGE + TEXT_MARGIN + ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_Y]);
                textBottomMargin = (ushort)(Screen.SCREEN_BOTTOM_EDGE - TEXT_MARGIN + ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_Y] - textSpriteHeight);

                textCpt.anim_x = textCpt.xcoord = ScummHelper.Clip(textX, textLeftMargin, textRightMargin);
                textCpt.anim_y = textCpt.ycoord = ScummHelper.Clip(textY, textTopMargin, textBottomMargin);
            }
            return SCRIPT_STOP;
        }
Beispiel #2
0
        private int fnAnim(SwordObject cpt, int id, int cdt, int spr, int e, int f, int z, int x)
        {

            if (cdt != 0 && (spr == 0))
            {
                var animTab = _resMan.OpenFetchRes((uint)cdt);
                var animOffset = Header.Size + cpt.dir * AnimSet.Size;
                var anim = new AnimSet(animTab, animOffset);
                cpt.anim_resource = (int)_resMan.ReadUInt32(anim.cdt);
                cpt.resource = (int)_resMan.ReadUInt32(anim.spr);
                _resMan.ResClose((uint)cdt);
            }
            else
            {
                cpt.anim_resource = cdt;
                cpt.resource = spr;
            }
            if ((cpt.anim_resource == 0) || (cpt.resource == 0))
                throw new InvalidOperationException($"fnAnim called width ({cdt}/{spr}) => ({cpt.anim_resource}/{cpt.resource})");

            var frameHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes((uint)cpt.resource), 0));
            if (frameHead.offsetX != 0 || frameHead.offsetY != 0)
            { // boxed mega anim?
                cpt.status |= STAT_SHRINK;
                cpt.anim_x = cpt.xcoord; // set anim coords to 'feet' coords - only need to do this once
                cpt.anim_y = cpt.ycoord;
            }
            else
            {
                // Anim_driver sets anim coords to cdt coords for every frame of a loose anim
                cpt.status &= ~STAT_SHRINK;
            }
            _resMan.ResClose((uint)cpt.resource);

            cpt.logic = LOGIC_anim;
            cpt.anim_pc = 0;
            cpt.sync = 0;
            return SCRIPT_STOP;
        }