/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.petah.spring.bai.map.target; import com.springrts.ai.oo.AIFloat3; import java.awt.Point; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; import org.petah.common.event.UpdateAdapter; import org.petah.common.option.Option; import org.petah.common.option.OptionsManager; import org.petah.common.util.GameMath; import org.petah.common.util.profiler.Profiler; import org.petah.spring.bai.AIReturnCode; import org.petah.spring.bai.ThreadManager; import org.petah.spring.bai.cache.CachedUnit; import org.petah.spring.bai.delegate.TeamDelegate; import org.petah.spring.bai.listener.UpdateEventListener; import org.petah.spring.bai.unit.UnitInfo; import org.petah.spring.bai.unit.UnitType; /** * * @author Petah */ public class TargetMap extends UpdateAdapter implements UpdateEventListener { // Target map options private static Option<Integer> updateTime = OptionsManager.getOption( new Option<Integer>("TargetMap.updateTime", 40)); private static Option<Integer> maxDistance = OptionsManager.getOption( new Option<Integer>("TargetMap.maxDistance", 1000)); // Class properties private TeamDelegate teamDelegate; private Map<TargetType, CopyOnWriteArrayList<TargetZone>> targetZones = new ConcurrentHashMap<TargetType, CopyOnWriteArrayList<TargetZone>>(); /** * Next frame to update the target map on */ private int nextUpdate = 0; /** * Future object returned from the update thread */ private Future updateFuture; public TargetMap(TeamDelegate teamDelegate) { this.teamDelegate = teamDelegate; } /** * Updates the target map periodically. * @param frame the current frame */ public void update(int frame) { if (nextUpdate <= frame) { nextUpdate = frame + updateTime.getValue(); if (updateFuture == null || updateFuture.isDone()) { updateFuture = ThreadManager.run("TargetMap.update()", new Runnable() { public void run() { update(); } }); } } } private void update() { Profiler.start(TargetMap.class, "update()"); targetZones.clear(); for (CachedUnit unit : teamDelegate.getEnemyUnits().values()) { AIFloat3 pos = unit.getPos(); TargetType type = getTargetType(unit); TargetZone zone = getClosestTargetZone(pos, type); if (zone == null) { zone = new TargetZone(type); CopyOnWriteArrayList<TargetZone> zones = targetZones.get(type); if (zones == null) { zones = new CopyOnWriteArrayList<TargetZone>(); targetZones.put(type, zones); } zones.add(zone); } zone.addUnit(unit); } fireUpdate(this); Profiler.stop(TargetMap.class, "update()"); } private TargetType getTargetType(CachedUnit unit) { UnitInfo info = unit.getUnitInfo(); if (info != null) { if (info.isType(UnitType.MetalExtractor) || info.isType(UnitType.MetalMaker) || info.isType(UnitType.MetalStorage)) { return TargetType.Metal; } else if (info.isType(UnitType.EnergyGenerator) || info.isType(UnitType.EnergyStorage)) { return TargetType.Energy; } else if (info.isType(UnitType.Nuke)) { return TargetType.Nuke; } else if (info.isType(UnitType.AntiNuke)) { return TargetType.AntiNuke; } else if (info.isType(UnitType.AntiAir)) { return TargetType.AntiAir; } else if (info.isType(UnitType.DefenseTower)) { return TargetType.DefenceTowers; } else if (info.isType(UnitType.Factory)) { return TargetType.Factory; } else if (info.isType(UnitType.Nano)) { return TargetType.Nanos; } else if (info.isType(UnitType.Building)) { return TargetType.Buildings; } else if (info.isType(UnitType.Commander)) { return TargetType.Commander; } else if (info.isType(UnitType.Builder) || info.isType(UnitType.Scavenger)) { return TargetType.Builders; } else if (info.isType(UnitType.Aircraft)) { return TargetType.Aircraft; } else if (info.isType(UnitType.Hovercraft)) { return TargetType.Hovercraft; } else if (info.isType(UnitType.Ship) || info.isType(UnitType.Submarine)) { return TargetType.Ships; } else if (info.isType(UnitType.Kbot) || info.isType(UnitType.Vehicle)) { return TargetType.Units; } } return TargetType.Unknown; } private TargetZone getClosestTargetZone(AIFloat3 pos, TargetType type) { if (targetZones.containsKey(type)) { for (TargetZone zone : targetZones.get(type)) { if (zone.getTargetType() == type) { AIFloat3 center = zone.getPosition(); float distance = GameMath.pointDistance(center.x, center.z, pos.x, pos.z); if (distance < maxDistance.getValue()) { return zone; } } } } return null; } public List<TargetZone> getTargetZones() { List<TargetZone> zones = new LinkedList<TargetZone>(); Iterator<TargetType> i = targetZones.keySet().iterator(); while (i.hasNext()) { CopyOnWriteArrayList<TargetZone> targetZoneList = targetZones.get(i.next()); if (targetZoneList != null) { zones.addAll(targetZoneList); } } // for (TargetType type : targetZones.keySet()) { // zones.addAll(targetZones.get(type)); // } return zones; } public List<TargetZone> getTargetZones(TargetType type) { return targetZones.get(type); } }