Copy to Clipboard Test

FFC Camera Code

#include "std.zh"

//Global settings
const int SNAP_SENSITIVITY = 2; //Distance within which panning viewport snaps to destination is multiplied by this value (values < 2 may be buggy)

//enums
enum
{
    MV_Vx, MV_Vy, MV_Ax, MV_Ay, MV_INTERNAL_X, MV_INTERNAL_Y, MV_Delay, OG_X, OG_Y, DEST_X, DEST_Y, DELAY_TIMER,

    ENUM_MAX
};

//FFC Script
@InitD0("Viewport Mode"),
@InitDHelp0("0 = absolute X/Y, 1 = offset X/Y, 2 = absolute X/Y (pan), 3 = offset X/Y (pan)"),
@InitD1("Move When Triggered"),
@InitDHelp1("If in offset mode, 1 = will not apply this FFC's Vx/Vy/Ax/Ay/A. Delay until the script is triggered"),
@InitD2("X"),
@InitD3("Y"),
@InitD4("Counter ID"),
@InitDHelp4("Counter with this ID will toggle controlled viewport when >= 1 (on) or = 0 (off)"),
@InitD5("Pan Speed 1"),
@InitDHelp5("How fast in px/frame to pan to the destination"),
@InitD6("Pan Speed 2"),
@InitDHelp6("How fast in px/frame to pan back to the hero"),
@InitD7("Allow Out-of-Bounds"),
@InitDHelp7("0 = viewport will not go out-of-bounds, 1 = no restrictions")
ffc script Viewport_Combo
{
    void run(int ViewportMode, bool TrigMove, int ParamX, int ParamY, int TriggerCounter, int PanSpeed, int PanSpeed2, bool OOB)
    {
        //Error messages for out-of-range parameters
        if (ViewportMode < 0 || ViewportMode > 3)
        {
            printf("Mode is out-of-range (0-3)! Ending Viewport_Combo script!");
            this->Script = -1;
        }
        else
        if (TriggerCounter < 0 || TriggerCounter > 106)
        {
            printf("Counter ID is out-of-range (0-106)! Ending Viewport_Combo script!");
            this->Script = -1;
        }

        bool StoredViewMode = false;
        dmapdata DMap = Game->LoadDMapData(Game->CurDMap);
        ViewportMode DefaultViewMode;
        OOB = !OOB;

        //Store and reset FFC movement values
        if (TrigMove)
        {
            this->Misc[MV_Vx] = this->Vx;
            this->Misc[MV_Vy] = this->Vy;
            this->Misc[MV_Ax] = this->Ax;
            this->Misc[MV_Ay] = this->Ay;
            this->Misc[MV_Delay] = this->Delay;
            this->Misc[DELAY_TIMER] = this->Delay;
            this->Vx = 0;
            this->Vy = 0;
            this->Ax = 0;
            this->Ay = 0;
            this->Delay = 0;
        }

        while (true)
        {
            if (Game->Counter[TriggerCounter])
            {
                //this->Misc[DELAY_TIMER] for Move Delay
                if (this->Misc[DELAY_TIMER])
                    --this->Misc[DELAY_TIMER];
                else
                {
                    if (!StoredViewMode)
                    {
                        //Store current view mode
                        DefaultViewMode = Viewport->Mode;
                        StoredViewMode = true;

                        //Restore movement values if moving when triggered
                        if (TrigMove && (ViewportMode == 1 || ViewportMode == 3))
                        {
                            this->Vx = this->Misc[MV_Vx];
                            this->Vy = this->Misc[MV_Vy];
                            this->Ax = this->Misc[MV_Ax];
                            this->Ay = this->Misc[MV_Ay];
                        }

                        //Store current viewport position if panning
                        if (ViewportMode > 1)
                        {
                            this->Misc[OG_X] = Viewport->X;
                            this->Misc[OG_Y] = Viewport->Y;

                            this->Misc[MV_INTERNAL_X] = Viewport->X;
                            this->Misc[MV_INTERNAL_Y] = Viewport->Y;
                        }

                        //Store destination if absolute
                        if (!ViewportMode || ViewportMode == 2)
                        {
                            this->Misc[DEST_X] = ParamX;
                            this->Misc[DEST_Y] = ParamY;
                        }

                        //Clamp the above to bounds
                        if (OOB)
                        {
                            this->Misc[DEST_X] = Clamp(this->Misc[DEST_X], 0, Region->Width-256);
                            this->Misc[DEST_Y] = Clamp(this->Misc[DEST_Y], 0, Region->Height-176-(DMap->Flagset[22] ? 56 : 0));
                            this->Misc[OG_X] = Clamp(this->Misc[OG_X], 0, Region->Width-256);
                            this->Misc[OG_Y] = Clamp(this->Misc[OG_Y], 0, Region->Height-176-(DMap->Flagset[22] ? 56 : 0));
                        }
                    }
                    
                    Viewport->Mode = VIEW_MODE_SCRIPT;

                    //If offset, update destination to FFC's current position + offset
                    if (ViewportMode == 1 || ViewportMode == 3)
                    {
                        this->Misc[DEST_X] = OOB ? Clamp(this->X+ParamX, 0, Region->Width-256) : this->X+ParamX;
                        this->Misc[DEST_Y] = OOB ? Clamp(this->Y+ParamY, 0, Region->Height-176-(DMap->Flagset[22] ? 56 : 0))
                                                            : this->Y+ParamY;
                    }

                    //Pan to destination
                    if (ViewportMode > 1 && Distance(this->Misc[MV_INTERNAL_X], this->Misc[MV_INTERNAL_Y],
                            this->Misc[DEST_X], this->Misc[DEST_Y]) > PanSpeed*SNAP_SENSITIVITY)
                        PanViewport(this->Misc[DEST_X], this->Misc[DEST_Y], PanSpeed, this);
                    else
                    {
                        //Or instantly snap to the FFC + offset
                        Viewport->X = OOB ? Clamp(this->Misc[DEST_X], 0, Region->Width-256) : this->Misc[DEST_X];
                        Viewport->Y = OOB ? Clamp(this->Misc[DEST_Y], 0, Region->Height-176-(DMap->Flagset[22] ? 56 : 0))
                                                    : this->Misc[DEST_Y];
                    }
                }
            }
            else
            {
                if (ViewportMode > 1 && Viewport->Mode == VIEW_MODE_SCRIPT)
                {
                    //Pan back to original position
                    if (Distance(this->Misc[MV_INTERNAL_X], this->Misc[MV_INTERNAL_Y], this->Misc[OG_X],
                            this->Misc[OG_Y]) > PanSpeed2*SNAP_SENSITIVITY)
                        PanViewport(this->Misc[OG_X], this->Misc[OG_Y], PanSpeed2, this);
                    else
                    {
                        //Restore original viewport mode and reset Move Delay
                        Viewport->Mode = DefaultViewMode;
                        StoredViewMode = false;
                        this->Misc[DELAY_TIMER] = this->Misc[MV_Delay];
                    }
                }
                else
                {
                    //^
                    Viewport->Mode = DefaultViewMode;
                    StoredViewMode = false;

                    this->Misc[DELAY_TIMER] = this->Misc[MV_Delay];
                }
            }

            Waitframe();
        }
    }
}

//Function to pan viewport from X/Y to DX/DY
void PanViewport(int DX, int DY, int speed, ffc this)
{
    int angle = Angle(this->Misc[MV_INTERNAL_X], this->Misc[MV_INTERNAL_Y], DX, DY), cangle = Cos(angle), sangle = Sin(angle);

    this->Misc[MV_INTERNAL_X] += cangle*speed;
    this->Misc[MV_INTERNAL_Y] += sangle*speed;

    Viewport->X = this->Misc[MV_INTERNAL_X];
    Viewport->Y = this->Misc[MV_INTERNAL_Y];
}