コード例 #1
0
ファイル: PoolUnit.cs プロジェクト: n-stefan/SharpDune
    /*
     * Recount all Units, ignoring the cache array. Also set the unitCount
     *  of all houses to zero.
     */
    internal static void Unit_Recount()
    {
        ushort index;
        var    find = new PoolFindStruct();

        unchecked { find.houseID = (byte)-1; find.type = (ushort)-1; find.index = (ushort)-1; }
        var h = House_Find(find);

        while (h != null)
        {
            h.unitCount = 0;
            h           = House_Find(find);
        }

        g_unitFindCount = 0;

        for (index = 0; index < (ushort)UnitIndex.UNIT_INDEX_MAX; index++)
        {
            var u = Unit_Get_ByIndex(index);
            if (!u.o.flags.used)
            {
                continue;
            }

            h = House_Get_ByIndex(u.o.houseID);
            h.unitCount++;

            g_unitFindArray[g_unitFindCount++] = u;
        }
    }
コード例 #2
0
    static uint s_tickTeamGameLoop; /*!< Indicates next time the GameLoop function is executed. */

    /*
     * Loop over all teams, performing various of tasks.
     */
    internal static void GameLoop_Team()
    {
        var find = new PoolFindStruct();

        if (s_tickTeamGameLoop > g_timerGame)
        {
            return;
        }
        s_tickTeamGameLoop = (uint)(g_timerGame + (Tools_Random_256() & 7) + 5);

        find.houseID = (byte)HouseType.HOUSE_INVALID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        g_scriptCurrentObject    = null;
        g_scriptCurrentUnit      = null;
        g_scriptCurrentStructure = null;

        while (true)
        {
            CTeam  t;
            CHouse h;

            t = Team_Find(find);
            if (t == null)
            {
                break;
            }

            h = House_Get_ByIndex(t.houseID);

            g_scriptCurrentTeam = t;

            if (!h.flags.isAIActive)
            {
                continue;
            }

            if (t.script.delay != 0)
            {
                t.script.delay--;
                continue;
            }

            if (!Script_IsLoaded(t.script))
            {
                continue;
            }

            if (!Script_Run(t.script))
            {
                /* ENHANCEMENT -- Dune2 aborts all other teams if one gives a script error. This doesn't seem correct */
                if (g_dune2_enhanced)
                {
                    continue;
                }
                break;
            }
        }
    }
コード例 #3
0
    /*
     * Save all new Units information to a file. It converts pointers to indices
     *   where needed.
     * @param fp The file to save to.
     * @return True if and only if all bytes were written successful.
     */
    internal static bool UnitNew_Save(BinaryWriter fp)
    {
        var find = new PoolFindStruct
        {
            houseID = (byte)HouseType.HOUSE_INVALID,
            type    = 0xFFFF,
            index   = 0xFFFF
        };

        while (true)
        {
            CUnit u;

            u = Unit_Find(find);
            if (u == null)
            {
                break;
            }

            if (!SaveLoad_Save(s_saveUnitNewIndex, fp, u.o))
            {
                return(false);
            }
            if (!SaveLoad_Save(s_saveUnitNew, fp, u))
            {
                return(false);
            }
        }

        return(true);
    }
コード例 #4
0
    /*
     * Save all Teams to a file. It converts pointers to indices where needed.
     * @param fp The file to save to.
     * @return True if and only if all bytes were written successful.
     */
    internal static bool Team_Save(BinaryWriter fp)
    {
        var find = new PoolFindStruct
        {
            houseID = (byte)HouseType.HOUSE_INVALID,
            type    = 0xFFFF,
            index   = 0xFFFF
        };

        while (true)
        {
            CTeam t;

            t = Team_Find(find);
            if (t == null)
            {
                break;
            }

            if (!SaveLoad_Save(s_saveTeam, fp, t))
            {
                return(false);
            }
        }

        return(true);
    }
コード例 #5
0
ファイル: PoolStructure.cs プロジェクト: n-stefan/SharpDune
    /*
     * Recount all Structures, ignoring the cache array. Also set the structureCount
     *  of all houses to zero.
     */
    internal static void Structure_Recount()
    {
        ushort index;
        var    find = new PoolFindStruct();

        unchecked { find.houseID = (byte)-1; find.type = (ushort)-1; find.index = (ushort)-1; }
        var h = House_Find(find);

        while (h != null)
        {
            h.unitCount = 0;
            h           = House_Find(find);
        }

        g_structureFindCount = 0;

        for (index = 0; index < (ushort)StructureIndex.STRUCTURE_INDEX_MAX_SOFT; index++)
        {
            var s = Structure_Get_ByIndex(index);
            if (s.o.flags.used)
            {
                g_structureFindArray[g_structureFindCount++] = s;
            }
        }
    }
コード例 #6
0
    /*
     * Save all Structures to a file. It converts pointers to indices where needed.
     * @param fp The file to save to.
     * @return True if and only if all bytes were written successful.
     */
    internal static bool Structure_Save(BinaryWriter fp)
    {
        var find = new PoolFindStruct
        {
            houseID = (byte)HouseType.HOUSE_INVALID,
            type    = 0xFFFF,
            index   = 0xFFFF
        };

        while (true)
        {
            CStructure s;

            s = Structure_Find(find);
            if (s == null)
            {
                break;
            }

            if (!SaveLoad_Save(s_saveStructure, fp, s))
            {
                return(false);
            }
        }

        return(true);
    }
コード例 #7
0
ファイル: PoolUnit.cs プロジェクト: n-stefan/SharpDune
    //internal static void Unit_Set_ByIndex(Unit u)
    //{
    //	Debug.Assert(u.o.index < (ushort)UnitIndex.UNIT_INDEX_MAX);
    //	g_unitArray[u.o.index] = u;
    //}

    /*
     * Find the first matching Unit based on the PoolFindStruct filter data.
     *
     * @param find A pointer to a PoolFindStruct which contains filter data and
     * last known tried index. Calling this functions multiple times with the
     * same 'find' parameter walks over all possible values matching the filter.
     * @return The Unit, or NULL if nothing matches (anymore).
     */
    internal static CUnit Unit_Find(PoolFindStruct find)
    {
        if (find.index >= g_unitFindCount && find.index != 0xFFFF)
        {
            return(null);
        }
        find.index++; /* First, we always go to the next index */

        for (; find.index < g_unitFindCount; find.index++)
        {
            var u = g_unitFindArray[find.index];
            if (u == null)
            {
                continue;
            }

            if (u.o.flags.isNotOnMap && g_validateStrictIfZero == 0)
            {
                continue;
            }
            if (find.houseID != (byte)HouseType.HOUSE_INVALID && find.houseID != Unit_GetHouseID(u))
            {
                continue;
            }
            if (find.type != (ushort)UnitIndex.UNIT_INDEX_INVALID && find.type != u.o.type)
            {
                continue;
            }

            return(u);
        }

        return(null);
    }
コード例 #8
0
    //internal static void House_Set_ByIndex(House h)
    //{
    //    Debug.Assert(h.index < (byte)HouseIndex.HOUSE_INDEX_MAX);
    //    g_houseArray[h.index] = h;
    //}

    /*
     * Find the first matching House based on the PoolFindStruct filter data.
     *
     * @param find A pointer to a PoolFindStruct which contains filter data and
     *   last known tried index. Calling this functions multiple times with the
     *   same 'find' parameter walks over all possible values matching the filter.
     * @return The House, or NULL if nothing matches (anymore).
     */
    internal static CHouse House_Find(PoolFindStruct find)
    {
        if (find.index >= g_houseFindCount && find.index != 0xFFFF)
        {
            return(null);
        }
        find.index++; /* First, we always go to the next index */

        for (; find.index < g_houseFindCount; find.index++)
        {
            var h = g_houseFindArray[find.index];
            if (h != null)
            {
                return(h);
            }
        }

        return(null);
    }
コード例 #9
0
    /*
     * Gets the best target for the current team.
     *
     * Stack: *none*.
     *
     * @param script The script engine to operate on.
     * @return The encoded index of the best target or 0 if none found.
     */
    internal static ushort Script_Team_FindBestTarget(ScriptEngine _)
    {
        CTeam t;
        var   find = new PoolFindStruct();

        t = g_scriptCurrentTeam;

        find.houseID = t.houseID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        while (true)
        {
            CUnit  u;
            ushort target;

            u = Unit_Find(find);
            if (u == null)
            {
                break;
            }
            if (u.team - 1 != t.index)
            {
                continue;
            }
            target = Unit_FindBestTargetEncoded(u, (ushort)(t.action == (ushort)TeamActionType.TEAM_ACTION_KAMIKAZE ? 4 : 0));
            if (target == 0)
            {
                continue;
            }
            if (t.target == target)
            {
                return(target);
            }

            t.target     = target;
            t.targetTile = Tile_GetTileInDirectionOf(Tile_PackTile(u.o.position), Tools_Index_GetPackedTile(target));
            return(target);
        }

        return(0);
    }
コード例 #10
0
ファイル: House.cs プロジェクト: n-stefan/SharpDune
    /*
     * Update the CreditsStorage by walking over all structures and checking what
     *  they can hold.
     * @param houseID The house to check the storage for.
     */
    internal static void House_UpdateCreditsStorage(byte houseID)
    {
        var  find = new PoolFindStruct();
        uint creditsStorage;

        var oldValidateStrictIfZero = g_validateStrictIfZero;

        g_validateStrictIfZero = 0;

        find.houseID = houseID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        creditsStorage = 0;
        while (true)
        {
            StructureInfo si;
            CStructure    s;

            s = Structure_Find(find);
            if (s == null)
            {
                break;
            }

            si              = g_table_structureInfo[s.o.type];
            creditsStorage += si.creditsStorage;
        }

        if (creditsStorage > 32000)
        {
            creditsStorage = 32000;
        }

        House_Get_ByIndex(houseID).creditsStorage = (ushort)creditsStorage;

        g_validateStrictIfZero = oldValidateStrictIfZero;
    }
コード例 #11
0
    //internal static void Team_Set_ByIndex(Team t)
    //{
    //	Debug.Assert(t.index < (ushort)TeamIndex.TEAM_INDEX_MAX);
    //	g_teamArray[t.index] = t;
    //}

    /*
     * Find the first matching Team based on the PoolFindStruct filter data.
     *
     * @param find A pointer to a PoolFindStruct which contains filter data and
     *   last known tried index. Calling this functions multiple times with the
     *   same 'find' parameter walks over all possible values matching the filter.
     * @return The Team, or NULL if nothing matches (anymore).
     */
    internal static CTeam Team_Find(PoolFindStruct find)
    {
        if (find.index >= g_teamFindCount && find.index != 0xFFFF)
        {
            return(null);
        }
        find.index++; /* First, we always go to the next index */

        for (; find.index < g_teamFindCount; find.index++)
        {
            var t = g_teamFindArray[find.index];
            if (t == null)
            {
                continue;
            }

            if (find.houseID == (byte)HouseType.HOUSE_INVALID || find.houseID == t.houseID)
            {
                return(t);
            }
        }

        return(null);
    }
コード例 #12
0
ファイル: PoolStructure.cs プロジェクト: n-stefan/SharpDune
    //internal static void Structure_Set_ByIndex(Structure s)
    //{
    //    Debug.Assert(s.o.index < (ushort)StructureIndex.STRUCTURE_INDEX_MAX_HARD);
    //    g_structureArray[s.o.index] = s;
    //}

    /*
     * Find the first matching Structure based on the PoolFindStruct filter data.
     *
     * @param find A pointer to a PoolFindStruct which contains filter data and
     *   last known tried index. Calling this functions multiple times with the
     *   same 'find' parameter walks over all possible values matching the filter.
     * @return The Structure, or NULL if nothing matches (anymore).
     */
    internal static CStructure Structure_Find(PoolFindStruct find)
    {
        if (find.index >= g_structureFindCount + 3 && find.index != 0xFFFF)
        {
            return(null);
        }
        find.index++; /* First, we always go to the next index */

        Debug.Assert(g_structureFindCount <= (ushort)StructureIndex.STRUCTURE_INDEX_MAX_SOFT);
        for (; find.index < g_structureFindCount + 3; find.index++)
        {
            CStructure s = null;

            if (find.index < g_structureFindCount)
            {
                s = g_structureFindArray[find.index];
            }
            else
            {
                /* There are 3 special structures that are never in the Find array */
                Debug.Assert(find.index - g_structureFindCount < 3);
                switch (find.index - g_structureFindCount)
                {
                case 0:
                    s = Structure_Get_ByIndex((ushort)StructureIndex.STRUCTURE_INDEX_WALL);
                    if (s.o.index != (ushort)StructureIndex.STRUCTURE_INDEX_WALL)
                    {
                        continue;
                    }
                    break;

                case 1:
                    s = Structure_Get_ByIndex((ushort)StructureIndex.STRUCTURE_INDEX_SLAB_2x2);
                    if (s.o.index != (ushort)StructureIndex.STRUCTURE_INDEX_SLAB_2x2)
                    {
                        continue;
                    }
                    break;

                case 2:
                    s = Structure_Get_ByIndex((ushort)StructureIndex.STRUCTURE_INDEX_SLAB_1x1);
                    if (s.o.index != (ushort)StructureIndex.STRUCTURE_INDEX_SLAB_1x1)
                    {
                        continue;
                    }
                    break;
                }
            }
            if (s == null)
            {
                continue;
            }

            if (s.o.flags.isNotOnMap && g_validateStrictIfZero == 0)
            {
                continue;
            }
            if (find.houseID != (byte)HouseType.HOUSE_INVALID && find.houseID != s.o.houseID)
            {
                continue;
            }
            if (find.type != (ushort)StructureIndex.STRUCTURE_INDEX_INVALID && find.type != s.o.type)
            {
                continue;
            }

            return(s);
        }

        return(null);
    }
コード例 #13
0
ファイル: ScriptStructure.cs プロジェクト: n-stefan/SharpDune
    /*
     * Find a Unit which is within range and not an ally.
     *
     * Stack: 1 - Range to find a target in (amount of tiles multiplied with 256).
     *
     * @param script The script engine to operate on.
     * @return The Unit Index of the closest unit within range and not friendly,
     *   or 0 if none exists.
     */
    internal static ushort Script_Structure_FindTargetUnit(ScriptEngine script)
    {
        var        find = new PoolFindStruct();
        CStructure s;
        CUnit      u;
        uint       distanceCurrent;
        uint       targetRange;
        Tile32     position;

        s               = g_scriptCurrentStructure;
        targetRange     = STACK_PEEK(script, 1);
        distanceCurrent = 32000;
        u               = null;

        find.houseID = (byte)HouseType.HOUSE_INVALID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        /* ENHANCEMENT -- The original code calculated distances from the top-left corner of the structure. */
        position = g_dune2_enhanced ? Tile_Center(s.o.position) : s.o.position;

        while (true)
        {
            ushort distance;
            CUnit  uf;

            uf = Unit_Find(find);
            if (uf == null)
            {
                break;
            }

            if (House_AreAllied(s.o.houseID, Unit_GetHouseID(uf)))
            {
                continue;
            }

            if (uf.o.type != (byte)UnitType.UNIT_ORNITHOPTER)
            {
                if ((uf.o.seenByHouses & (1 << s.o.houseID)) == 0)
                {
                    continue;
                }
            }

            distance = Tile_GetDistance(uf.o.position, position);
            if (distance >= distanceCurrent)
            {
                continue;
            }

            if (g_dune2_enhanced)
            {
                if (uf.o.type == (byte)UnitType.UNIT_ORNITHOPTER)
                {
                    if (distance > targetRange * 3)
                    {
                        continue;
                    }
                }
                else
                {
                    if (distance > targetRange)
                    {
                        continue;
                    }
                }
            }
            else
            {
                if (uf.o.type == (byte)UnitType.UNIT_ORNITHOPTER)
                {
                    if (distance >= targetRange * 3)
                    {
                        continue;
                    }
                }
                else
                {
                    if (distance >= targetRange)
                    {
                        continue;
                    }
                }
            }

            /* ENHANCEMENT -- The original code swapped the assignment, making it do nothing, Now it finds the closest unit to shoot at, what seems to be the intention */
            if (g_dune2_enhanced)
            {
                distanceCurrent = distance;
            }
            u = uf;
        }

        if (u == null)
        {
            return((ushort)IndexType.IT_NONE);
        }
        return(Tools_Index_Encode(u.o.index, IndexType.IT_UNIT));
    }
コード例 #14
0
ファイル: Viewport.cs プロジェクト: n-stefan/SharpDune
    /*
     * Redraw parts of the viewport that require redrawing.
     *
     * @param forceRedraw If true, dirty flags are ignored, and everything is drawn.
     * @param hasScrolled Viewport position has changed
     * @param drawToMainScreen True if and only if we are drawing to the main screen and not some buffer screen.
     */
    internal static void GUI_Widget_Viewport_Draw(bool forceRedraw, bool hasScrolled, bool drawToMainScreen)
    {
        var paletteHouse = new byte[16]; /*!< Used for palette manipulation to get housed coloured units etc. */

        paletteHouse[0] = 0;
        ushort x;
        ushort y;
        ushort i;
        ushort curPos;
        bool   updateDisplay;
        Screen oldScreenID;
        ushort oldWidgetID;
        var    minX = new short[10];
        var    maxX = new short[10];

        var find = new PoolFindStruct();

        updateDisplay = forceRedraw;

        Array.Fill <short>(minX, 0xF, 0, minX.Length); //memset(minX, 0xF, sizeof(minX));
                                                       //Array.Fill<short>(maxX, 0,   0, minX.Length); //memset(maxX, 0,   sizeof(minX));

        oldScreenID = GFX_Screen_SetActive(Screen.NO1);

        oldWidgetID = Widget_SetCurrentWidget(2);

        if (g_dirtyViewportCount != 0 || forceRedraw)
        {
            for (y = 0; y < 10; y++)
            {
                var top = (ushort)((y << 4) + 0x28); /* 40 */
                for (x = 0; x < (drawToMainScreen ? 15 : 16); x++)
                {
                    CTile  t;
                    ushort left;

                    curPos = (ushort)(g_viewportPosition + Tile_PackXY(x, y));

                    if (x < 15 && !forceRedraw && BitArray_Test(g_dirtyViewport, curPos))
                    {
                        if (maxX[y] < x)
                        {
                            maxX[y] = (short)x;
                        }
                        if (minX[y] > x)
                        {
                            minX[y] = (short)x;
                        }
                        updateDisplay = true;
                    }

                    if (!BitArray_Test(g_dirtyMinimap, curPos) && !forceRedraw)
                    {
                        continue;
                    }

                    BitArray_Set(g_dirtyViewport, curPos);

                    if (x < 15)
                    {
                        updateDisplay = true;
                        if (maxX[y] < x)
                        {
                            maxX[y] = (short)x;
                        }
                        if (minX[y] > x)
                        {
                            minX[y] = (short)x;
                        }
                    }

                    t    = g_map[curPos];
                    left = (ushort)(x << 4);

                    if (!g_debugScenario && g_veiledTileID == t.overlayTileID)
                    {
                        /* draw a black rectangle */
                        GUI_DrawFilledRectangle((short)left, (short)top, (short)(left + 15), (short)(top + 15), 12);
                        continue;
                    }

                    GFX_DrawTile(t.groundTileID, left, top, t.houseID);

                    if (t.overlayTileID != 0 && !g_debugScenario)
                    {
                        GFX_DrawTile(t.overlayTileID, left, top, t.houseID);
                    }
                }
            }
            g_dirtyViewportCount = 0;
        }

        /* Draw Sandworm */
        find.type    = (ushort)UnitType.UNIT_SANDWORM;
        find.index   = 0xFFFF;
        find.houseID = (byte)HouseType.HOUSE_INVALID;

        while (true)
        {
            CUnit  u;
            byte[] sprite;

            u = Unit_Find(find);

            if (u == null)
            {
                break;
            }

            if (!u.o.flags.isDirty && !forceRedraw)
            {
                continue;
            }
            u.o.flags.isDirty = false;

            if (!g_map[Tile_PackTile(u.o.position)].isUnveiled && !g_debugScenario)
            {
                continue;
            }

            sprite = g_sprites[g_table_unitInfo[u.o.type].groundSpriteID];
            GUI_Widget_Viewport_GetSprite_HousePalette(sprite, Unit_GetHouseID(u), paletteHouse);

            if (Map_IsPositionInViewport(u.o.position, out x, out y))
            {
                GUI_DrawSprite(Screen.ACTIVE, sprite, (short)x, (short)y, 2, DRAWSPRITE_FLAG_BLUR | DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER);
            }
            if (Map_IsPositionInViewport(u.targetLast, out x, out y))
            {
                GUI_DrawSprite(Screen.ACTIVE, sprite, (short)x, (short)y, 2, DRAWSPRITE_FLAG_BLUR | DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER);
            }
            if (Map_IsPositionInViewport(u.targetPreLast, out x, out y))
            {
                GUI_DrawSprite(Screen.ACTIVE, sprite, (short)x, (short)y, 2, DRAWSPRITE_FLAG_BLUR | DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER);
            }
            if (u == g_unitSelected && Map_IsPositionInViewport(u.o.position, out x, out y))
            {
                GUI_DrawSprite(Screen.ACTIVE, g_sprites[6], (short)x, (short)y, 2, DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER);
            }
        }

        if (g_unitSelected == null && (g_selectionRectangleNeedRepaint || hasScrolled) && (Structure_Get_ByPackedTile(g_selectionRectanglePosition) != null || g_selectionType == (ushort)SelectionType.PLACE || g_debugScenario))
        {
            var x1 = (ushort)((Tile_GetPackedX(g_selectionRectanglePosition) - Tile_GetPackedX(g_minimapPosition)) << 4);
            var y1 = (ushort)(((Tile_GetPackedY(g_selectionRectanglePosition) - Tile_GetPackedY(g_minimapPosition)) << 4) + 0x28);
            var x2 = (ushort)(x1 + (g_selectionWidth << 4) - 1);
            var y2 = (ushort)(y1 + (g_selectionHeight << 4) - 1);

            GUI_SetClippingArea(0, 40, 239, SCREEN_HEIGHT - 1);
            GUI_DrawWiredRectangle(x1, y1, x2, y2, 0xFF);

            if (g_selectionState == 0 && g_selectionType == (ushort)SelectionType.PLACE)
            {
                GUI_DrawLine((short)x1, (short)y1, (short)x2, (short)y2, 0xFF);
                GUI_DrawLine((short)x2, (short)y1, (short)x1, (short)y2, 0xFF);
            }

            GUI_SetClippingArea(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);

            g_selectionRectangleNeedRepaint = false;
        }

        /* Draw ground units */
        if (g_dirtyUnitCount != 0 || forceRedraw || updateDisplay)
        {
            find.type    = 0xFFFF;
            find.index   = 0xFFFF;
            find.houseID = (byte)HouseType.HOUSE_INVALID;

            while (true)
            {
                CUnit    u;
                UnitInfo ui;
                ushort   packed;
                byte     orientation;
                ushort   index;
                ushort   spriteFlags = 0;

                u = Unit_Find(find);

                if (u == null)
                {
                    break;
                }

                if (u.o.index is < 20 or > 101)
                {
                    continue;
                }

                packed = Tile_PackTile(u.o.position);

                if ((!u.o.flags.isDirty || u.o.flags.isNotOnMap) && !forceRedraw && !BitArray_Test(g_dirtyViewport, packed))
                {
                    continue;
                }
                u.o.flags.isDirty = false;

                if (!g_map[packed].isUnveiled && !g_debugScenario)
                {
                    continue;
                }

                ui = g_table_unitInfo[u.o.type];

                if (!Map_IsPositionInViewport(u.o.position, out x, out y))
                {
                    continue;
                }

                x += g_table_tilediff[0][u.wobbleIndex].x;
                y += g_table_tilediff[0][u.wobbleIndex].y;

                orientation = Orientation_Orientation256ToOrientation8((byte)u.orientation[0].current);

                if (u.spriteOffset >= 0 || ui.destroyedSpriteID == 0)
                {
                    index = ui.groundSpriteID;

                    switch ((DisplayMode)ui.displayMode)
                    {
                    case DisplayMode.UNIT:
                    case DisplayMode.ROCKET:
                        if (ui.movementType == (ushort)MovementType.MOVEMENT_SLITHER)
                        {
                            break;
                        }
                        index      += values_32A4[orientation][0];
                        spriteFlags = values_32A4[orientation][1];
                        break;

                    case DisplayMode.INFANTRY_3_FRAMES:
                    {
                        index      += (ushort)(values_32C4[orientation][0] * 3); //[orientation][0]
                        index      += values_334A[u.spriteOffset & 3];
                        spriteFlags = values_32C4[orientation][1];               //[orientation][1]
                    }
                    break;

                    case DisplayMode.INFANTRY_4_FRAMES:
                        index      += (ushort)(values_32C4[orientation][0] * 4); //[orientation][0]
                        index      += (ushort)(u.spriteOffset & 3);
                        spriteFlags = values_32C4[orientation][1];               //[orientation][1]
                        break;

                    default:
                        spriteFlags = 0;
                        break;
                    }
                }
                else
                {
                    index       = (ushort)(ui.destroyedSpriteID - u.spriteOffset - 1);
                    spriteFlags = 0;
                }

                if (u.o.type != (byte)UnitType.UNIT_SANDWORM && u.o.flags.isHighlighted)
                {
                    spriteFlags |= DRAWSPRITE_FLAG_REMAP;
                }
                if (ui.o.flags.blurTile)
                {
                    spriteFlags |= DRAWSPRITE_FLAG_BLUR;
                }

                spriteFlags |= DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER;

                if (GUI_Widget_Viewport_GetSprite_HousePalette(g_sprites[index], (u.deviated != 0) ? u.deviatedHouse : Unit_GetHouseID(u), paletteHouse))
                {
                    spriteFlags |= DRAWSPRITE_FLAG_PAL;
                    GUI_DrawSprite(Screen.ACTIVE, g_sprites[index], (short)x, (short)y, 2, spriteFlags, paletteHouse, g_paletteMapping2, (short)1);
                }
                else
                {
                    GUI_DrawSprite(Screen.ACTIVE, g_sprites[index], (short)x, (short)y, 2, spriteFlags, g_paletteMapping2, 1);
                }

                if (u.o.type == (byte)UnitType.UNIT_HARVESTER && u.actionID == (byte)ActionType.ACTION_HARVEST && u.spriteOffset >= 0 && (u.actionID == (byte)ActionType.ACTION_HARVEST || u.actionID == (byte)ActionType.ACTION_MOVE))
                {
                    var type = Map_GetLandscapeType(packed);
                    if (type is ((ushort)LandscapeType.LST_SPICE)or((ushort)LandscapeType.LST_THICK_SPICE))
                    {
                        /*GUI_Widget_Viewport_GetSprite_HousePalette(. . ., Unit_GetHouseID(u), paletteHouse),*/
                        GUI_DrawSprite(Screen.ACTIVE,
                                       g_sprites[(u.spriteOffset % 3) + 0xDF + (values_32A4[orientation][0] * 3)],
                                       (short)(x + values_334E[orientation][0]), (short)(y + values_334E[orientation][1]),
                                       2, values_32A4[orientation][1] | DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER);
                    }
                }

                if (u.spriteOffset >= 0 && ui.turretSpriteID != 0xFFFF)
                {
                    short offsetX  = 0;
                    short offsetY  = 0;
                    var   spriteID = ui.turretSpriteID;

                    orientation = Orientation_Orientation256ToOrientation8((byte)u.orientation[ui.o.flags.hasTurret ? 1 : 0].current);

                    switch (ui.turretSpriteID)
                    {
                    case 0x8D:     /* sonic tank */
                        offsetY = -2;
                        break;

                    case 0x92:     /* rocket launcher */
                        offsetY = -3;
                        break;

                    case 0x7E:
                    {         /* siege tank */
                        offsetX = values_336E[orientation][0];
                        offsetY = values_336E[orientation][1];
                    }
                    break;

                    case 0x88:
                    {         /* devastator */
                        offsetX = values_338E[orientation][0];
                        offsetY = values_338E[orientation][1];
                    }
                    break;

                    default:
                        break;
                    }

                    spriteID += values_32A4[orientation][0];

                    if (GUI_Widget_Viewport_GetSprite_HousePalette(g_sprites[spriteID], Unit_GetHouseID(u), paletteHouse))
                    {
                        GUI_DrawSprite(Screen.ACTIVE, g_sprites[spriteID],
                                       (short)(x + offsetX), (short)(y + offsetY),
                                       2, values_32A4[orientation][1] | DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER | DRAWSPRITE_FLAG_PAL, paletteHouse);
                    }
                    else
                    {
                        GUI_DrawSprite(Screen.ACTIVE, g_sprites[spriteID],
                                       (short)(x + offsetX), (short)(y + offsetY),
                                       2, values_32A4[orientation][1] | DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER);
                    }
                }

                if (u.o.flags.isSmoking)
                {
                    var spriteID = (ushort)(180 + (u.spriteOffset & 3));
                    if (spriteID == 183)
                    {
                        spriteID = 181;
                    }

                    GUI_DrawSprite(Screen.ACTIVE, g_sprites[spriteID], (short)x, (short)(y - 14), 2, DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER);
                }

                if (u != g_unitSelected)
                {
                    continue;
                }

                GUI_DrawSprite(Screen.ACTIVE, g_sprites[6], (short)x, (short)y, 2, DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER);
            }

            g_dirtyUnitCount = 0;
        }

        /* draw explosions */
        for (i = 0; i < EXPLOSION_MAX; i++)
        {
            var e = Explosion_Get_ByIndex(i);

            curPos = Tile_PackTile(e.position);

            if (BitArray_Test(g_dirtyViewport, curPos))
            {
                e.isDirty = true;
            }

            if (e.commands == null)
            {
                continue;
            }
            if (!e.isDirty && !forceRedraw)
            {
                continue;
            }
            if (e.spriteID == 0)
            {
                continue;
            }

            e.isDirty = false;

            if (!g_map[curPos].isUnveiled && !g_debugScenario)
            {
                continue;
            }
            if (!Map_IsPositionInViewport(e.position, out x, out y))
            {
                continue;
            }

            /*GUI_Widget_Viewport_GetSprite_HousePalette(g_sprites[e->spriteID], e->houseID, paletteHouse);*/
            GUI_DrawSprite(Screen.ACTIVE, g_sprites[e.spriteID], (short)x, (short)y, 2, DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER /*, paletteHouse*/);
        }

        /* draw air units */
        if (g_dirtyAirUnitCount != 0 || forceRedraw || updateDisplay)
        {
            find.type    = 0xFFFF;
            find.index   = 0xFFFF;
            find.houseID = (byte)HouseType.HOUSE_INVALID;

            while (true)
            {
                CUnit    u;
                UnitInfo ui;
                byte     orientation;
                byte[]   sprite;
                ushort   index;
                ushort   spriteFlags;

                u = Unit_Find(find);

                if (u == null)
                {
                    break;
                }

                if (u.o.index > 15)
                {
                    continue;
                }

                curPos = Tile_PackTile(u.o.position);

                if ((!u.o.flags.isDirty || u.o.flags.isNotOnMap) && !forceRedraw && !BitArray_Test(g_dirtyViewport, curPos))
                {
                    continue;
                }
                u.o.flags.isDirty = false;

                if (!g_map[curPos].isUnveiled && !g_debugScenario)
                {
                    continue;
                }

                ui = g_table_unitInfo[u.o.type];

                if (!Map_IsPositionInViewport(u.o.position, out x, out y))
                {
                    continue;
                }

                index       = ui.groundSpriteID;
                orientation = (byte)u.orientation[0].current;
                spriteFlags = DRAWSPRITE_FLAG_WIDGETPOS | DRAWSPRITE_FLAG_CENTER;

                switch ((DisplayMode)ui.displayMode)
                {
                case DisplayMode.SINGLE_FRAME:
                    if (u.o.flags.bulletIsBig)
                    {
                        index++;
                    }
                    break;

                case DisplayMode.UNIT:
                    orientation = Orientation_Orientation256ToOrientation8(orientation);

                    index       += values_32E4[orientation][0];
                    spriteFlags |= values_32E4[orientation][1];
                    break;

                case DisplayMode.ROCKET:
                {
                    orientation = Orientation_Orientation256ToOrientation16(orientation);

                    index       += values_3304[orientation][0];
                    spriteFlags |= values_3304[orientation][1];
                }
                break;

                case DisplayMode.ORNITHOPTER:
                {
                    orientation = Orientation_Orientation256ToOrientation8(orientation);

                    index       += (ushort)((values_32E4[orientation][0] * 3) + values_33AE[u.spriteOffset & 3]);
                    spriteFlags |= values_32E4[orientation][1];
                }
                break;

                default:
                    spriteFlags = 0x0;
                    break;
                }

                if (ui.flags.hasAnimationSet && u.o.flags.animationFlip)
                {
                    index += 5;
                }
                if (u.o.type == (byte)UnitType.UNIT_CARRYALL && u.o.flags.inTransport)
                {
                    index += 3;
                }

                sprite = g_sprites[index];

                if (ui.o.flags.hasShadow)
                {
                    GUI_DrawSprite(Screen.ACTIVE, sprite, (short)(x + 1), (short)(y + 3), 2, (spriteFlags & ~DRAWSPRITE_FLAG_PAL) | DRAWSPRITE_FLAG_REMAP | DRAWSPRITE_FLAG_BLUR, g_paletteMapping1, (short)1);
                }
                if (ui.o.flags.blurTile)
                {
                    spriteFlags |= DRAWSPRITE_FLAG_BLUR;
                }

                if (GUI_Widget_Viewport_GetSprite_HousePalette(sprite, Unit_GetHouseID(u), paletteHouse))
                {
                    GUI_DrawSprite(Screen.ACTIVE, sprite, (short)x, (short)y, 2, spriteFlags | DRAWSPRITE_FLAG_PAL, paletteHouse);
                }
                else
                {
                    GUI_DrawSprite(Screen.ACTIVE, sprite, (short)x, (short)y, 2, spriteFlags);
                }
            }

            g_dirtyAirUnitCount = 0;
        }

        if (updateDisplay)
        {
            Array.Fill <byte>(g_dirtyMinimap, 0, 0, g_dirtyMinimap.Length);   //memset(g_dirtyMinimap, 0, sizeof(g_dirtyMinimap));
            Array.Fill <byte>(g_dirtyViewport, 0, 0, g_dirtyViewport.Length); //memset(g_dirtyViewport, 0, sizeof(g_dirtyViewport));
        }

        if (g_changedTilesCount != 0)
        {
            var    init         = false;
            var    update       = false;
            ushort minY         = 0xffff;
            ushort maxY         = 0;
            var    oldScreenID2 = Screen.NO1;

            for (i = 0; i < g_changedTilesCount; i++)
            {
                curPos = g_changedTiles[i];
                BitArray_Clear(g_changedTilesMap, curPos);

                if (!init)
                {
                    init = true;

                    oldScreenID2 = GFX_Screen_SetActive(Screen.NO1);

                    GUI_Mouse_Hide_InWidget(3);
                }

                if (GUI_Widget_Viewport_DrawTile(curPos))
                {
                    y  = (ushort)(Tile_GetPackedY(curPos) - g_mapInfos[g_scenario.mapScale].minY); /* +136 */
                    y *= (ushort)(g_scenario.mapScale + 1);
                    if (y > maxY)
                    {
                        maxY = y;
                    }
                    if (y < minY)
                    {
                        minY = y;
                    }
                }

                if (!update && BitArray_Test(g_displayedMinimap, curPos))
                {
                    update = true;
                }
            }

            if (update)
            {
                Map_UpdateMinimapPosition(g_minimapPosition, true);
            }

            if (init)
            {
                if (hasScrolled)
                {   /* force copy of the whole map (could be of the white rectangle) */
                    minY = 0;
                    maxY = (ushort)(63 - g_scenario.mapScale);
                }
                /* MiniMap : redraw only line that changed */
                if (minY < maxY)
                {
                    GUI_Screen_Copy(32, (short)(136 + minY), 32, (short)(136 + minY), 8, (short)(maxY + 1 + g_scenario.mapScale - minY), Screen.ACTIVE, Screen.NO0);
                }

                GFX_Screen_SetActive(oldScreenID2);

                GUI_Mouse_Show_InWidget();
            }

            if (g_changedTilesCount == g_changedTiles.Length)
            {
                g_changedTilesCount = 0;

                for (i = 0; i < 4096; i++)
                {
                    if (!BitArray_Test(g_changedTilesMap, i))
                    {
                        continue;
                    }
                    g_changedTiles[g_changedTilesCount++] = i;
                    if (g_changedTilesCount == g_changedTiles.Length)
                    {
                        break;
                    }
                }
            }
            else
            {
                g_changedTilesCount = 0;
            }
        }

        if ((g_viewportMessageCounter & 1) != 0 && g_viewportMessageText != null && (minX[6] <= 14 || maxX[6] >= 0 || hasScrolled || forceRedraw))
        {
            GUI_DrawText_Wrapper(g_viewportMessageText, 112, 139, 15, 0, 0x132);
            minX[6] = -1;
            maxX[6] = 14;
        }

        if (updateDisplay && !drawToMainScreen)
        {
            if (g_viewport_fadein)
            {
                GUI_Mouse_Hide_InWidget(g_curWidgetIndex);

                /* ENHANCEMENT -- When fading in the game on start, you don't see the fade as it is against the already drawn screen. */
                if (g_dune2_enhanced)
                {
                    var oldScreenID2 = GFX_Screen_SetActive(Screen.NO0);
                    GUI_DrawFilledRectangle((short)(g_curWidgetXBase << 3), (short)g_curWidgetYBase, (short)((g_curWidgetXBase + g_curWidgetWidth) << 3), (short)(g_curWidgetYBase + g_curWidgetHeight), 0);
                    GFX_Screen_SetActive(oldScreenID2);
                }

                GUI_Screen_FadeIn(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, Screen.ACTIVE, Screen.NO0);
                GUI_Mouse_Show_InWidget();

                g_viewport_fadein = false;
            }
            else
            {
                var init = false;

                for (i = 0; i < 10; i++)
                {
                    ushort width;
                    ushort height;

                    if (hasScrolled)
                    {
                        minX[i] = 0;
                        maxX[i] = 14;
                    }

                    if (maxX[i] < minX[i])
                    {
                        continue;
                    }

                    x      = (ushort)(minX[i] * 2);
                    y      = (ushort)((i << 4) + 0x28);
                    width  = (ushort)((maxX[i] - minX[i] + 1) * 2);
                    height = 16;

                    if (!init)
                    {
                        GUI_Mouse_Hide_InWidget(g_curWidgetIndex);

                        init = true;
                    }

                    GUI_Screen_Copy((short)x, (short)y, (short)x, (short)y, (short)width, (short)height, Screen.ACTIVE, Screen.NO0);
                }

                if (init)
                {
                    GUI_Mouse_Show_InWidget();
                }
            }
        }

        GFX_Screen_SetActive(oldScreenID);

        Widget_SetCurrentWidget(oldWidgetID);
    }
コード例 #15
0
ファイル: House.cs プロジェクト: n-stefan/SharpDune
    /*
     * Calculate the power usage and production, and the credits storage.
     *
     * @param h The house to calculate the numbers for.
     */
    internal static void House_CalculatePowerAndCredit(CHouse h)
    {
        var find = new PoolFindStruct();

        if (h == null)
        {
            return;
        }

        h.powerUsage      = 0;
        h.powerProduction = 0;
        h.creditsStorage  = 0;

        find.houseID = h.index;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        while (true)
        {
            StructureInfo si;
            CStructure    s;

            s = Structure_Find(find);
            if (s == null)
            {
                break;
            }
            /* ENHANCEMENT -- Only count structures that are placed on the map, not ones we are building. */
            if (g_dune2_enhanced && s.o.flags.isNotOnMap)
            {
                continue;
            }

            si = g_table_structureInfo[s.o.type];

            h.creditsStorage += si.creditsStorage;

            /* Positive values means usage */
            if (si.powerUsage >= 0)
            {
                h.powerUsage += (ushort)si.powerUsage;
                continue;
            }

            /* Negative value and full health means everything goes to production */
            if (s.o.hitpoints >= si.o.hitpoints)
            {
                h.powerProduction += (ushort)-si.powerUsage;
                continue;
            }

            /* Negative value and partial health, calculate how much should go to production (capped at 50%) */
            /* ENHANCEMENT -- The 50% cap of Dune2 is silly and disagress with the GUI. If your hp is 10%, so should the production. */
            if (!g_dune2_enhanced && s.o.hitpoints <= si.o.hitpoints / 2)
            {
                h.powerProduction += (ushort)((-si.powerUsage) / 2);
                continue;
            }
            h.powerProduction += (ushort)((-si.powerUsage) * s.o.hitpoints / si.o.hitpoints);
        }

        /* Check if we are low on power */
        if (h.index == (byte)g_playerHouseID && h.powerUsage > h.powerProduction)
        {
            GUI_DisplayText(String_Get_ByIndex(Text.STR_INSUFFICIENT_POWER_WINDTRAP_IS_NEEDED), 1);
        }

        /* If there are no buildings left, you lose your right on 'credits without storage' */
        if (h.index == (byte)g_playerHouseID && h.structuresBuilt == 0 && g_validateStrictIfZero == 0)
        {
            g_playerCreditsNoSilo = 0;
        }
    }
コード例 #16
0
    /*
     * Tries to add the closest unit to the current team.
     *
     * Stack: *none*.
     *
     * @param script The script engine to operate on.
     * @return The amount of space left in current team.
     */
    internal static ushort Script_Team_AddClosestUnit(ScriptEngine _)
    {
        CTeam  t;
        CUnit  closest      = null;
        CUnit  closest2     = null;
        ushort minDistance  = 0;
        ushort minDistance2 = 0;
        var    find         = new PoolFindStruct();

        t = g_scriptCurrentTeam;

        if (t.members >= t.maxMembers)
        {
            return(0);
        }

        find.houseID = t.houseID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        while (true)
        {
            CUnit  u;
            CTeam  t2;
            ushort distance;

            u = Unit_Find(find);
            if (u == null)
            {
                break;
            }
            if (!u.o.flags.byScenario)
            {
                continue;
            }
            if (u.o.type == (byte)UnitType.UNIT_SABOTEUR)
            {
                continue;
            }
            if (g_table_unitInfo[u.o.type].movementType != t.movementType)
            {
                continue;
            }
            if (u.team == 0)
            {
                distance = Tile_GetDistance(t.position, u.o.position);
                if (distance >= minDistance && minDistance != 0)
                {
                    continue;
                }
                minDistance = distance;
                closest     = u;
                continue;
            }

            t2 = Team_Get_ByIndex((ushort)(u.team - 1));
            if (t2.members > t2.minMembers)
            {
                continue;
            }

            distance = Tile_GetDistance(t.position, u.o.position);
            if (distance >= minDistance2 && minDistance2 != 0)
            {
                continue;
            }
            minDistance2 = distance;
            closest2     = u;
        }

        if (closest == null)
        {
            closest = closest2;
        }
        if (closest == null)
        {
            return(0);
        }

        Unit_RemoveFromTeam(closest);
        return(Unit_AddToTeam(closest, t));
    }
コード例 #17
0
    /*
     * Unknown function 0788.
     *
     * Stack: *none*.
     *
     * @param script The script engine to operate on.
     * @return The value 0. Always.
     */
    internal static ushort Script_Team_Unknown0788(ScriptEngine _)
    {
        CTeam  t;
        Tile32 tile;
        var    find = new PoolFindStruct();

        t = g_scriptCurrentTeam;
        if (t.target == 0)
        {
            return(0);
        }

        tile = Tools_Index_GetTile(t.target);

        find.houseID = t.houseID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        while (true)
        {
            CUnit  u;
            ushort distance;
            ushort packed;
            short  orientation;

            u = Unit_Find(find);
            if (u == null)
            {
                break;
            }
            if (u.team - 1 != t.index)
            {
                continue;
            }
            if (t.target == 0)
            {
                Unit_SetAction(u, ActionType.ACTION_GUARD);
                continue;
            }

            distance = (ushort)(g_table_unitInfo[u.o.type].fireDistance << 8);
            if (u.actionID == (byte)ActionType.ACTION_ATTACK && u.targetAttack == t.target)
            {
                if (u.targetMove != 0)
                {
                    continue;
                }
                if (Tile_GetDistance(u.o.position, tile) >= distance)
                {
                    continue;
                }
            }

            if (u.actionID != (byte)ActionType.ACTION_ATTACK)
            {
                Unit_SetAction(u, ActionType.ACTION_ATTACK);
            }

            orientation = (short)((Tile_GetDirection(tile, u.o.position) & 0xC0) + Tools_RandomLCG_Range(0, 127));
            if (orientation < 0)
            {
                orientation += 256;
            }

            packed = Tile_PackTile(Tile_MoveByDirection(tile, orientation, distance));

            if (Object_GetByPackedTile(packed) == null)
            {
                Unit_SetDestination(u, Tools_Index_Encode(packed, IndexType.IT_TILE));
            }
            else
            {
                Unit_SetDestination(u, Tools_Index_Encode(Tile_PackTile(tile), IndexType.IT_TILE));
            }

            Unit_SetTarget(u, t.target);
        }

        return(0);
    }
コード例 #18
0
    /*
     * Gets the average distance between current team members, and set the
     *  position of the team to the average position.
     *
     * Stack: *none*.
     *
     * @param script The script engine to operate on.
     * @return The average distance.
     */
    internal static ushort Script_Team_GetAverageDistance(ScriptEngine _)
    {
        ushort averageX = 0;
        ushort averageY = 0;
        ushort count    = 0;
        ushort distance = 0;
        CTeam  t;
        var    find = new PoolFindStruct();

        t = g_scriptCurrentTeam;

        find.houseID = t.houseID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        while (true)
        {
            CUnit u;

            u = Unit_Find(find);
            if (u == null)
            {
                break;
            }
            if (t.index != u.team - 1)
            {
                continue;
            }
            count++;
            averageX += (ushort)((u.o.position.x >> 8) & 0x3f);
            averageY += (ushort)((u.o.position.y >> 8) & 0x3f);
        }

        if (count == 0)
        {
            return(0);
        }
        averageX /= count;
        averageY /= count;

        Tile_MakeXY(ref t.position, averageX, averageY);

        find.houseID = t.houseID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        while (true)
        {
            CUnit u;

            u = Unit_Find(find);
            if (u == null)
            {
                break;
            }
            if (t.index != u.team - 1)
            {
                continue;
            }
            distance += Tile_GetDistanceRoundedUp(u.o.position, t.position);
        }

        distance /= count;

        if (t.target == 0 || t.targetTile == 0)
        {
            return(distance);
        }

        if (Tile_GetDistancePacked(Tile_PackXY(averageX, averageY), Tools_Index_GetPackedTile(t.target)) <= 10)
        {
            t.targetTile = 2;
        }

        return(distance);
    }
コード例 #19
0
ファイル: House.cs プロジェクト: n-stefan/SharpDune
    /*
     * Loop over all houses, preforming various of tasks.
     */
    internal static void GameLoop_House()
    {
        var    find = new PoolFindStruct();
        CHouse h; // = NULL;
        var    tickHouse                = false;
        var    tickPowerMaintenance     = false;
        var    tickStarport             = false;
        var    tickReinforcement        = false;
        var    tickMissileCountdown     = false;
        var    tickStarportAvailability = false;

        if (g_debugScenario)
        {
            return;
        }

        if (s_tickHouseHouse <= g_timerGame)
        {
            tickHouse        = true;
            s_tickHouseHouse = g_timerGame + 900;
        }

        if (g_tickHousePowerMaintenance <= g_timerGame)
        {
            tickPowerMaintenance        = true;
            g_tickHousePowerMaintenance = g_timerGame + 10800;
        }

        if (s_tickHouseStarport <= g_timerGame)
        {
            tickStarport        = true;
            s_tickHouseStarport = g_timerGame + 180;
        }

        if (s_tickHouseReinforcement <= g_timerGame)
        {
            tickReinforcement        = true;
            s_tickHouseReinforcement = (uint)(g_timerGame + (g_debugGame ? 60 : 600));
        }

        if (s_tickHouseMissileCountdown <= g_timerGame)
        {
            tickMissileCountdown        = true;
            s_tickHouseMissileCountdown = g_timerGame + 60;
        }

        if (s_tickHouseStarportAvailability <= g_timerGame)
        {
            tickStarportAvailability        = true;
            s_tickHouseStarportAvailability = g_timerGame + 1800;
        }

        if (tickMissileCountdown && g_houseMissileCountdown != 0)
        {
            g_houseMissileCountdown--;
            Sound_Output_Feedback((ushort)(g_houseMissileCountdown + 41));

            if (g_houseMissileCountdown == 0)
            {
                Unit_LaunchHouseMissile(Map_FindLocationTile(4, (byte)g_playerHouseID));
            }
        }

        if (tickStarportAvailability)
        {
            ushort type;

            /* Pick a random unit to increase starport availability */
            type = Tools_RandomLCG_Range(0, (ushort)(UnitType.UNIT_MAX - 1));

            /* Increase how many of this unit is available via starport by one */
            if (g_starportAvailable[type] is not 0 and < 10)
            {
                if (g_starportAvailable[type] == -1)
                {
                    g_starportAvailable[type] = 1;
                }
                else
                {
                    g_starportAvailable[type]++;
                }
            }
        }

        if (tickReinforcement)
        {
            CUnit nu = null;
            int   i;

            for (i = 0; i < 16; i++)
            {
                ushort locationID;
                bool   deployed;
                CUnit  u;

                if (g_scenario.reinforcement[i].unitID == (ushort)UnitIndex.UNIT_INDEX_INVALID)
                {
                    continue;
                }
                if (g_scenario.reinforcement[i].timeLeft == 0)
                {
                    continue;
                }
                if (--g_scenario.reinforcement[i].timeLeft != 0)
                {
                    continue;
                }

                u = Unit_Get_ByIndex(g_scenario.reinforcement[i].unitID);

                locationID = g_scenario.reinforcement[i].locationID;
                deployed   = false;

                if (locationID >= 4)
                {
                    if (nu == null)
                    {
                        nu = Unit_Create((ushort)UnitIndex.UNIT_INDEX_INVALID, (byte)UnitType.UNIT_CARRYALL, u.o.houseID, Tile_UnpackTile(Map_FindLocationTile((ushort)(Tools_Random_256() & 3), u.o.houseID)), 100);

                        if (nu != null)
                        {
                            nu.o.flags.byScenario = true;
                            Unit_SetDestination(nu, Tools_Index_Encode(Map_FindLocationTile(locationID, u.o.houseID), IndexType.IT_TILE));
                        }
                    }

                    if (nu != null)
                    {
                        u.o.linkedID                       = nu.o.linkedID;
                        nu.o.linkedID                      = (byte)u.o.index;
                        nu.o.flags.inTransport             = true;
                        g_scenario.reinforcement[i].unitID = (ushort)UnitIndex.UNIT_INDEX_INVALID;
                        deployed = true;
                    }
                    else
                    {
                        /* Failed to create carry-all, try again in a short moment */
                        g_scenario.reinforcement[i].timeLeft = 1;
                    }
                }
                else
                {
                    deployed = Unit_SetPosition(u, Tile_UnpackTile(Map_FindLocationTile(locationID, u.o.houseID)));
                }

                if (deployed && g_scenario.reinforcement[i].repeat != 0)
                {
                    var tile = new Tile32
                    {
                        x = 0xFFFF,
                        y = 0xFFFF
                    };

                    g_validateStrictIfZero++;
                    u = Unit_Create((ushort)UnitIndex.UNIT_INDEX_INVALID, u.o.type, u.o.houseID, tile, 0);
                    g_validateStrictIfZero--;

                    if (u != null)
                    {
                        g_scenario.reinforcement[i].unitID   = u.o.index;
                        g_scenario.reinforcement[i].timeLeft = g_scenario.reinforcement[i].timeBetween;
                    }
                }
            }
        }

        find.houseID = (byte)HouseType.HOUSE_INVALID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        while (true)
        {
            h = House_Find(find);
            if (h == null)
            {
                break;
            }

            if (tickHouse)
            {
                /* ENHANCEMENT -- Originally this code was outside the house loop, which seems very odd.
                 *  This problem is considered to be so bad, that the original code has been removed. */
                if (h.index != (byte)g_playerHouseID)
                {
                    if (h.creditsStorage < h.credits)
                    {
                        h.credits = h.creditsStorage;
                    }
                }
                else
                {
                    var maxCredits = Math.Max(h.creditsStorage, g_playerCreditsNoSilo);
                    if (h.credits > maxCredits)
                    {
                        h.credits = maxCredits;

                        GUI_DisplayText(String_Get_ByIndex(Text.STR_INSUFFICIENT_SPICE_STORAGE_AVAILABLE_SPICE_IS_LOST), 1);
                    }
                }

                if (h.index == (byte)g_playerHouseID)
                {
                    if (h.creditsStorage > g_playerCreditsNoSilo)
                    {
                        g_playerCreditsNoSilo = 0;
                    }

                    if (g_playerCreditsNoSilo == 0 && g_campaignID > 1 && h.credits != 0)
                    {
                        if (h.creditsStorage != 0 && ((h.credits * 256 / h.creditsStorage) > 200))
                        {
                            GUI_DisplayText(String_Get_ByIndex(Text.STR_SPICE_STORAGE_CAPACITY_LOW_BUILD_SILOS), 0);
                        }
                    }

                    if (h.credits < 100 && g_playerCreditsNoSilo != 0)
                    {
                        GUI_DisplayText(String_Get_ByIndex(Text.STR_CREDITS_ARE_LOW_HARVEST_SPICE_FOR_MORE_CREDITS), 0);
                    }
                }
            }

            if (tickHouse)
            {
                House_EnsureHarvesterAvailable(h.index);
            }

            if (tickStarport && h.starportLinkedID != (ushort)UnitIndex.UNIT_INDEX_INVALID)
            {
                CUnit u = null;

                h.starportTimeLeft--;
                if ((short)h.starportTimeLeft < 0)
                {
                    h.starportTimeLeft = 0;
                }

                if (h.starportTimeLeft == 0)
                {
                    CStructure s;

                    s = Structure_Get_ByIndex(g_structureIndex);
                    if (s.o.type == (byte)StructureType.STRUCTURE_STARPORT && s.o.houseID == h.index)
                    {
                        u = Unit_CreateWrapper(h.index, UnitType.UNIT_FRIGATE, Tools_Index_Encode(s.o.index, IndexType.IT_STRUCTURE));
                    }
                    else
                    {
                        var find2 = new PoolFindStruct
                        {
                            houseID = h.index,
                            index   = 0xFFFF,
                            type    = (ushort)StructureType.STRUCTURE_STARPORT
                        };

                        while (true)
                        {
                            s = Structure_Find(find2);
                            if (s == null)
                            {
                                break;
                            }
                            if (s.o.linkedID != 0xFF)
                            {
                                continue;
                            }

                            u = Unit_CreateWrapper(h.index, UnitType.UNIT_FRIGATE, Tools_Index_Encode(s.o.index, IndexType.IT_STRUCTURE));
                            break;
                        }
                    }

                    if (u != null)
                    {
                        u.o.linkedID          = (byte)h.starportLinkedID;
                        h.starportLinkedID    = (ushort)UnitIndex.UNIT_INDEX_INVALID;
                        u.o.flags.inTransport = true;

                        Sound_Output_Feedback(38);
                    }

                    h.starportTimeLeft = (ushort)((u != null) ? g_table_houseInfo[h.index].starportDeliveryTime : 1);
                }
            }

            if (tickHouse)
            {
                House_CalculatePowerAndCredit(h);
                Structure_CalculateHitpointsMax(h);

                if (h.timerUnitAttack != 0)
                {
                    h.timerUnitAttack--;
                }
                if (h.timerSandwormAttack != 0)
                {
                    h.timerSandwormAttack--;
                }
                if (h.timerStructureAttack != 0)
                {
                    h.timerStructureAttack--;
                }
                if (h.harvestersIncoming > 0 && Unit_CreateWrapper(h.index, UnitType.UNIT_HARVESTER, 0) != null)
                {
                    h.harvestersIncoming--;
                }
            }

            if (tickPowerMaintenance)
            {
                var powerMaintenanceCost = (ushort)((h.powerUsage / 32) + 1);
                h.credits -= Math.Min(h.credits, powerMaintenanceCost);
            }
        }
    }
コード例 #20
0
    /*
     * Unknown function 0543.
     *
     * Stack: 1 - A distance.
     *
     * @param script The script engine to operate on.
     * @return The number of moving units.
     */
    internal static ushort Script_Team_Unknown0543(ScriptEngine script)
    {
        CTeam  t;
        ushort count = 0;
        ushort distance;
        var    find = new PoolFindStruct();

        t        = g_scriptCurrentTeam;
        distance = STACK_PEEK(script, 1);

        find.houseID = t.houseID;
        find.index   = 0xFFFF;
        find.type    = 0xFFFF;

        while (true)
        {
            CUnit  u;
            Tile32 tile;
            ushort distanceUnitDest;
            ushort distanceUnitTeam;
            ushort distanceTeamDest;

            u = Unit_Find(find);
            if (u == null)
            {
                break;
            }
            if (t.index != u.team - 1)
            {
                continue;
            }

            tile             = Tools_Index_GetTile(u.targetMove);
            distanceUnitTeam = Tile_GetDistanceRoundedUp(u.o.position, t.position);

            if (u.targetMove != 0)
            {
                distanceUnitDest = Tile_GetDistanceRoundedUp(u.o.position, tile);
                distanceTeamDest = Tile_GetDistanceRoundedUp(t.position, tile);
            }
            else
            {
                distanceUnitDest = 64;
                distanceTeamDest = 64;
            }

            if ((distanceUnitDest < distanceTeamDest && (distance + 2) < distanceUnitTeam) || (distanceUnitDest >= distanceTeamDest && distanceUnitTeam > distance))
            {
                Unit_SetAction(u, ActionType.ACTION_MOVE);

                tile = Tile_MoveByRandom(t.position, (ushort)(distance << 4), true);

                Unit_SetDestination(u, Tools_Index_Encode(Tile_PackTile(tile), IndexType.IT_TILE));
                count++;
                continue;
            }

            Unit_SetAction(u, ActionType.ACTION_GUARD);
        }

        return(count);
    }
コード例 #21
0
ファイル: House.cs プロジェクト: n-stefan/SharpDune
    /*
     * Gives a harvester to the given house if it has a refinery and no harvesters.
     *
     * @param houseID The index of the house to give a harvester to.
     */
    static void House_EnsureHarvesterAvailable(byte houseID)
    {
        var        find = new PoolFindStruct();
        CStructure s;

        find.houseID = houseID;
        find.type    = 0xFFFF;
        find.index   = 0xFFFF;

        while (true)
        {
            s = Structure_Find(find);
            if (s == null)
            {
                break;
            }
            /* ENHANCEMENT -- Dune2 checked the wrong type to skip. LinkedID is a structure for a Construction Yard */
            if (!g_dune2_enhanced && s.o.type == (byte)StructureType.STRUCTURE_HEAVY_VEHICLE)
            {
                continue;
            }
            if (g_dune2_enhanced && s.o.type == (byte)StructureType.STRUCTURE_CONSTRUCTION_YARD)
            {
                continue;
            }
            if (s.o.linkedID == (byte)UnitType.UNIT_INVALID)
            {
                continue;
            }
            if (Unit_Get_ByIndex(s.o.linkedID).o.type == (byte)UnitType.UNIT_HARVESTER)
            {
                return;
            }
        }

        find.houseID = houseID;
        find.type    = (ushort)UnitType.UNIT_CARRYALL;
        find.index   = 0xFFFF;

        while (true)
        {
            CUnit u;

            u = Unit_Find(find);
            if (u == null)
            {
                break;
            }
            if (u.o.linkedID == (byte)UnitType.UNIT_INVALID)
            {
                continue;
            }
            if (Unit_Get_ByIndex(u.o.linkedID).o.type == (byte)UnitType.UNIT_HARVESTER)
            {
                return;
            }
        }

        if (Unit_IsTypeOnMap(houseID, (byte)UnitType.UNIT_HARVESTER))
        {
            return;
        }

        find.houseID = houseID;
        find.type    = (ushort)StructureType.STRUCTURE_REFINERY;
        find.index   = 0xFFFF;

        s = Structure_Find(find);
        if (s == null)
        {
            return;
        }

        if (Unit_CreateWrapper(houseID, UnitType.UNIT_HARVESTER, Tools_Index_Encode(s.o.index, IndexType.IT_STRUCTURE)) == null)
        {
            return;
        }

        if (houseID != (byte)g_playerHouseID)
        {
            return;
        }

        GUI_DisplayText(String_Get_ByIndex(Text.STR_HARVESTER_IS_HEADING_TO_REFINERY), 0);
    }
コード例 #22
0
    /*
     * Save the game to a filename
     *
     * @param fp The filename of the savegame.
     * @param description The description of the savegame.
     * @return True if and only if all bytes were written successful.
     */
    internal static bool SaveGame_SaveFile(string filename, string description)
    {
        FileStream fp;
        bool       res;

        /* In debug-scenario mode, the whole map is uncovered. Cover it now in
         *  the savegame based on the current position of the units and
         *  structures. */
        if (g_debugScenario)
        {
            var    find = new PoolFindStruct();
            ushort i;

            /* Add fog of war for all tiles on the map */
            for (i = 0; i < 0x1000; i++)
            {
                var tile = g_map[i];
                tile.isUnveiled    = false;
                tile.overlayTileID = g_veiledTileID;
            }

            find.houseID = (byte)HouseType.HOUSE_INVALID;
            find.type    = 0xFFFF;
            find.index   = 0xFFFF;

            /* Remove the fog of war for all units */
            while (true)
            {
                CUnit u;

                u = Unit_Find(find);
                if (u == null)
                {
                    break;
                }

                Unit_RemoveFog(u);
            }

            find.houseID = (byte)HouseType.HOUSE_INVALID;
            find.type    = 0xFFFF;
            find.index   = 0xFFFF;

            /* Remove the fog of war for all structures */
            while (true)
            {
                CStructure s;

                s = Structure_Find(find);
                if (s == null)
                {
                    break;
                }
                if (s.o.type is ((byte)StructureType.STRUCTURE_SLAB_1x1)or((byte)StructureType.STRUCTURE_SLAB_2x2) or((byte)StructureType.STRUCTURE_WALL))
                {
                    continue;
                }

                Structure_RemoveFog(s);
            }
        }

        fp = FOpenDataDir(SearchDirectory.SEARCHDIR_PERSONAL_DATA_DIR, filename, "wb");
        if (fp == null)
        {
            Trace.WriteLine($"ERROR: Failed to open file '{filename}' for writing.");
            return(false);
        }

        g_validateStrictIfZero++;
        res = Save_Main(fp, description);
        g_validateStrictIfZero--;

        fp.Close();

        if (!res)
        {
            /* TODO -- Also remove the savegame now */
            Trace.WriteLine($"ERROR: Error while writing savegame '{filename}'.");
            return(false);
        }

        return(true);
    }