GameApi.getGameObjectData(objId) / getUnitData(unitId)
Copyright Notice: This article is an original work licensed under the CC 4.0 BY-NC-ND license.
If you wish to repost this article, please include the original source link and this copyright notice.
Source link: https://v2know.com/article/1211
GameApi 暴露了兩個用於在執行期間檢查物件的輔助方法:
getGameObjectData(objId: number): GameObjectData | undefined;
getUnitData(unitId: number): UnitData | undefined;
這些方法的回傳內容
GameObjectData
提供任何遊戲內物件的一般資訊。主要欄位包括規則定義、地圖座標、基礎尺寸,以及選擇性地包含生命值或擁有者資訊:
export interface GameObjectData {
id: number;
type: ObjectType;
name: string;
rules: ObjectRules;
tile: Tile;
worldPosition: Vector3;
tileElevation: number;
foundation: Size;
hitPoints?: number;
maxHitPoints?: number;
owner?: string;
}
UnitData
在此基礎上擴充,提供單位特有的屬性,例如武器、工廠狀態、集結點、砲塔朝向等:
export interface UnitData extends GameObjectData {
rules: TechnoRules;
owner: string;
sight: number;
veteranLevel: VeteranLevel;
guardMode: boolean;
purchaseValue: number;
primaryWeapon?: WeaponData;
secondaryWeapon?: WeaponData;
deathWeapon?: WeaponData;
attackState?: AttackState;
hitPoints: number;
maxHitPoints: number;
direction?: number;
onBridge?: boolean;
zone?: ZoneType;
buildStatus?: BuildStatus;
factory?: FactoryData;
rallyPoint?: Tile;
isPoweredOn?: boolean;
hasWrenchRepair?: boolean;
garrisonUnitCount?: number;
garrisonUnitsMax?: number;
turretFacing?: number;
turretNo?: number;
isIdle?: boolean;
canMove?: boolean;
velocity?: Vector3;
stance?: StanceType;
harvestedOre?: number;
harvestedGems?: number;
passengerSlotCount?: number;
passengerSlotMax?: number;
ammo?: number;
isWarpedOut: boolean;
mindControlledBy?: number;
tntTimer?: number;
}
編譯後的程式碼顯示:
getGameObjectData
根據 ID 擷取世界物件,並回傳其欄位:
...getGameObjectData(t){
if(Mp(this,Lp,"f").getWorld().hasObjectId(t)){
let e=Mp(this,Lp,"f").getObjectById(t);
return {
id: e.id,
type: e.type,
name: e.name,
rules: e.rules,
tile: e.tile,
tileElevation: e.tileElevation,
worldPosition: e.position.worldPosition.clone(),
foundation: e.getFoundation(),
hitPoints: e.healthTrait?.getHitPoints(),
maxHitPoints: e.healthTrait?.maxHitPoints,
owner: e.isTechno() ? e.owner.name : void 0
}
}
}
getUnitData
在此基礎上進行擴充,若該物件不是單位或建築則會丟出錯誤:
getUnitData(t){
var i = this.getGameObjectData(t);
if(i){
let e = Mp(this,Lp,"f").getObjectById(t);
if(!e.isTechno())
throw new Error(`Game object with id ${t} is not a Techno type`);
return {
...i,
owner: e.owner.name,
sight: e.sight,
veteranLevel: e.veteranLevel,
guardMode: e.guardMode,
purchaseValue: e.purchaseValue,
primaryWeapon: e.primaryWeapon ? Mp(this,jp,"m",Up).call(this, e.primaryWeapon) : void 0,
secondaryWeapon: e.secondaryWeapon ? Mp(this,jp,"m",Up).call(this, e.secondaryWeapon) : void 0,
deathWeapon: e.armedTrait?.deathWeapon ? Mp(this,jp,"m",Up).call(this, e.armedTrait.deathWeapon) : void 0,
attackState: e.attackTrait?.attackState,
direction: e.direction,
onBridge: e.isInfantry() || e.isVehicle() ? e.onBridge : void 0,
zone: e.isUnit() ? e.zone : void 0,
buildStatus: e.isBuilding() ? e.buildStatus : void 0,
factory: e.isBuilding() && e.factoryTrait ? {
deliveringUnit: e.factoryTrait.deliveringUnit?.id,
status: e.factoryTrait.status
} : void 0,
rallyPoint: e.isBuilding() ? e.rallyTrait?.getRallyPoint() : void 0,
isPoweredOn: e.isBuilding() && e.poweredTrait ? e.poweredTrait.isPoweredOn : void 0,
hasWrenchRepair: e.isBuilding() && e.autoRepairTrait.isDisabled,
turretFacing: e.isBuilding() || e.isVehicle ? e.turretTrait?.facing : void 0,
...
}
}
}
使用範例
下方的 bot 在遊戲開始時會回報其第一個單位的基本資訊。
getGameObjectData
提供一般資訊,getUnitData
提供單位的詳細資料。
import { cdapi, Bot, GameApi } from "@chronodivide/game-api";
class ObjectInfoBot extends Bot {
onGameStart(game: GameApi) {
const units = game.getVisibleUnits(this.name, "self");
if (!units.length) {
console.log("No units visible!");
return;
}
const id = units[0];
const obj = game.getGameObjectData(id);
const unit = game.getUnitData(id);
if (obj) {
console.log(`Object ${id}: ${obj.name} at (${obj.tile.rx}, ${obj.tile.ry})`);
}
if (unit) {
console.log(
`HP ${unit.hitPoints}/${unit.maxHitPoints}, sight ${unit.sight}, ` +
`veteran=${unit.veteranLevel}`
);
if (unit.primaryWeapon) {
console.log(`Primary weapon: ${unit.primaryWeapon.name}`);
}
}
}
}
async function main() {
await cdapi.init(process.env.MIX_DIR!);
await cdapi.createGame({
agents: [new ObjectInfoBot("Scout", "Americans")],
mapName: "mp03t4.map",
shortGame: true,
online: false,
});
}
main().catch(console.error);
這段程式碼展示了如何取得單位 ID,並將其轉換為 GameObjectData
與 UnitData
,再輸出位置、生命值、武器等關鍵欄位。
這些方法在整個專案中被廣泛使用,例如任務系統會使用它們來更新重心位置:
const movableUnitTiles = this.unitIds
.map((unitId) => gameApi.getUnitData(unitId))
.filter((unit) => unit?.canMove)
.map((unit) => unit?.tile)
.filter((tile) => !!tile) as Tile[];
意識模組則會先將可見單位 ID 轉換為物件後,再更新四叉樹:
const hostileUnits = hostileUnitIds
.map((id) => game.getGameObjectData(id))
.filter(
(gameObjectData: GameObjectData | undefined): gameObjectData is GameObjectData =>
gameObjectData !== undefined,
);
透過將數字 ID 轉換為結構化資料,Bot 可以取得規則定義、當前生命值、武器等眾多屬性,使其能夠理解世界狀態並做出決策。
→返回《@chronodivide/game-api 使用教學與完整 API 對照表》
This article was last edited at