/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.petah.spring.bai.map.control; import com.springrts.ai.oo.AIFloat3; import java.awt.Point; import java.util.List; import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; 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.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.GlobalDelegate; import org.petah.spring.bai.delegate.TeamDelegate; import org.petah.spring.bai.listener.UpdateEventListener; import org.petah.spring.bai.util.FormatUtil; import org.petah.spring.bai.util.MapUtil; /** * * @author Petah */ public class ControlMap extends UpdateAdapter implements UpdateEventListener { // Control map options private static Option<Integer> updateTime = OptionsManager.getOption( new Option<Integer>("ControlMap.updateTime", 40)); private static Option<Integer> unknownUnitPower = OptionsManager.getOption( new Option<Integer>("ControlMap.unknownUnitPower", 100), new Option<String>("description", "Amount of power to allocate a unit when it is not known (In radar not LOS).")); // Class properties private TeamDelegate teamDelegate; /** * Control zones */ private final Map<Point, ControlZone> controlZones = new ConcurrentHashMap<Point, ControlZone>(); /** * Next frame to update the control map on */ private int nextUpdate = 0; /** * Future object returned from the update thread */ private Future updateFuture; public ControlMap(TeamDelegate teamDelegate) { this.teamDelegate = teamDelegate; Profiler.start(ControlMap.class, "ControlMap()"); createControlZones(); Profiler.stop(ControlMap.class, "ControlMap()"); } /** * Updates the control 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("ControlMap.update()", new Runnable() { public void run() { update(); } }); } } } private ControlZone getUnitZone(CachedUnit unit) { AIFloat3 pos = unit.getPos(); Point point = new Point((int) (MapUtil.terrainToMap(pos.x) / ControlZone.getSize()), (int) (MapUtil.terrainToMap(pos.z) / ControlZone.getSize())); ControlZone zone = controlZones.get(point); if (zone.getX() == 0 || zone.getY() == 0) { // TODO: fix this bug // System.err.println(FormatUtil.formatAIFloat3(pos)); // System.err.println(MapUtil.terrainToMap(pos.x) + "\t/ " + ControlZone.getSize() + "\t, " + MapUtil.terrainToMap(pos.z) + "\t/ " + ControlZone.getSize()); } // if (zone == null) { // Logger.getLogger(ControlMap.class.getName()).warning("Unit outside all valid control zones: " + // unit.getDef().getHumanName() + " " + pos.x + ", " + pos.z); // } return zone; } private void updateZones(CachedUnit unit, boolean friendly) { ControlZone zone = getUnitZone(unit); // System.err.println("ControlMap.updateZones(" + unit.getUnitId() + ", " + zone.getX() + ", " + zone.getY() + ")"); if (zone != null) { if (friendly) { zone.incPower(unit.getPower()); } else { zone.decPower(unit.getPower() == -1 ? unknownUnitPower.getValue() : unit.getPower()); } } } private void createControlZones() { for (int x = 0; x < GlobalDelegate.getMapWidth() / ControlZone.getSize(); x++) { for (int y = 0; y < GlobalDelegate.getMapHeight() / ControlZone.getSize(); y++) { controlZones.put(new Point(x, y), new ControlZone(x, y)); } } } /** * Updates the ControlMap's state. */ private void update() { Profiler.start(ControlMap.class, "update()"); for (ControlZone zone : controlZones.values()) { zone.reset(); } for (CachedUnit unit : teamDelegate.getFriendlyUnits().values()) { updateZones(unit, true); } for (CachedUnit unit : teamDelegate.getEnemyUnits().values()) { updateZones(unit, false); } // Update listeners fireUpdate(this); Profiler.stop(ControlMap.class, "update()"); } public Collection<ControlZone> getControlZones() { return controlZones.values(); } public List<ControlZone> getEnemyControlZones() { List<ControlZone> enemyControlZones = new ArrayList<ControlZone>(); for (ControlZone zone : controlZones.values()) { if (zone.isEnemy()) { enemyControlZones.add(zone); } } return enemyControlZones; } public List<ControlZone> getFriendlyControlZones() { List<ControlZone> friendlyControlZones = new ArrayList<ControlZone>(); for (ControlZone zone : controlZones.values()) { if (zone.isFriendly()) { friendlyControlZones.add(zone); } } return friendlyControlZones; } public List<ControlZone> getNeutralControlZones() { List<ControlZone> neutralControlZones = new ArrayList<ControlZone>(); for (ControlZone zone : controlZones.values()) { if (zone.isNeutral()) { neutralControlZones.add(zone); } } return neutralControlZones; } }