//@ignore_object_type

int PIC;
int FIST_TRP[6];
int ARR_TP[25];
int ARR_TRP2[15];
int DROT[3];
int DROT2[4];
int SQ_ROW[24];
int STY_WLL[12];
int UNDER_ROT[36];

void InitArrowRows()
{
    int k;

    for (k = 15 ; k ; k --)
        ARR_TRP2[k - 1] = Object("ArrowTrap" + IntToString(k));
}

void InitFistTraps(int max)
{
    int k;

    for (k = 0 ; k < max ; k ++)
    {
        LookWithAngle(Object("FistPlate" + IntToString(k + 1)), k);
        FIST_TRP[k] = Object("FistTrap" + IntToString(k + 1));
    }
}

void InitArrowTraps()
{
    int k;

    for (k = 0 ; k < 7 ; k ++)
    {
        if (k < 5)
        {
            ARR_TP[k] = Object("WestGroup1Row" + IntToString(k + 1));
            ARR_TP[k + 5] = Object("WestGroup2Row" + IntToString(k + 1));
        }
        if (k < 4)
        {
            ARR_TP[k + 17] = Object("WestGroup4Row" + IntToString(k + 1));
            ARR_TP[k + 21] = Object("WestGroup5Row" + IntToString(k + 1));
        }
        ARR_TP[k + 10] = Object("WestGroup3Row" + IntToString(k + 1));
    }
}

void MagicHurricane()
{
    int unit = CreateObject("Maiden", 8);
    CreateObject("Maiden", 133);
    CreateObject("WhirlWind", 8);
    CreateObject("WhirlWind", 133);
    Frozen(unit, 1);
    Frozen(unit + 1, 1);
    SetDialog(unit, "NORMAL", WellOfRestoration, DummyFunction);
    SetDialog(unit + 1, "NORMAL", WellOfRestoration, DummyFunction);
}

void DummyFunction()
{
    //
}

void MapInitialize()
{
    MusicEvent();
    PIC = Random(0, 1);
    InitArrowRows();
    InitFistTraps(6);
    InitArrowTraps();
    MathSine(0, 0.0);

    InitFireway();
    CreateObject("RedPotion", 274);
    CreateObject("SilverKey", 285);
    CreateObject("SilverKey", 113);
    CreateObject("SilverKey", 393);
    CreateObject("SilverKey", 131);
    CreateObject("BoulderIndestructible", 132);
    FrameTimer(1, MagicHurricane);
    FrameTimer(2, InitSentryWalls);
    FrameTimer(10, InitDestroyRots);
    FrameTimer(10, MovingGenerators);
    FrameTimer(30, InitSquareRows);
    FrameTimerWithArg(80, 8 | (72 << 8) | (80 << 16), MovingSkull);
    FrameTimerWithArg(81, 8 | (114 << 8) | (137 << 16), MovingSkull);
}

void OpenEastWalls()
{
    int count;

    ObjectOff(self);
    Print("벽 하나가 열렸습니다");
    if (!count)
    {
        count = 1;
        WallOpen(Wall(65, 35));
        WallOpen(Wall(66, 36));
        WallOpen(Wall(67, 37));
    }
    else
    {
        WallOpen(Wall(63, 37));
        WallOpen(Wall(64, 38));
        WallOpen(Wall(65, 39));
    }
}

void ActivateWestRowsGroup1()
{
    ObjectOn(ARR_TP[0]);
    ObjectOn(ARR_TP[1]);
    ObjectOn(ARR_TP[2]);
    ObjectOn(ARR_TP[3]);
    ObjectOn(ARR_TP[4]);
    FrameTimerWithArg(1, 0 | 0x500, DisableArrowTraps);
}

void ActivateWestRowsGroup2()
{
    ObjectOn(ARR_TP[5]);
    ObjectOn(ARR_TP[6]);
    ObjectOn(ARR_TP[7]);
    ObjectOn(ARR_TP[8]);
    ObjectOn(ARR_TP[9]);
    FrameTimerWithArg(1, 5 | 0x500, DisableArrowTraps);
}

void ActivateWestRowsGroup3()
{
    ObjectOn(ARR_TP[10]);
    ObjectOn(ARR_TP[11]);
    ObjectOn(ARR_TP[12]);
    ObjectOn(ARR_TP[13]);
    ObjectOn(ARR_TP[14]);
    ObjectOn(ARR_TP[15]);
    ObjectOn(ARR_TP[16]);
    FrameTimerWithArg(1, 10 | (0x7 << 8), DisableArrowTraps);
}

void DisableArrowTraps(int ptr)
{
    int base = ptr & 0xff;
    int max = ptr >> 8;
    int k;

    for (k = 0 ; k < max ; k ++)
        ObjectOff(ARR_TP[k + base]);
}

void StartCryptBlocks()
{
    int unit[2];

    ObjectOff(self);
    if (!unit[0])
    {
        unit[0] = Object("CryptBlock1");
        unit[1] = Object("CryptBlock2");
        Move(unit[0], 10);
        Move(unit[1], 11);
    }
}

void ActivateMonoBlock()
{
    int flag;
    ObjectOff(self);
    if (!flag)
    {
        Move(Object("MonoBlock"), 35);
    }
    else
    {
        Move(Object("MonoBlock"), 38);
    }
    AudioEvent("SpikeBlockMove", 35);
    flag = (flag + 1) % 2;
    SecondTimerWithArg(5, GetTrigger(), DelayEnableUnit);
}

void DelayEnableUnit(int unit)
{
    ObjectOn(unit);
}

void ActivateDropFist()
{
    int cur = GetDirection(self);
    ObjectOff(self);
    ObjectOff(FIST_TRP[cur]);
    CastSpellObjectObject("SPELL_FIST", self, self);
    FrameTimerWithArg(120, GetTrigger(), ResetFistTrap);
}

void ResetFistTrap(int ptr)
{
    int cur = GetDirection(ptr);
    ObjectOn(ptr);
    ObjectOn(FIST_TRP[cur]);
    MoveWaypoint(16, GetObjectX(ptr), GetObjectY(ptr));
    AudioEvent("TriggerReleased", 16);
}

void OpenGenWalls()
{
    ObjectOff(self);
    WallOpen(Wall(183, 79));
    WallOpen(Wall(184, 80));
    WallOpen(Wall(185, 79));

    WallOpen(Wall(177, 85));
    WallOpen(Wall(177, 87));
    WallOpen(Wall(178, 86));

    WallOpen(Wall(192, 86));
    WallOpen(Wall(191, 87));
    WallOpen(Wall(192, 88));

    WallOpen(Wall(184, 94));
    WallOpen(Wall(185, 93));
    WallOpen(Wall(186, 94));
}

void WellOfRestoration()
{
    if (!HasEnchant(other, "ENCHANT_DETECTING"))
    {
        Print("이 우물이 잠시동안 당신의 체력을 지속적으로 회복시켜 줄 겁니다");
        Enchant(other, "ENCHANT_DETECTING", 12.0);
        MoveWaypoint(16, GetObjectX(other), GetObjectY(other));
        AudioEvent("LongBellsDown", 16);
        AudioEvent("RestoreHealth", 16);
        HealUnit(GetCaller());
    }
}

void HealUnit(int unit)
{
    if (CurrentHealth(unit) && HasEnchant(unit, "ENCHANT_DETECTING"))
    {
        RestoreHealth(unit, 3);
        Effect("GREATER_HEAL", GetObjectX(unit), GetObjectY(unit), GetObjectX(unit), GetObjectY(unit) - 100.0);
        FrameTimerWithArg(3, unit, HealUnit);
    }
}

void MovingSkull(int flag)
{
    int rep = flag & 0xff;
    int wp = (flag >> 8) & 0xff;
    int go = (flag >> 16) & 0xff;
    int unit;
    if (rep)
    {
        unit = CreateObject("SpinningSkull", wp);
        Frozen(unit, 1);
        CreateMover(unit, go, 22.0);
        FrameTimerWithArg(10, flag - 1, MovingSkull);
    }
}

void ShotSouthArrowPart1()
{
    ObjectOn(ARR_TRP2[0]);
    ObjectOn(ARR_TRP2[1]);
    ObjectOn(ARR_TRP2[2]);
    ObjectOn(ARR_TRP2[3]);
    FrameTimerWithArg(1, 0 | 0x400, DisableSouthArrowTraps);
}

void ShotSouthArrowPart2()
{
    ObjectOn(ARR_TRP2[4]);
    ObjectOn(ARR_TRP2[5]);
    ObjectOn(ARR_TRP2[6]);
    ObjectOn(ARR_TRP2[7]);
    ObjectOn(ARR_TRP2[8]);
    FrameTimerWithArg(1, 4 | 0x500, DisableSouthArrowTraps);
}

void ShotSouthArrowPart3()
{
    ObjectOn(ARR_TRP2[9]);
    ObjectOn(ARR_TRP2[10]);
    ObjectOn(ARR_TRP2[11]);
    ObjectOn(ARR_TRP2[12]);
    ObjectOn(ARR_TRP2[13]);
    ObjectOn(ARR_TRP2[14]);
    FrameTimerWithArg(1, 9 | 0x600, DisableSouthArrowTraps);
}

void DisableSouthArrowTraps(int ptr)
{
    int max = ptr >> 8;
    int base = ptr & 0xff;
    int k;

    for (k = 0 ; k < max ; k ++)
        ObjectOff(ARR_TRP2[base + k]);
}

void InitDestroyRots()
{
    DROT[0] = Object("DestroyGenRot1");
    DROT[1] = Object("DestroyGenRot2");
    DROT[2] = Object("DestroyGenRot3");
    Frozen(DROT[0], 1);
    Frozen(DROT[1], 1);
    Frozen(DROT[2], 1);
    CreateMover(DROT[0], 0, 40.0);
    CreateMover(DROT[1], 0, 40.0);
    CreateMover(DROT[2], 0, 40.0);
    DROT2[0] = Object("SouthGenRot1");
    DROT2[1] = Object("SouthGenRot2");
    DROT2[2] = Object("SouthGenRot3");
    DROT2[3] = Object("SouthGenRot4");
    Frozen(DROT2[0], 1);
    Frozen(DROT2[1], 1);
    Frozen(DROT2[2], 1);
    Frozen(DROT2[3], 1);
    CreateMover(DROT2[0], 0, 20.0);
    CreateMover(DROT2[1], 0, 20.0);
    CreateMover(DROT2[2], 0, 20.0);
    CreateMover(DROT2[3], 0, 20.0);
}

void ActivateDestroyGenRots()
{
    if (!GetDirection(DROT[0]))
    {
        Print("함정이 작동되었습니다");
        LookWithAngle(DROT[0], 1);
        FrameTimer(10, GoDestroyGenRots);
    }
}

void GoDestroyGenRots()
{
    if (GetObjectX(DROT[0]) <= 3990.0)
        MoveObject(DROT[0], GetObjectX(DROT[0]) + 2.0, GetObjectY(DROT[0]) - 2.0);
    if (GetObjectX(DROT[1]) <= 4036.0)
        MoveObject(DROT[1], GetObjectX(DROT[1]) + 2.0, GetObjectY(DROT[1]) - 2.0);
    if (GetObjectX(DROT[2]) <= 4082.0)
    {
        MoveObject(DROT[2], GetObjectX(DROT[2]) + 2.0, GetObjectY(DROT[2]) - 2.0);
        FrameTimer(1, GoDestroyGenRots);
    }
    else
        FrameTimer(1, GoDestroyRot2);
}

void GoDestroyRot2() //4013, 4036
{
    if (GetObjectX(DROT[1]) >= 4013.0)
        MoveObject(DROT[1], GetObjectX(DROT[1]) - 1.0, GetObjectY(DROT[1]) - 1.0);
    if (GetObjectX(DROT[2]) >= 4036.0)
    {
        MoveObject(DROT[2], GetObjectX(DROT[2]) - 2.0, GetObjectY(DROT[2]) - 2.0);
        FrameTimer(1, GoDestroyRot2);
    }
    else
        FrameTimer(1, GoDestroyGenRot3);
}

void GoDestroyGenRot3()
{
    if (GetObjectX(DROT[0]) >= 3576.0)
    {
        MoveObject(DROT[0], GetObjectX(DROT[0]) - 2.0, GetObjectY(DROT[0]) - 2.0);
        MoveObject(DROT[1], GetObjectX(DROT[1]) - 2.0, GetObjectY(DROT[1]) - 2.0);
        MoveObject(DROT[2], GetObjectX(DROT[2]) - 2.0, GetObjectY(DROT[2]) - 2.0);
        FrameTimer(1, GoDestroyGenRot3);
    }
    else
        FrameTimer(1, DestroyGenRotsGoHome);
}

void DestroyGenRotsGoHome()
{
    if (GetObjectY(DROT[0]) <= 4565.0)
        MoveObject(DROT[0], GetObjectX(DROT[0]) + 2.0, GetObjectY(DROT[0]) + 2.0);
    if (GetObjectY(DROT[1]) <= 4565.0)
        MoveObject(DROT[1], GetObjectX(DROT[1]) + 2.0, GetObjectY(DROT[1]) + 2.0);
    if (GetObjectY(DROT[2]) <= 4565.0)
    {
        MoveObject(DROT[2], GetObjectX(DROT[2]) + 2.0, GetObjectY(DROT[2]) + 2.0);
        FrameTimer(1, DestroyGenRotsGoHome);
    }
    else
    {
        Move(DROT[0], 5);
        Move(DROT[1], 6);
        Move(DROT[2], 7);
        FrameTimer(75, StandByDestroyGenRots);
    }
}

void StandByDestroyGenRots()
{
    if (Distance(GetObjectX(DROT[0]), GetObjectY(DROT[0]), GetWaypointX(5), GetWaypointY(5)) < 30.0)
        LookWithAngle(DROT[0], 0);
}

void MovingGenerators()
{
    CreateMover(Object("GenGrid01Generator01"), 32, 30.0);
    CreateMover(Object("GenGrid01Generator02"), 32, 30.0);
}

void DestroyGenByRots()
{
    if (CurrentHealth(self) && IsCaller(DROT[0]))
    {
        Damage(self, 0, 999, 14);
    }
}

void getCryptsGenerator4()
{
    int gnd;

    ObjectOff(self);
    if (!gnd) gnd = Object("ArrowTower");
    if (HasClass(other, "MONSTERGENERATOR"))
    {
        if (GetObjectX(self) < GetObjectX(gnd))
            CreateMover(other, 127, 25.0);
        else
            CreateMover(other, 129, 25.0);
    }
}

void shotArrowTower()
{
    int tower;
    int unit;

    if (!tower) tower = Object("ArrowTower");
    if (CurrentHealth(other))
    {
        MoveWaypoint(51, GetObjectX(tower) - UnitRatioX(tower, other, 32.0), GetObjectY(tower) - UnitRatioY(tower, other, 32.0));
        AudioEvent("FireGrate", 51);
        unit = CreateObject("OgreShuriken", 51);
        CreateObject("WeakFireball", 51);
        PushObject(unit, -40.0, GetObjectX(other), GetObjectY(other));
        PushObject(unit + 1, -40.0, GetObjectX(other), GetObjectY(other));
    }
}

void RemoveGenWalls()
{
    ObjectOff(self);
    if (PIC)
    {
        WallOpen(Wall(99, 129));
        WallOpen(Wall(100, 130));
        WallOpen(Wall(101, 131));
        WallOpen(Wall(102, 132));
        WallOpen(Wall(103, 133));
        WallOpen(Wall(104, 132));
        WallOpen(Wall(105, 131));
        WallOpen(Wall(106, 130));
        WallOpen(Wall(107, 129));
        PIC = 0;
    }
    else
    {
        WallOpen(Wall(99, 141));
        WallOpen(Wall(100, 140));
        WallOpen(Wall(101, 139));
        WallOpen(Wall(102, 138));
        WallOpen(Wall(103, 137));
        WallOpen(Wall(104, 138));
        WallOpen(Wall(105, 139));
        WallOpen(Wall(106, 140));
        WallOpen(Wall(107, 141));
        PIC = 1;
    }
}

void ActivateWestRowsGroup4()
{
    ObjectOn(ARR_TP[17]);
    ObjectOn(ARR_TP[18]);
    ObjectOn(ARR_TP[19]);
    ObjectOn(ARR_TP[20]);
    FrameTimerWithArg(1, 17 | 0x400, DisableArrowTraps);
}

void ActivateWestRowsGroup5()
{
    ObjectOn(ARR_TP[21]);
    ObjectOn(ARR_TP[22]);
    ObjectOn(ARR_TP[23]);
    ObjectOn(ARR_TP[24]);
    FrameTimerWithArg(1, 21 | 0x400, DisableArrowTraps);
}

void ActivateRotSouthRows()
{
    int k;
    if (!GetDirection(DROT2[0]))
    {
        for (k = 3 ; k >= 0 ; k --)
            Move(DROT2[k], Waypoint("SouthGenRotWP" + IntToString(k + 1)));
        LookWithAngle(DROT2[0], 1);
        FrameTimer(210, TurnSouthRots);
    }
}

void TurnSouthRots()
{
    int k;

    for (k = 3 ; k >= 0 ; k --)
        Move(DROT2[k], Waypoint("SouthGenRotBack" + IntToString(k + 1)));
    FrameTimerWithArg(210, DROT2[0], ResetSouthRow);
}

void ResetSouthRow(int unit)
{
    LookWithAngle(unit, 0);
}

float UnitRatioX(int unit, int target, float size)
{
    return (GetObjectX(unit) - GetObjectX(target)) * size / Distance(GetObjectX(unit), GetObjectY(unit), GetObjectX(target), GetObjectY(target));
}

float UnitRatioY(int unit, int target, float size)
{
    return (GetObjectY(unit) - GetObjectY(target)) * size / Distance(GetObjectX(unit), GetObjectY(unit), GetObjectX(target), GetObjectY(target));
}

void InitSquareRows()
{
    int k;

    for (k = 11 ; k >= 0 ; k --)
    {
        SQ_ROW[k] = Object("SquareBlock" + IntToString(k + 1));
        SQ_ROW[k + 12] = Waypoint("squareGo" + IntToString(k + 1));
    }
    SimpleRow();
    AnnexRow();
    FrameTimer(200, ControlSquareBlocks);
}

void ControlSquareBlocks()
{
    int k;

    for (k = 11 ; k >= 0 ; k --)
        Move(SQ_ROW[k], SQ_ROW[k + 12]);
    FrameTimer(240, ControlSquareBlocks);
}

int SimpleRow()
{
    int ptr;

    if (!ptr)
    {
        ptr = CreateObject("IronBlock", 89);
        CreateObject("IronBlock", 75);
        CreateObject("IronBlock", 74);
    }
    return ptr;
}

void ActivateSouthRows()
{
    int ptr;

    ObjectOff(self);
    if (!ptr)
    {
        ptr = SimpleRow();
        LookWithAngle(ptr, 120);
        LookWithAngle(ptr + 1, 119);
        LookWithAngle(ptr + 2, 117);
        CreateMover(ptr, 0, 15.0);
        CreateMover(ptr + 1, 0, 15.0);
        CreateMover(ptr + 2, 0, 15.0);
        FrameTimerWithArg(1, ptr, DelayMoveUnit);
        //89,75,74
    }
}

void DelayMoveUnit(int unit)
{
    Move(unit, GetDirection(unit));
    Move(unit + 1, GetDirection(unit + 1));
    Move(unit + 2, GetDirection(unit + 2));
}

int AnnexRow()
{
    int ptr;

    if (!ptr)
    {
        ptr = CreateObject("SpikeBlock", 106);
        CreateObject("SpikeBlock", 107);
        CreateObject("SpikeBlock", 108);
        CreateObject("SpikeBlock", 109);
        CreateObject("SpikeBlock", 110);
        CreateMover(ptr, 0, 20.0);
        CreateMover(ptr + 1, 0, 20.0);
        CreateMover(ptr + 2, 0, 20.0);
        CreateMover(ptr + 3, 0, 20.0);
        CreateMover(ptr + 4, 0, 20.0);
    }
    return ptr;
}

void ActivateBlockGroup01()
{
    if (!GetDirection(AnnexRow()))
    {
        Print("동력장치가 작동되었습니다");
        LookWithAngle(AnnexRow(), 1);
        FrameTimer(10, ControlSouthRowsSR);
    }
}

void ControlSouthRowsSR()
{
    int ptr = AnnexRow();
    int wp = GetDirection(ptr + 1) * 5;
    Move(ptr, 90 + wp);
    Move(ptr + 1, 91 + wp);
    Move(ptr + 2, 92 + wp);
    Move(ptr + 3, 93 + wp);
    Move(ptr + 4, 94 + wp);
    LookWithAngle(ptr + 2, wp);
    LookWithAngle(ptr + 1, (GetDirection(ptr + 1) + 1) % 2);
    FrameTimerWithArg(1, AnnexRow(), ResetSR);
}

void ResetSR(int ptr)
{
    int wp = GetDirection(ptr + 2);
    if (Distance(GetObjectX(ptr + 1), GetObjectY(ptr + 1), GetWaypointX(102 + wp), GetWaypointY(102 + wp)) > 20.0)
        FrameTimerWithArg(1, ptr, ResetSR);
    else
        LookWithAngle(ptr, 0);
}

void setBoundarySentry()
{
    int trap;
    int ptr;
    ObjectOff(self);
    if (!ptr)
    {
        trap = Object("SouthSentry");
        ptr = CreateMover(trap, 115, 20.0);
        ObjectOn(trap);
        TempData(ptr);
    }
}

int TempData(int num)
{
    int data;
    if (num)
        data = num;
    return data;
}

void InitSentryWalls()
{
    int k;

    for (k = 0 ; k < 12 ; k ++)
    {
        STY_WLL[k] = Wall(238 - k, 34 + k);
        WallOpen(STY_WLL[k]);
    }
}

void EnableSentryWallsRow1()
{
    SafeWalls(0);
}

void EnableSentryWallsRow2()
{
    SafeWalls(1);
}

void EnableSentryWallsRow3()
{
    SafeWalls(2);
}

void SafeWalls(int num)
{
    int k;

    for (k = 11 ; k >= 0 ; k --)
    {
        if ((k / 4) == num)
            WallClose(STY_WLL[k]);
        else
            WallOpen(STY_WLL[k]);
    }
}

void EastGenWallOpen1()
{
    ObjectOff(self);
    WallOpen(Wall(230, 16));
    OpenSentryGenWalls();
}

void EastGenWallOpen2()
{
    ObjectOff(self);
    WallOpen(Wall(237, 23));
    OpenSentryGenWalls();
}

void OpenSentryGenWalls()
{
    int count;

    count ++;
    if (count == 2)
    {
        WallOpen(Wall(231, 17));
        WallOpen(Wall(232, 18));
        WallOpen(Wall(233, 19));
        WallOpen(Wall(234, 20));
        WallOpen(Wall(235, 21));
        WallOpen(Wall(236, 22));
    }
}

void DisableBoundaryTrap()
{
    ObjectOff(self);
    ObjectOff(TempData(0));
    ObjectOff(Object("SouthSentry"));
    WallOpen(Wall(224, 50));
    WallOpen(Wall(225, 51));
    WallOpen(Wall(226, 52));
    WallOpen(Wall(228, 52));
    WallOpen(Wall(229, 51));
    WallOpen(Wall(230, 50));
}

void InitUnderFoot()
{
    int k;
    for (k = 5 ; k >= 0 ; k --)
    {
        UNDER_ROT[k] = Object("UnderRightRow" + IntToString(k + 1));
        UNDER_ROT[k + 6] = Waypoint("UnderRightGo" + IntToString(k + 1));
        UNDER_ROT[k + 12] = Waypoint("UnderRightHome" + IntToString(k + 1));
        UNDER_ROT[k + 18] = Object("UnderLeftRow" + IntToString(k + 1));
        UNDER_ROT[k + 24] = Waypoint("UnderLeftGo" + IntToString(k + 1));
        UNDER_ROT[k + 30] = Waypoint("UnderLeftHome" + IntToString(k + 1));
    }
    LookWithAngle(UNDER_ROT[0], 0);
}

void UnderfootToggleRots()
{
    int wp = GetDirection(UNDER_ROT[0]) * 6;
    int k;

    for (k = 5 ; k >= 0 ; k --)
    {
        Move(UNDER_ROT[k], UNDER_ROT[wp + k + 6]);
        Move(UNDER_ROT[k + 18], UNDER_ROT[wp + k + 24]);
    }
    LookWithAngle(UNDER_ROT[0], (GetDirection(UNDER_ROT[0]) + 1) % 2);
    FrameTimer(90, UnderfootToggleRots);
}

void OpenHiddenGen()
{
    ObjectOff(self);
    WallOpen(Wall(43, 193));
    WallOpen(Wall(42, 194));
}

void StartFireway()
{
    ObjectOff(self);
    InitUnderFoot();
    FrameTimer(10, UnderfootToggleRots);
    FrameTimer(100, FirewalkTrap);
}

float MathSine(int angle, float size)
{
    float var_0[91];
    int i;
    int k;
 
    if (!AnyFloatToInt(var_0[90]))
    {
        k = MathRingCore(193);
        Delete(k);
        for (i = 0 ; i <= 90 ; i ++)
        {
            var_0[i] = GetObjectZ(k + i + 1);
            Delete(k + i + 1);
        }
        return var_0[0];
    }

    k = angle / 90;
    i = angle - (k * 90);
 
    k %= 2;
    if (k == 1)
        i = 90 - i;
    if ((angle / 180) % 2 == 1)
        return -var_0[i] * size;
	else
		return var_0[i] * size;
}

int MathRingCore(int wp)
{
    float x_ratio;
    float y_ratio;
    string name = "InvisibleLightBlueLow";
    int unit = CreateObject(name, wp);
    int i;

    MoveWaypoint(wp + 1, GetWaypointX(wp), GetWaypointY(wp) - 1.0);
    for (i = 0 ; i <= 90 ; i ++)
    {
        x_ratio = WayRatioXY(wp, wp + 1, 0);
        y_ratio = WayRatioXY(wp, wp + 1, 1);
        MoveWaypoint(wp + 1, GetWaypointX(wp) - x_ratio, GetWaypointY(wp) - y_ratio);
        CreateObject(name, wp + 1);
        Raise(unit + i + 1, GetWaypointX(wp) - GetWaypointX(wp + 1));
        MoveWaypoint(wp + 1, GetWaypointX(wp) - (1.0 / 57.3 * y_ratio) - x_ratio, GetWaypointY(wp) + (1.0 / 57.3 * x_ratio) - y_ratio);
    }
    return unit;
}

float WayRatioXY(int wp1, int wp2, int mode)
{
    if (!mode)
        return (GetWaypointX(wp1) - GetWaypointX(wp2)) * 1.0 / Distance(GetWaypointX(wp1), GetWaypointY(wp1), GetWaypointX(wp2), GetWaypointY(wp2));
    else
        return (GetWaypointY(wp1) - GetWaypointY(wp2)) * 1.0 / Distance(GetWaypointX(wp1), GetWaypointY(wp1), GetWaypointX(wp2), GetWaypointY(wp2));
}

int AnyFloatToInt(float x)
{
    StopScript(x);
}

void SummonCreature()
{
    int unit;
    MoveWaypoint(22, GetObjectX(other), GetObjectY(other));
    Delete(other);
    unit = CreateObject("WeirdlingBeast", 22);
    SetOwner(self, unit);
    LookAtObject(unit, self);
    LookWithAngle(unit, GetDirection(unit) + 128);
    CreatureGuard(unit, GetObjectX(unit), GetObjectY(unit), GetObjectX(unit) + UnitAngleCos(unit, 20.0), GetObjectY(unit) + UnitAngleSin(unit, 20.0), 450.0);
    SetCallback(unit, 3, ShotWeapon);
    DeleteObjectTimer(unit, 1);
}

void ShotWeapon()
{
    int mis;

    MoveWaypoint(22, GetObjectX(self) - UnitRatioX(self, other, 20.0), GetObjectY(self) - UnitRatioY(self, other, 20.0));
    mis = CreateObject("DeathBallFragment", 22);
    SetOwner(self, mis);
    PushObject(mis, -20.0, GetObjectX(other), GetObjectY(other));
    DeleteObjectTimer(mis, 60);
}

float UnitAngleCos(int unit, float size)
{
    return MathSine((GetDirection(unit) * 45 / 32) + 90, size);
}

float UnitAngleSin(int unit, float size)
{
    return MathSine(GetDirection(unit) * 45 / 32, size);
}

void RemoveExitWalls()
{
    WallOpen(Wall(33, 133));
    WallOpen(Wall(34, 134));
    WallOpen(Wall(33, 135));
    WallOpen(Wall(32, 136));
    WallOpen(Wall(31, 137));
    WallOpen(Wall(30, 138));
    WallOpen(Wall(29, 139));
    WallOpen(Wall(28, 140));
    WallOpen(Wall(27, 139));
}

void NotCrashStaff()
{
    int var_0;
    int var_1 = 0;

    var_0 = GetLastItem(other);
    while(IsObjectOn(var_0)) {
        if (HasClass(var_0, "WAND") && !HasEnchant(var_0, "ENCHANT_INVULNERABLE")) {
            var_1 ++;
            Enchant(var_0, "ENCHANT_INVULNERABLE", 0.0);
        }
        var_0 = GetPreviousItem(var_0);
    }
    if (var_1 > 0) {
        PrintToAll("처리결과: 총 " + IntToString(var_1) + " 개의 아이템을 무적화 했습니다 .");
        Enchant(other, "ENCHANT_FREEZE", 1.0);
    }
}

void NotCrashWeapon()
{
    int var_0;
    int var_1 = 0;

    var_0 = GetLastItem(other);
    while (IsObjectOn(var_0)) {
        if (HasClass(var_0, "WEAPON") && !HasEnchant(var_0, "ENCHANT_INVULNERABLE")) {
            var_1 ++;
            Enchant(var_0, "ENCHANT_INVULNERABLE", 0.0);
        }
        var_0 = GetPreviousItem(var_0);
    }
    if (var_1 > 0) {
        PrintToAll("처리결과: 총 " + IntToString(var_1) + " 개의 아이템을 무적화 했습니다 .");
        Enchant(other, "ENCHANT_FREEZE", 1.0);
    }
}

void NotCrashArmor()
{
    int var_0;
    int var_1 = 0;

    var_0 = GetLastItem(other);
    while(IsObjectOn(var_0)) {
        if (HasClass(var_0, "ARMOR") && !HasEnchant(var_0, "ENCHANT_INVULNERABLE")) {
            var_1 ++;
            Enchant(var_0, "ENCHANT_INVULNERABLE", 0.0);
        }
        var_0 = GetPreviousItem(var_0);
    }
    if (var_1 > 0) {
        PrintToAll("처리결과: 총 " + IntToString(var_1) + " 개의 아이템을 무적화 했습니다 .");
        Enchant(other, "ENCHANT_FREEZE", 1.0);
    }
}

int AnyStrToInt(string x)
{
    StopScript(x);
}

string AnyIntToStr(int x)
{
    StopScript(x);
}

string FlameTable(int num)
{
    string table = "SmallFlamE"; "MediumFlamE"; "FlamE";

    return AnyIntToStr(AnyStrToInt(table) + num);
}

void InitFireway()
{
    float temp_x;
    float temp_y;

    if (!AnyFloatToInt(temp_x))
    {
        temp_x = GetWaypointX(126);
        temp_y = GetWaypointY(126);
    }
    else
    {
        MoveWaypoint(126, temp_x, temp_y);
    }
}

//9x8
void FirewalkTrap()
{
    int k;
    int line;
    int ptr;

    if (line < 9)
    {
        MoveWaypoint(125, GetWaypointX(126), GetWaypointY(126));
        AudioEvent("FireExtinguish", 125);
        ptr = CreateObject("InvisibleLightBlueHigh", 125);
        for (k = 7 ; k >= 0 ; k --)
        {
            CreateObject(FlameTable(0), 125);
            MoveWaypoint(125, GetWaypointX(125) - 23.0, GetWaypointY(125) + 23.0);
        }
        Delete(ptr);
        FrameTimerWithArg(4, ptr + 1, SpawnMedFlame);
        MoveWaypoint(126, GetWaypointX(126) - 23.0, GetWaypointY(126) - 23.0);
        line ++;
        FrameTimer(6, FirewalkTrap);
    }
    else
    {
        line = 0;
        InitFireway();
        FrameTimer(50, FirewalkTrap);
    }
}

void SpawnMedFlame(int ptr)
{
    int k;
    int ptr2 = CreateObject("InvisibleLightBlueHigh", 187);

    for (k = 7 ; k >= 0 ; k --)
    {
        MoveWaypoint(187, GetObjectX(ptr + k), GetObjectY(ptr + k));
        Delete(ptr + k);
        CreateObject(FlameTable(1), 187);
    }
    Delete(ptr2);
    FrameTimerWithArg(4, ptr2 + 1, SpawnNormalFlame);
}

void SpawnNormalFlame(int ptr)
{
    int k;
    int ptr2 = CreateObject("InvisibleLightBlueHigh", 187);

    for (k = 7 ; k >= 0 ; k --)
    {
        MoveWaypoint(187, GetObjectX(ptr + k), GetObjectY(ptr + k));
        Delete(ptr + k);
        CreateObject(FlameTable(2), 187);
    }
    Delete(ptr2);
    FrameTimerWithArg(4, ptr2 + 1, RemoveAllFlames);
}

void RemoveAllFlames(int ptr)
{
    int k;
    for (k = 7 ; k >= 0 ; k --)
        Delete(ptr + k);
}