📄 fireprocessor.java
字号:
/* * MegaMek - * Copyright (C) 2000,2001,2002,2003,2004,2005 Ben Mazur (bmazur@sev.org) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */package megamek.server;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;import megamek.common.Building;import megamek.common.Compute;import megamek.common.Coords;import megamek.common.IBoard;import megamek.common.IGame;import megamek.common.IHex;import megamek.common.Report;import megamek.common.Terrains;public class FireProcessor extends DynamicTerrainProcessor { private IGame game; Vector<Report> vPhaseReport; public FireProcessor(Server server) { super(server); // TODO Auto-generated constructor stub } @Override void DoEndPhaseChanges(Vector<Report> vPhaseReport) { this.vPhaseReport = vPhaseReport; game = server.getGame(); resolveFire(); this.vPhaseReport = null; } /** * This debug/profiling function will print the current time * (in milliseconds) to the log. If the boolean is true, the * garbage collector will be called in an attempt to minimize * timing errors. You should try and minimize applications * being run in the background when using this function. * Note that MS Windows only has 10 milisecond resolution. * * The function should be optimized completely out of the code * when the first if-statement below reads "if (false)...", so * performance shouldn't be impacted if you leave calls to this * function in the code (I think). */ private void debugTime(String s, boolean collectGarbage) { //Change the "false" below to "true" to enable this function if (false) { if (collectGarbage) System.gc(); System.out.println(s + ": " + System.currentTimeMillis()); } } /** * Make fires spread, smoke spread, and make sure that all fires * started this turn are marked as "burning" for next turn. * * A "FIRE" terrain has one of two levels: * 1 (Created this turn, and so can't spread of generate heat) * 2 (Created as a result of spreading fire or on a previous turn) * * Since fires created at end of turn act normally in the following turn, * spread fires have level 2. * * At NO TIME should any fire created outside this function have a level of * 2, nor should anything except this function SET fires to level 2. * * Newly created "spread" fires have a level of 1, so that they do not * spread in the turn they are created. After all spreading has been * completed, all burning hexes are set to level 2. */ private void resolveFire() { IBoard board = game.getBoard(); int width = board.getWidth(); int height = board.getHeight(); int windDirection = game.getWindDirection(); Report r; // Get the position map of all entities in the game. Hashtable positionMap = game.getPositionMap(); // Build vector to send for updated buildings at once. Vector burningBldgs = new Vector(); // If we're in L3 rules, process smoke FIRST, before any fires spread or smoke is produced. if (game.getOptions().booleanOption("maxtech_fire")) { resolveSmoke(); } // Cycle through all buildings, checking for fire. // ASSUMPTION: buildings don't lose 2 CF on the turn a fire starts. // ASSUMPTION: multi-hex buildings lose 2 CF max, regardless of # fires Enumeration buildings = game.getBoard().getBuildings(); while ( buildings.hasMoreElements() ) { Building bldg = (Building) buildings.nextElement(); if ( bldg.isBurning() ) { int cf = Math.max(bldg.getCurrentCF() - 2, 0); bldg.setCurrentCF( cf ); // Does the building burned down? if ( cf == 0 ) { r = new Report(5120, Report.PUBLIC); r.add(bldg.getName()); vPhaseReport.addElement(r); server.collapseBuilding( bldg, positionMap ); } // If it doesn't collapse under its load, mark it for update. else if ( !server.checkForCollapse(bldg, positionMap) ) { bldg.setPhaseCF( cf ); burningBldgs.addElement( bldg ); } } } debugTime("resolve fire 1", true); // Cycle through all hexes, checking for fire. for (int currentXCoord = 0; currentXCoord < width; currentXCoord++ ) { for (int currentYCoord = 0; currentYCoord < height; currentYCoord++) { Coords currentCoords = new Coords(currentXCoord, currentYCoord); IHex currentHex = board.getHex(currentXCoord, currentYCoord); boolean infernoBurning = board.burnInferno( currentCoords ); // optional rule, woods burn down if ((currentHex.containsTerrain(Terrains.WOODS) || currentHex.containsTerrain(Terrains.JUNGLE)) && currentHex.terrainLevel(Terrains.FIRE) == 2 && game.getOptions().booleanOption("woods_burn_down")) { burnDownWoods(currentCoords); } // If the woods has been cleared, or the building // has collapsed put non-inferno fires out. if ( currentHex.containsTerrain(Terrains.FIRE) && !infernoBurning && !(currentHex.containsTerrain(Terrains.WOODS)) && !(currentHex.containsTerrain(Terrains.JUNGLE)) && !(currentHex.containsTerrain(Terrains.FUEL_TANK)) && !(currentHex.containsTerrain(Terrains.BUILDING)) ) { server.removeFire(currentXCoord, currentYCoord, currentHex); } // Was the fire started on a previous turn? else if (currentHex.terrainLevel(Terrains.FIRE) == 2) { r = new Report(5125, Report.PUBLIC); if ( infernoBurning ) r.messageId = 5130; r.add(currentCoords.getBoardNum()); vPhaseReport.addElement(r); spreadFire(currentXCoord, currentYCoord, windDirection); } } } debugTime("resolve fire 1 end, begin resolve fire 2", true); // Loop a second time, to set all fires to level 2 before next turn, and add smoke. for (int currentXCoord = 0; currentXCoord < width; currentXCoord++ ) { for (int currentYCoord = 0; currentYCoord < height; currentYCoord++) { Coords currentCoords = new Coords(currentXCoord, currentYCoord); IHex currentHex = board.getHex(currentXCoord,currentYCoord); // if the fire in the hex was started this turn if (currentHex.terrainLevel(Terrains.FIRE) == 1) { currentHex.removeTerrain(Terrains.FIRE); currentHex.addTerrain(Terrains.getTerrainFactory().createTerrain(Terrains.FIRE, 2)); server.sendChangedHex(currentCoords); //fire started this round r = new Report(5135, Report.PUBLIC); r.add(currentCoords.getBoardNum()); vPhaseReport.addElement(r); // If the hex contains a building, set it on fire. Building bldg = game.getBoard().getBuildingAt( currentCoords ); if ( bldg != null ) { bldg.setBurning( true ); burningBldgs.addElement( bldg ); } } // If the L3 smoke rule is off, add smoke normally, otherwise call the L3 method if (currentHex.containsTerrain(Terrains.FIRE) && !game.getOptions().booleanOption("maxtech_fire")) { server.addSmoke(currentXCoord, currentYCoord, windDirection); server.addSmoke(currentXCoord, currentYCoord, (windDirection+1)%6); server.addSmoke(currentXCoord, currentYCoord, (windDirection+5)%6); board.initializeAround(currentXCoord,currentYCoord); } else if (currentHex.containsTerrain(Terrains.FIRE) && game.getOptions().booleanOption("maxtech_fire")) { server.addL3Smoke(currentXCoord, currentYCoord); board.initializeAround(currentXCoord, currentYCoord); } } } debugTime("resolve fire 2 end", false); // If any buildings are burning, update the clients. if ( !burningBldgs.isEmpty() ) { server.sendChangedCFBuildings(burningBldgs); } // If we're in L3 rules, shift the wind. if (game.getOptions().booleanOption("maxtech_fire")) { game.determineWind(); } } // End the ResolveFire() method public void burnDownWoods(Coords coords) { IHex hex = game.getBoard().getHex(coords); int roll = Compute.d6(2); Report r; if(roll >= 11) { if(hex.terrainLevel(Terrains.WOODS) > 2) { hex.removeTerrain(Terrains.WOODS); hex.addTerrain(Terrains.getTerrainFactory().createTerrain(Terrains.WOODS, 2)); //ultra heavy woods burned down to heavy woods r = new Report(5141, Report.PUBLIC); r.add(coords.getBoardNum()); vPhaseReport.addElement(r); } else if(hex.terrainLevel(Terrains.WOODS) == 2) { hex.removeTerrain(Terrains.WOODS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -