GameApi.getVisibleUnits(playerName, type, filter?)

| Chrono Divide | 3 Reads

GameApi.getVisibleUnits(playerName, type, filter?) 會返回目前對指定玩家可見的單位 ID 清單。該方法在 package/dist/index.d.ts 中的宣告如下,說明了參數及 type 參數的意義:

/**
 * 取得對指定玩家可見的單位列表(未被迷霧遮蔽),依據敵對狀態分類
 *
 * 可以額外傳入過濾條件以進一步篩選結果
 *
 * @param playerName - 觀察者的玩家名稱
 * @param type - 根據單位的擁有者進行過濾
 *  - `self` 回傳由 playerName 擁有的單位
 *  - `allied` 回傳由 playerName 或其盟友擁有的單位
 *  - `hostile` 回傳所有非 playerName 與其盟友擁有的單位,包含中立單位
 *  - `enemy` 回傳由敵方玩家擁有的單位,不包含中立單位
 * @param filter - 可選的過濾條件,根據單位規則(rules)進一步篩選
 */
getVisibleUnits(playerName: string, type: "self" | "allied" | "hostile" | "enemy", filter?: (r: TechnoRules) => boolean): number[];

經過壓縮的實作碼揭示了該方法的內部運作方式。它會根據名稱找到玩家,檢查所要求的類型,並收集所有對應的不在迷霧中的世界物件。若有提供過濾函式則會進一步篩選:

getVisibleUnits(e, s, t = () => !0) {
    const r = Mp(this, Lp, "f").getPlayerByName(e);
    if (!r)
        throw new Error(`Player "${e}" doesn't exist`);
    if ("self" === s)
        return r.getOwnedObjects().filter(e => t(e.rules)).map(e => e.id);
    let a;
    if ("allied" === s)
        a = e => e.owner === r || Mp(this, Lp, "f").alliances.areAllied(e.owner, r);
    else {
        if ("hostile" !== s && "enemy" !== s)
            throw new Error(`Unexpected type ${s}`);
        let i = Mp(this, Lp, "f").mapShroudTrait.getPlayerShroud(r);
        a = t => Mp(this, Lp, "f").map.tileOccupation.calculateTilesForGameObject(t.tile, t)
            .some(e => !i?.isShrouded(e, t.tileElevation)) &&
            t.owner !== r &&
            !Mp(this, Lp, "f").alliances.areAllied(t.owner, r) &&
            ("enemy" !== s || t.owner.isCombatant());
    }
    return Mp(this, Lp, "f").getWorld().getAllObjects()
        .filter(e => e.isTechno() && !e.isDestroyed && a(e) && t(e.rules))
        .map(e => e.id);
}

【F:package/dist/index.js†byte793252-794052】


【範例用法】

以下是一個簡單的 Bot 範例,展示如何使用 getVisibleUnits 來檢查地圖上可見的單位。該 Bot 會回報自己的單位、盟軍單位、敵對單位,最後列出所有可見的敵方飛機:

import { cdapi, Bot, GameApi, MovementZone } from "@chronodivide/game-api";

class VisibilityBot extends Bot {
    onGameStart(game: GameApi) {
        // 1)由此玩家擁有的單位
        const ours = game.getVisibleUnits(this.name, "self");
        console.log(`我們可見的單位數量:${ours.length}`);

        // 2)由我們或盟友擁有的單位
        const allies = game.getVisibleUnits(this.name, "allied");
        console.log(`可見盟友單位數量:${allies.length}`);

        // 3)任何非盟友的可見單位
        const hostile = game.getVisibleUnits(this.name, "hostile");
        console.log(`偵測到的敵對單位數量:${hostile.length}`);

        // 4)僅敵方飛機(使用 filter 過濾)
        const enemyAircraft = game.getVisibleUnits(
            this.name,
            "enemy",
            r => r.movementZone === MovementZone.Fly
        );
        enemyAircraft.forEach(id => {
            const data = game.getGameObjectData(id);
            if (data) {
                console.log(`敵方飛機 ${data.name} 位於 (${data.tile.rx}, ${data.tile.ry})`);
            }
        });
    }
}

async function main() {
    await cdapi.init(process.env.MIX_DIR!);
    await cdapi.createGame({
        agents: [new VisibilityBot("Scout", "Americans")],
        mapName: "mp03t4.map",
        shortGame: true,
        online: false,
    });
}
main().catch(console.error);

本範例依序使用 getVisibleUnits 方法的所有可能類型值。可選的 filter 函式展示如何選出移動方式為飛行 (movementZone === MovementZone.Fly) 的敵方單位,並透過 getGameObjectData 顯示其名稱與所在座標。

 

→返回《@chronodivide/game-api 使用教學與完整 API 對照表》

This article was last edited at