r.addDesc(entity);
r.subject = entity.getId();
addReport(r);
//until we get a rules clarification assume that the entity is both giver and taker
//for charge damage
HitData hit = entity.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT);
addReport(damageEntity(entity, hit, ChargeAttackAction.getDamageTakenBy(entity, entity)));
turnOver = true;
break;
}
}
}
}
// check for breaking magma crust
if ((curHex.terrainLevel(Terrains.MAGMA) == 1) && (step.getElevation() == 0) && (step.getMovementType() != IEntityMovementType.MOVE_JUMP)) {
int roll = Compute.d6(1);
r = new Report(2395);
r.addDesc(entity);
r.add(roll);
r.subject = entity.getId();
addReport(r);
if (roll == 6) {
curHex.removeTerrain(Terrains.MAGMA);
curHex.addTerrain(Terrains.getTerrainFactory().createTerrain(Terrains.MAGMA, 2));
sendChangedHex(curPos);
for (Enumeration<Entity> e = game.getEntities(curPos); e.hasMoreElements();) {
Entity en = e.nextElement();
if (en != entity) {
doMagmaDamage(en, false);
}
}
}
}
// check for entering liquid magma
if ((curHex.terrainLevel(Terrains.MAGMA) == 2) && (step.getElevation() == 0) && (step.getMovementType() != IEntityMovementType.MOVE_JUMP)) {
doMagmaDamage(entity, false);
}
// check if we've moved into a swamp
rollTarget = entity.checkBogDown(step, curHex, lastPos, curPos, lastElevation, isPavementStep);
if (rollTarget.getValue() != TargetRoll.CHECK_FALSE) {
if (0 < doSkillCheckWhileMoving(entity, lastPos, curPos, rollTarget, false)) {
entity.setStuck(true);
entity.setCanUnstickByJumping(true);
r = new Report(2081);
r.add(entity.getDisplayName());
r.subject = entity.getId();
addReport(r);
//check for quicksand
addReport(checkQuickSand(curPos));
// check for accidental stacking violation
Entity violation = Compute.stackingViolation(game, entity.getId(), curPos);
if (violation != null) {
// target gets displaced, because of low elevation
int direction = lastPos.direction(curPos);
Coords targetDest = Compute.getValidDisplacement(game, entity.getId(), curPos, direction);
addReport(doEntityDisplacement(violation, curPos, targetDest, new PilotingRollData(violation.getId(), 0, "domino effect")));
// Update the violating entity's postion on the client.
entityUpdate(violation.getId());
}
break;
}
}
// check to see if we are a mech and we've moved OUT of fire
IHex lastHex = game.getBoard().getHex(lastPos);
if (entity instanceof Mech) {
if (!lastPos.equals(curPos) && (prevStep != null) && ((lastHex.containsTerrain(Terrains.FIRE) && (prevStep.getElevation() <= 1)) || (lastHex.containsTerrain(Terrains.MAGMA) && (prevStep.getElevation() == 0))) && ((step.getMovementType() != IEntityMovementType.MOVE_JUMP)
// Bug #828741 -- jumping bypasses fire, but not on the
// first step
// getMpUsed -- total MP used to this step
// getMp -- MP used in this step
// the difference will always be 0 on the "first step"
// of a jump,
// and >0 on a step in the midst of a jump
|| (0 == step.getMpUsed() - step.getMp()))) {
int heat = 0;
if (lastHex.containsTerrain(Terrains.FIRE)) {
heat += 2;
}
if (lastHex.terrainLevel(Terrains.MAGMA) == 1) {
heat += 2;
} else if (lastHex.terrainLevel(Terrains.MAGMA) == 2) {
heat += 5;
}
entity.heatFromExternal += heat;
r = new Report(2115);
r.subject = entity.getId();
r.addDesc(entity);
r.add(heat);
addReport(r);
}
}
// check to see if we are not a mech and we've moved INTO fire
if (!(entity instanceof Mech)) {
if (game.getBoard().getHex(curPos).containsTerrain(Terrains.FIRE) && !lastPos.equals(curPos) && (step.getMovementType() != IEntityMovementType.MOVE_JUMP) && (step.getElevation() <= 1)) {
doFlamingDamage(entity);
}
}
// check for extreme gravity movement
if (!i.hasMoreElements() && !firstStep) {
checkExtremeGravityMovement(entity, step, curPos, cachedGravityLimit);
}
// check for minefields. have to check both new hex and new elevation
// VTOLs may land and submarines may rise or lower into a minefield
if (!lastPos.equals(curPos) || (lastElevation != curElevation)) {
boolean boom = false;
boolean isOnGround = !i.hasMoreElements();
isOnGround |= step.getMovementType() != IEntityMovementType.MOVE_JUMP;
isOnGround &= step.getElevation() < 1;
if(isOnGround) {
boom = checkVibrabombs(entity, curPos, false, lastPos, curPos, vPhaseReport);
}
if (game.containsMinefield(curPos)) {
// set the new position temporarily, because
// infantry otherwise would get double damage
// when moving from clear into mined woods
entity.setPosition(curPos);
if(enterMinefield(entity, curPos, step.getElevation(), isOnGround, vPhaseReport)) {
//resolve any piloting rolls from damage unless unit was jumping
if(step.getMovementType() != IEntityMovementType.MOVE_JUMP) {
addReport(resolvePilotingRolls(entity));
game.resetPSRs(entity);
}
boom = true;
}
if(wasProne || !entity.isProne()) {
entity.setPosition(lastPos);
}
}
//did anything go boom?
if(boom) {
//set fell during movement so that entity will get another chance to move with any motive damage
//taken account of (functions the same as MASC failure)
//only do this if they had more steps (and they were not jumping
if(i.hasMoreElements() && (step.getMovementType() != IEntityMovementType.MOVE_JUMP)) {
md.clear();
fellDuringMovement = true;
}
//reset mines if anything detonated
resetMines();
}
}
// infantry discovers minefields if they end their move
// in a minefield.
if (!lastPos.equals(curPos) && !i.hasMoreElements() && isInfantry) {
if (game.containsMinefield(curPos)) {
Player owner = entity.getOwner();
for (Minefield mf : game.getMinefields(curPos)) {
if (!owner.containsMinefield(mf)) {
r = new Report(2120);
r.subject = entity.getId();
r.add(entity.getShortName(), true);
addReport(r);
revealMinefield(game.getTeamForPlayer(owner), mf);
}
}
}
}
// check if we've moved into water
rollTarget = entity.checkWaterMove(step, curHex, lastPos, curPos, isPavementStep);
if (rollTarget.getValue() != TargetRoll.CHECK_FALSE) {
// Swarmers need special handling.
final int swarmerId = entity.getSwarmAttackerId();
boolean swarmerDone = true;
Entity swarmer = null;
if (Entity.NONE != swarmerId) {
swarmer = game.getEntity(swarmerId);
swarmerDone = swarmer.isDone();
}
// Now do the skill check.
doSkillCheckWhileMoving(entity, lastPos, curPos, rollTarget, true);
// Swarming infantry platoons may drown.
if (curHex.terrainLevel(Terrains.WATER) > 1) {
drownSwarmer(entity, curPos);
}
// Do we need to remove a game turn for the swarmer
if (!swarmerDone && (swarmer != null) && (swarmer.isDoomed() || swarmer.isDestroyed())) {
// We have to diddle with the swarmer's
// status to get its turn removed.
swarmer.setDone(false);
swarmer.setUnloaded(false);
// Dead entities don't take turns.
game.removeTurnFor(swarmer);
send(createTurnVectorPacket());
// Return the original status.
swarmer.setDone(true);
swarmer.setUnloaded(true);
}
// check for inferno wash-off
checkForWashedInfernos(entity, curPos);
}
// In water, may or may not be a new hex, neccessary to
// check during movement, for breach damage, and always
// set dry if appropriate
// TODO: possibly make the locations local and set later
addReport(doSetLocationsExposure(entity, curHex, step.getMovementType() == IEntityMovementType.MOVE_JUMP, step.getElevation()));
// check for breaking ice by breaking through from below
if ((lastElevation < 0) && (step.getElevation() == 0)
&& lastHex.containsTerrain(Terrains.ICE) && lastHex.containsTerrain(Terrains.WATER)
&& (step.getMovementType() != IEntityMovementType.MOVE_JUMP) && !lastPos.equals(curPos)) {
//need to temporarily reset entity's position so it doesn't fall in the ice
entity.setPosition(curPos);
r = new Report(2410);
r.addDesc(entity);
addReport(r);
addReport(resolveIceBroken(lastPos));
//ok now set back
entity.setPosition(lastPos);
}
// check for breaking ice by stepping on it
if (curHex.containsTerrain(Terrains.ICE) && curHex.containsTerrain(Terrains.WATER)
&& (step.getMovementType() != IEntityMovementType.MOVE_JUMP)
&& !lastPos.equals(curPos)
&& !(entity instanceof Infantry)
&& !(step.isPavementStep() && curHex.containsTerrain(Terrains.BRIDGE))) {
if (step.getElevation() == 0) {
int roll = Compute.d6(1);
r = new Report(2118);
r.addDesc(entity);
r.add(roll);
r.subject = entity.getId();
addReport(r);
if (roll == 6) {
entity.setPosition(curPos);
addReport(resolveIceBroken(curPos));
curPos = entity.getPosition();
}
}
// or intersecting it
else if (step.getElevation() + entity.height() == 0) {
r = new Report(2410);
r.addDesc(entity);
addReport(r);
addReport(resolveIceBroken(curPos));
}
}
// Handle loading units.
if (step.getType() == MovePath.STEP_LOAD) {
// Find the unit being loaded.
Entity loaded = null;
Enumeration<Entity> entities = game.getEntities(curPos);
while (entities.hasMoreElements()) {
// Is the other unit friendly and not the current entity?
loaded = entities.nextElement();
if (!entity.isEnemyOf(loaded) && !entity.equals(loaded)) {
// The moving unit should be able to load the other
// unit and the other should be able to have a turn.
if (!entity.canLoad(loaded) || !loaded.isLoadableThisTurn()) {
// Something is fishy in Denmark.
System.err.println(entity.getShortName() + " can not load " + loaded.getShortName());
loaded = null;
} else {
// Have the deployed unit load the indicated unit.
loadUnit(entity, loaded);
// Stop looking.
break;
}
} else {
// Nope. Discard it.
loaded = null;
}
} // Handle the next entity in this hex.
// We were supposed to find someone to load.
if (loaded == null) {
System.err.println("Could not find unit for " + entity.getShortName() + " to load in " + curPos);
}
} // End STEP_LOAD
// handle fighter recovery
if (step.getType() == MovePath.STEP_RECOVER) {
loader = game.getEntity(step.getRecoveryUnit());
PilotingRollData psr = entity.getBasePilotingRoll(overallMoveType);
if (loader.mpUsed > 0) {
psr.addModifier(5, "carrier used thrust");
}
int ctrlroll = Compute.d6(2);
r = new Report(9381);
r.subject = entity.getId();
r.add(entity.getDisplayName());
r.add(loader.getDisplayName());
r.add(psr.getValue());
r.add(ctrlroll);
r.newlines = 0;
r.indent(1);
if (ctrlroll < psr.getValue()) {
r.choose(false);
addReport(r);
// damage unit
Aero a = (Aero) entity;
HitData hit = a.rollHitLocation(ToHitData.HIT_NORMAL, ToHitData.SIDE_FRONT);
addReport(damageEntity(entity, hit, 2 * (psr.getValue() - ctrlroll)));
} else {
r.choose(true);
addReport(r);
recovered = true;