mirror of
https://github.com/Retera/WarsmashModEngine.git
synced 2022-07-31 17:38:59 +02:00
Some updates to attempt to support loading a 1.32 map
This commit is contained in:
parent
38f67af599
commit
92fc60eb45
@ -29,6 +29,7 @@ import com.etheller.interpreter.ast.scope.trigger.Trigger;
|
||||
import com.etheller.interpreter.ast.scope.trigger.TriggerBooleanExpression;
|
||||
import com.etheller.interpreter.ast.scope.variableevent.CLimitOp;
|
||||
import com.etheller.interpreter.ast.util.CHandle;
|
||||
import com.etheller.interpreter.ast.util.JassSettings;
|
||||
import com.etheller.interpreter.ast.value.BooleanJassValue;
|
||||
import com.etheller.interpreter.ast.value.HandleJassType;
|
||||
import com.etheller.interpreter.ast.value.HandleJassValue;
|
||||
@ -68,6 +69,7 @@ import com.etheller.warsmash.util.WarsmashConstants;
|
||||
import com.etheller.warsmash.viewer5.Scene;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.UnitSound;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.environment.RenderCorner;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderDestructable;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.ItemUI;
|
||||
@ -134,9 +136,11 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.C
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CWeaponSoundTypeJass;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.unit.CUnitTypeJass;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityActivationReceiver;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityTargetCheckReceiver;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.CHashtable;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.PointAbilityTargetCheckReceiver;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog.CScriptDialog;
|
||||
|
||||
public class Jass2 {
|
||||
public static final boolean REPORT_SYNTAX_ERRORS = true;
|
||||
@ -538,6 +542,7 @@ public class Jass2 {
|
||||
final HandleJassType imageType = globals.registerHandleType("image");
|
||||
final HandleJassType ubersplatType = globals.registerHandleType("ubersplat");
|
||||
final HandleJassType hashtableType = globals.registerHandleType("hashtable");
|
||||
final HandleJassType frameHandleType = globals.registerHandleType("framehandle");
|
||||
|
||||
jassProgramVisitor.getJassNativeManager().createNative("ConvertRace", new JassFunction() {
|
||||
@Override
|
||||
@ -1226,7 +1231,8 @@ public class Jass2 {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new HandleJassValue(timerType, new CTimerJass(globalScope));
|
||||
return new HandleJassValue(timerType,
|
||||
new CTimerJass(globalScope, simulation.getHandleIdAllocator().createId()));
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("DestroyTimer", new JassFunction() {
|
||||
@ -1245,7 +1251,7 @@ public class Jass2 {
|
||||
final CTimerJass timer = arguments.get(0).visit(ObjectJassValueVisitor.<CTimerJass>getInstance());
|
||||
final Double timeout = arguments.get(1).visit(RealJassValueVisitor.getInstance());
|
||||
final boolean periodic = arguments.get(2).visit(BooleanJassValueVisitor.getInstance());
|
||||
final JassFunction handlerFunc = arguments.get(3).visit(JassFunctionJassValueVisitor.getInstance());
|
||||
final JassFunction handlerFunc = nullable(arguments, 3, JassFunctionJassValueVisitor.getInstance());
|
||||
if (!timer.isRunning()) {
|
||||
timer.setTimeoutTime(timeout.floatValue());
|
||||
timer.setRepeats(periodic);
|
||||
@ -1393,6 +1399,9 @@ public class Jass2 {
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
if (whichUnit == null) {
|
||||
return BooleanJassValue.FALSE;
|
||||
}
|
||||
final String orderString = arguments.get(1).visit(StringJassValueVisitor.getInstance());
|
||||
final Point2D.Double whichLocation = arguments.get(2)
|
||||
.visit(ObjectJassValueVisitor.<Point2D.Double>getInstance());
|
||||
@ -1415,8 +1424,37 @@ public class Jass2 {
|
||||
}
|
||||
}
|
||||
}
|
||||
defaultPlayerUnitOrderExecutor.issuePointOrder(whichUnit.getHandleId(), abilityHandleId, orderId,
|
||||
targetAsPoint.x, targetAsPoint.y, false);
|
||||
if (abilityHandleId != 0) {
|
||||
defaultPlayerUnitOrderExecutor.issuePointOrder(whichUnit.getHandleId(), abilityHandleId,
|
||||
orderId, targetAsPoint.x, targetAsPoint.y, false);
|
||||
}
|
||||
return BooleanJassValue.of(abilityHandleId != 0);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("IssueImmediateOrder", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
final String orderString = arguments.get(1).visit(StringJassValueVisitor.getInstance());
|
||||
final CPlayerUnitOrderExecutor defaultPlayerUnitOrderExecutor = simulation
|
||||
.getDefaultPlayerUnitOrderExecutor(whichUnit.getPlayerIndex());
|
||||
final BooleanAbilityActivationReceiver activationReceiver = BooleanAbilityActivationReceiver.INSTANCE;
|
||||
final int orderId = OrderIdUtils.getOrderId(orderString);
|
||||
int abilityHandleId = 0;
|
||||
for (final CAbility ability : whichUnit.getAbilities()) {
|
||||
ability.checkCanUse(simulation, whichUnit, orderId, activationReceiver);
|
||||
if (activationReceiver.isOk()) {
|
||||
final BooleanAbilityTargetCheckReceiver<Void> targetReceiver = BooleanAbilityTargetCheckReceiver
|
||||
.<Void>getInstance();
|
||||
ability.checkCanTargetNoTarget(simulation, whichUnit, orderId, targetReceiver.reset());
|
||||
if (targetReceiver.isTargetable()) {
|
||||
abilityHandleId = ability.getHandleId();
|
||||
}
|
||||
}
|
||||
}
|
||||
defaultPlayerUnitOrderExecutor.issueImmediateOrder(whichUnit.getHandleId(), abilityHandleId,
|
||||
orderId, false);
|
||||
return BooleanJassValue.of(abilityHandleId != 0);
|
||||
}
|
||||
});
|
||||
@ -1915,12 +1953,12 @@ public class Jass2 {
|
||||
.visit(ObjectJassValueVisitor.<List<CPlayerJass>>getInstance());
|
||||
final CPlayerJass player = arguments.get(1)
|
||||
.visit(ObjectJassValueVisitor.<CPlayerJass>getInstance());
|
||||
final TriggerBooleanExpression filter = arguments.get(2)
|
||||
.visit(ObjectJassValueVisitor.<TriggerBooleanExpression>getInstance());
|
||||
final TriggerBooleanExpression filter = nullable(arguments, 2,
|
||||
ObjectJassValueVisitor.<TriggerBooleanExpression>getInstance());
|
||||
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
|
||||
final CPlayerJass jassPlayer = simulation.getPlayer(i);
|
||||
if (!player.hasAlliance(i, CAllianceType.PASSIVE)) {
|
||||
if (filter.evaluate(globalScope,
|
||||
if ((filter != null) && filter.evaluate(globalScope,
|
||||
CommonTriggerExecutionScope.filterScope(triggerScope, jassPlayer))) {
|
||||
force.add(jassPlayer);
|
||||
}
|
||||
@ -2337,7 +2375,7 @@ public class Jass2 {
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final Trigger trigger = arguments.get(0).visit(ObjectJassValueVisitor.<Trigger>getInstance());
|
||||
final String varName = arguments.get(1).visit(ObjectJassValueVisitor.<String>getInstance());
|
||||
final String varName = arguments.get(1).visit(StringJassValueVisitor.getInstance());
|
||||
final CLimitOp limitOp = arguments.get(2).visit(ObjectJassValueVisitor.<CLimitOp>getInstance());
|
||||
final Double limitval = arguments.get(3).visit(RealJassValueVisitor.getInstance());
|
||||
final RemovableTriggerEvent event = globalScope.registerVariableEvent(trigger, varName, limitOp,
|
||||
@ -2399,11 +2437,112 @@ public class Jass2 {
|
||||
simulation.registerTimeOfDayEvent(globalScope, trigger, opcode, limitval.doubleValue()));
|
||||
}
|
||||
});
|
||||
if (JassSettings.CONTINUE_EXECUTING_ON_ERROR) {
|
||||
// TODO this is a dumb stub that wont function
|
||||
jassProgramVisitor.getJassNativeManager().createNative("TriggerRegisterUnitStateEvent",
|
||||
new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new HandleJassValue(eventType, RemovableTriggerEvent.DO_NOTHING);
|
||||
}
|
||||
});
|
||||
}
|
||||
jassProgramVisitor.getJassNativeManager().createNative("DialogCreate", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new HandleJassValue(dialogType, meleeUI.createScriptDialog(globalScope));
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("DialogDestroy", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CScriptDialog dialog = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
meleeUI.destroyDialog(dialog);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("DialogClear", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CScriptDialog dialog = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
meleeUI.clearDialog(dialog);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("DialogSetMessage", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CScriptDialog dialog = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
final String messageText = arguments.get(1).visit(StringJassValueVisitor.getInstance());
|
||||
dialog.setTitle(CommonEnvironment.this.gameUI, messageText);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("DialogAddButton", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CScriptDialog dialog = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
final String buttonText = arguments.get(1).visit(StringJassValueVisitor.getInstance());
|
||||
final int hotkeyInt = arguments.get(2).visit(IntegerJassValueVisitor.getInstance());
|
||||
meleeUI.createScriptDialogButton(dialog, buttonText, (char) hotkeyInt);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("DialogDisplay", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CPlayerJass player = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
final CScriptDialog whichDialog = arguments.get(1).visit(ObjectJassValueVisitor.getInstance());
|
||||
final boolean flag = arguments.get(2).visit(BooleanJassValueVisitor.getInstance());
|
||||
if (player.getId() == war3MapViewer.getLocalPlayerIndex()) {
|
||||
whichDialog.setVisible(flag);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("SetUnitAcquireRange", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CUnit unit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
final double range = arguments.get(1).visit(RealJassValueVisitor.getInstance());
|
||||
unit.setAcquisitionRange((float) range);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetClickedButton", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new HandleJassValue(buttonType,
|
||||
((CommonTriggerExecutionScope) triggerScope).getClickedButton());
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetClickedDialog", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return new HandleJassValue(dialogType,
|
||||
((CommonTriggerExecutionScope) triggerScope).getClickedDialog());
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("TriggerRegisterDialogEvent", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
throw new UnsupportedOperationException("Not yet implemented: TriggerRegisterDialogEvent");
|
||||
final Trigger trigger = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
final CScriptDialog dialog = arguments.get(1).visit(ObjectJassValueVisitor.getInstance());
|
||||
if (dialog == null) {
|
||||
return new HandleJassValue(eventType, RemovableTriggerEvent.DO_NOTHING);
|
||||
}
|
||||
return new HandleJassValue(eventType, dialog.addEvent(trigger));
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("TriggerRegisterDialogButtonEvent",
|
||||
@ -2797,6 +2936,27 @@ public class Jass2 {
|
||||
simulation.createDestructable(new War3ID(rawcode), x, y, facing, scale, variation));
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("BlzCreateDestructableWithSkin", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
int rawcode = arguments.get(0).visit(IntegerJassValueVisitor.getInstance());
|
||||
final float x = arguments.get(1).visit(RealJassValueVisitor.getInstance()).floatValue();
|
||||
final float y = arguments.get(2).visit(RealJassValueVisitor.getInstance()).floatValue();
|
||||
final float facing = arguments.get(3).visit(RealJassValueVisitor.getInstance()).floatValue();
|
||||
final float scale = arguments.get(4).visit(RealJassValueVisitor.getInstance()).floatValue();
|
||||
final int variation = arguments.get(5).visit(IntegerJassValueVisitor.getInstance());
|
||||
final int skinId = arguments.get(6).visit(IntegerJassValueVisitor.getInstance());
|
||||
if (skinId != rawcode) {
|
||||
// throw new IllegalStateException(
|
||||
// "Our engine does not support DestructableSkinID != DestructableID (skinId="
|
||||
// + new War3ID(skinId) + ", destId=" + new War3ID(rawcode) + ")");
|
||||
rawcode = skinId;
|
||||
}
|
||||
return new HandleJassValue(destructableType,
|
||||
simulation.createDestructable(new War3ID(rawcode), x, y, facing, scale, variation));
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("CreateDestructableZ", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
@ -2853,6 +3013,35 @@ public class Jass2 {
|
||||
return new HandleJassValue(unitType, newUnit);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("BlzCreateUnitWithSkin", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CPlayer player = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
int rawcode = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
|
||||
final double x = arguments.get(2).visit(RealJassValueVisitor.getInstance());
|
||||
final double y = arguments.get(3).visit(RealJassValueVisitor.getInstance());
|
||||
final double facing = arguments.get(4).visit(RealJassValueVisitor.getInstance());
|
||||
final int skinId = arguments.get(5).visit(IntegerJassValueVisitor.getInstance());
|
||||
final CUnit newUnit = simulation.createUnit(new War3ID(rawcode), player.getId(), (float) x,
|
||||
(float) y, (float) facing);
|
||||
final CUnitType newUnitType = newUnit.getUnitType();
|
||||
final int foodUsed = newUnitType.getFoodUsed();
|
||||
newUnit.setFoodUsed(foodUsed);
|
||||
player.setFoodUsed(player.getFoodUsed() + foodUsed);
|
||||
if (newUnitType.getFoodMade() != 0) {
|
||||
player.setFoodCap(player.getFoodCap() + newUnitType.getFoodMade());
|
||||
}
|
||||
// nudge unit
|
||||
newUnit.setPointAndCheckUnstuck((float) x, (float) y, simulation);
|
||||
if (skinId != rawcode) {
|
||||
// throw new IllegalStateException("Our engine does not support UnitSkinID != UnitID (skinId="
|
||||
// + new War3ID(skinId) + ", unitId=" + new War3ID(rawcode) + ")");
|
||||
rawcode = skinId;
|
||||
}
|
||||
return new HandleJassValue(unitType, newUnit);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("CreateUnitAtLoc", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
@ -2926,6 +3115,9 @@ public class Jass2 {
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
final CUnitState whichUnitState = arguments.get(1).visit(ObjectJassValueVisitor.getInstance());
|
||||
if (whichUnit == null) {
|
||||
return RealJassValue.ZERO;
|
||||
}
|
||||
return new RealJassValue(whichUnit.getUnitState(simulation, whichUnitState));
|
||||
}
|
||||
});
|
||||
@ -3297,6 +3489,23 @@ public class Jass2 {
|
||||
return new RealJassValue(whichWidget.getY());
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetUnitPointValue", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CUnit whichWidget = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
return new IntegerJassValue(whichWidget.getUnitType().getPointValue());
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetUnitPointValueByType", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final int rawcode = arguments.get(0).visit(IntegerJassValueVisitor.getInstance());
|
||||
return new IntegerJassValue(
|
||||
simulation.getUnitData().getUnitType(new War3ID(rawcode)).getPointValue());
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetItemX", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
@ -3337,6 +3546,9 @@ public class Jass2 {
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CUnit whichWidget = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
final int rawcode = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
|
||||
if (whichWidget == null) {
|
||||
return IntegerJassValue.ZERO;
|
||||
}
|
||||
final CAbility ability = whichWidget
|
||||
.getAbility(GetAbilityByRawcodeVisitor.getInstance().reset(new War3ID(rawcode)));
|
||||
// TODO below code is very stupid!!
|
||||
@ -3383,6 +3595,14 @@ public class Jass2 {
|
||||
return new IntegerJassValue(whichHandle.getHandleId());
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("TriggerSleepAction", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final double time = arguments.get(0).visit(RealJassValueVisitor.getInstance());
|
||||
throw new IllegalStateException("Needs to sleep " + time);
|
||||
}
|
||||
});
|
||||
jassProgramVisitor.getJassNativeManager().createNative("GetPlayerNeutralAggressive", new JassFunction() {
|
||||
@Override
|
||||
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
|
||||
@ -3484,6 +3704,9 @@ public class Jass2 {
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
|
||||
final int whichSlot = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
|
||||
if (whichUnit == null) {
|
||||
return new HandleJassValue(itemType, null);
|
||||
}
|
||||
final CAbilityInventory inventoryData = whichUnit.getInventoryData();
|
||||
if (inventoryData != null) {
|
||||
return new HandleJassValue(itemType, inventoryData.getItemInSlot(whichSlot));
|
||||
@ -3796,11 +4019,17 @@ public class Jass2 {
|
||||
if (distSquared <= rSquared) {
|
||||
for (float pathX = -64; pathX < 64; pathX += 32f) {
|
||||
for (float pathY = -64; pathY < 64; pathY += 32f) {
|
||||
simulation.getPathingGrid().setBlighted(x + pathX + 16, y + pathY + 16,
|
||||
addBlight);
|
||||
final float blightX = x + pathX + 16;
|
||||
final float blightY = y + pathY + 16;
|
||||
if (simulation.getPathingGrid().contains(blightX, blightY)) {
|
||||
simulation.getPathingGrid().setBlighted(blightX, blightY, addBlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
war3MapViewer.terrain.getCorner(x, y).setBlight(true);
|
||||
final RenderCorner corner = war3MapViewer.terrain.getCorner(x, y);
|
||||
if (corner != null) {
|
||||
corner.setBlight(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4773,6 +5002,15 @@ public class Jass2 {
|
||||
return arg.visit(visitor);
|
||||
}
|
||||
|
||||
private static JassFunction nullable(final List<JassValue> arguments, final int index,
|
||||
final JassFunctionJassValueVisitor visitor) {
|
||||
final JassValue arg = arguments.get(index);
|
||||
if (arg == null) {
|
||||
return null;
|
||||
}
|
||||
return arg.visit(visitor);
|
||||
}
|
||||
|
||||
private static void doPreloadScript(final DataSource dataSource, final War3MapViewer war3MapViewer,
|
||||
final String filename) {
|
||||
final JassProgramVisitor jassProgramVisitor = new JassProgramVisitor();
|
||||
|
@ -9,6 +9,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerJass;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegion;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimerJass;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog.CScriptDialog;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog.CScriptDialogButton;
|
||||
|
||||
public class CommonTriggerExecutionScope extends TriggerExecutionScope {
|
||||
private CUnit triggeringUnit;
|
||||
@ -65,6 +67,8 @@ public class CommonTriggerExecutionScope extends TriggerExecutionScope {
|
||||
private CItem orderTargetItem;
|
||||
private CUnit orderTargetUnit;
|
||||
private CWidget triggerWidget;
|
||||
private CScriptDialog clickedDialog;
|
||||
private CScriptDialogButton clickedButton;
|
||||
|
||||
public CommonTriggerExecutionScope(final Trigger triggeringTrigger) {
|
||||
super(triggeringTrigger);
|
||||
@ -136,6 +140,8 @@ public class CommonTriggerExecutionScope extends TriggerExecutionScope {
|
||||
this.orderTargetItem = parentScope.orderTargetItem;
|
||||
this.orderTargetUnit = parentScope.orderTargetUnit;
|
||||
this.triggerWidget = parentScope.triggerWidget;
|
||||
this.clickedDialog = parentScope.clickedDialog;
|
||||
this.clickedButton = parentScope.clickedButton;
|
||||
}
|
||||
|
||||
public CUnit getEnumUnit() {
|
||||
@ -354,6 +360,14 @@ public class CommonTriggerExecutionScope extends TriggerExecutionScope {
|
||||
return this.orderTargetUnit;
|
||||
}
|
||||
|
||||
public CScriptDialogButton getClickedButton() {
|
||||
return this.clickedButton;
|
||||
}
|
||||
|
||||
public CScriptDialog getClickedDialog() {
|
||||
return this.clickedDialog;
|
||||
}
|
||||
|
||||
public static CommonTriggerExecutionScope filterScope(final TriggerExecutionScope parentScope,
|
||||
final CUnit filterUnit) {
|
||||
final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(parentScope.getTriggeringTrigger(),
|
||||
@ -426,6 +440,7 @@ public class CommonTriggerExecutionScope extends TriggerExecutionScope {
|
||||
final TriggerExecutionScope parentScope, final CUnit enteringUnit, final CRegion triggeringRegion) {
|
||||
final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(trigger, parentScope);
|
||||
scope.enteringUnit = enteringUnit;
|
||||
scope.triggeringUnit = enteringUnit;
|
||||
scope.triggeringRegion = triggeringRegion;
|
||||
return scope;
|
||||
}
|
||||
@ -434,18 +449,21 @@ public class CommonTriggerExecutionScope extends TriggerExecutionScope {
|
||||
final TriggerExecutionScope parentScope, final CUnit leavingUnit, final CRegion triggeringRegion) {
|
||||
final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(trigger, parentScope);
|
||||
scope.leavingUnit = leavingUnit;
|
||||
scope.triggeringUnit = leavingUnit;
|
||||
scope.triggeringRegion = triggeringRegion;
|
||||
return scope;
|
||||
}
|
||||
|
||||
public static CommonTriggerExecutionScope playerHeroLevelScope(final Trigger trigger, final CUnit hero) {
|
||||
final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(trigger, TriggerExecutionScope.EMPTY);
|
||||
scope.triggeringUnit = hero;
|
||||
scope.levelingUnit = hero;
|
||||
return scope;
|
||||
}
|
||||
|
||||
public static CommonTriggerExecutionScope playerHeroRevivableScope(final Trigger trigger, final CUnit hero) {
|
||||
final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(trigger, TriggerExecutionScope.EMPTY);
|
||||
scope.triggeringUnit = hero;
|
||||
scope.revivableUnit = hero;
|
||||
return scope;
|
||||
}
|
||||
@ -466,6 +484,14 @@ public class CommonTriggerExecutionScope extends TriggerExecutionScope {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public static CommonTriggerExecutionScope triggerDialogScope(final Trigger trigger,
|
||||
final CScriptDialog clickedDialog, final CScriptDialogButton clickedButton) {
|
||||
final CommonTriggerExecutionScope scope = new CommonTriggerExecutionScope(trigger, TriggerExecutionScope.EMPTY);
|
||||
scope.clickedDialog = clickedDialog;
|
||||
scope.clickedButton = clickedButton;
|
||||
return scope;
|
||||
}
|
||||
|
||||
public static interface UnitEventScopeBuilder {
|
||||
CommonTriggerExecutionScope create(Trigger trigger, CUnit unit);
|
||||
}
|
||||
|
@ -106,20 +106,20 @@ public class War3Map implements DataSource {
|
||||
return pathingMap;
|
||||
}
|
||||
|
||||
public War3MapDoo readDoodads() throws IOException {
|
||||
public War3MapDoo readDoodads(final War3MapW3i war3MapW3i) throws IOException {
|
||||
War3MapDoo doodadsFile;
|
||||
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream(
|
||||
this.dataSource.getResourceAsStream("war3map.doo"))) {
|
||||
doodadsFile = new War3MapDoo(stream);
|
||||
doodadsFile = new War3MapDoo(stream, war3MapW3i);
|
||||
}
|
||||
return doodadsFile;
|
||||
}
|
||||
|
||||
public War3MapUnitsDoo readUnits() throws IOException {
|
||||
public War3MapUnitsDoo readUnits(final War3MapW3i war3MapW3i) throws IOException {
|
||||
War3MapUnitsDoo unitsFile;
|
||||
try (LittleEndianDataInputStream stream = new LittleEndianDataInputStream(
|
||||
this.dataSource.getResourceAsStream("war3mapUnits.doo"))) {
|
||||
unitsFile = new War3MapUnitsDoo(stream);
|
||||
unitsFile = new War3MapUnitsDoo(stream, war3MapW3i);
|
||||
}
|
||||
return unitsFile;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
|
||||
import com.etheller.warsmash.util.ParseUtils;
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
import com.google.common.io.LittleEndianDataInputStream;
|
||||
@ -11,6 +12,7 @@ import com.google.common.io.LittleEndianDataOutputStream;
|
||||
|
||||
public class Doodad {
|
||||
private War3ID id;
|
||||
private War3ID skinId;
|
||||
private int variation;
|
||||
private final float[] location = new float[3];
|
||||
private float angle;
|
||||
@ -22,12 +24,21 @@ public class Doodad {
|
||||
private int editorId;
|
||||
private final short[] u1 = new short[8]; // short to store unsigned byte, java problem
|
||||
|
||||
public void load(final LittleEndianDataInputStream stream, final int version) throws IOException {
|
||||
public void load(final LittleEndianDataInputStream stream, final int version, final War3MapW3i mapInformation)
|
||||
throws IOException {
|
||||
this.id = ParseUtils.readWar3ID(stream);
|
||||
this.variation = stream.readInt();
|
||||
ParseUtils.readFloatArray(stream, this.location);
|
||||
this.angle = stream.readFloat();
|
||||
ParseUtils.readFloatArray(stream, this.scale);
|
||||
|
||||
if (((mapInformation.getGameVersionMajor() * 100) + mapInformation.getGameVersionMinor()) >= 132) {
|
||||
this.skinId = ParseUtils.readWar3ID(stream);
|
||||
}
|
||||
else {
|
||||
this.skinId = this.id;
|
||||
}
|
||||
|
||||
this.flags = ParseUtils.readUInt8(stream);
|
||||
this.life = ParseUtils.readUInt8(stream);
|
||||
|
||||
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
|
||||
import com.etheller.warsmash.util.ParseUtils;
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
import com.google.common.io.LittleEndianDataInputStream;
|
||||
@ -20,13 +21,13 @@ public class War3MapDoo {
|
||||
private final short[] u2 = new short[4];
|
||||
private final List<TerrainDoodad> terrainDoodads = new ArrayList<>();
|
||||
|
||||
public War3MapDoo(final LittleEndianDataInputStream stream) throws IOException {
|
||||
public War3MapDoo(final LittleEndianDataInputStream stream, final War3MapW3i mapInformation) throws IOException {
|
||||
if (stream != null) {
|
||||
this.load(stream);
|
||||
this.load(stream, mapInformation);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean load(final LittleEndianDataInputStream stream) throws IOException {
|
||||
private boolean load(final LittleEndianDataInputStream stream, final War3MapW3i mapInformation) throws IOException {
|
||||
final War3ID firstId = ParseUtils.readWar3ID(stream);
|
||||
if (!MAGIC_NUMBER.equals(firstId)) {
|
||||
return false;
|
||||
@ -38,7 +39,7 @@ public class War3MapDoo {
|
||||
for (int i = 0, l = stream.readInt(); i < l; i++) {
|
||||
final Doodad doodad = new Doodad();
|
||||
|
||||
doodad.load(stream, this.version);
|
||||
doodad.load(stream, this.version, mapInformation);
|
||||
|
||||
this.doodads.add(doodad);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
|
||||
import com.etheller.warsmash.util.ParseUtils;
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
import com.google.common.io.LittleEndianDataInputStream;
|
||||
@ -11,6 +12,7 @@ import com.google.common.io.LittleEndianDataOutputStream;
|
||||
|
||||
public class Unit {
|
||||
private War3ID id;
|
||||
private War3ID skinId;
|
||||
private int variation;
|
||||
private final float[] location = new float[3];
|
||||
private float angle;
|
||||
@ -52,12 +54,21 @@ public class Unit {
|
||||
private int waygate;
|
||||
private int creationNumber;
|
||||
|
||||
public void load(final LittleEndianDataInputStream stream, final int version) throws IOException {
|
||||
public void load(final LittleEndianDataInputStream stream, final int version, final War3MapW3i mapInformation)
|
||||
throws IOException {
|
||||
this.id = ParseUtils.readWar3ID(stream);
|
||||
this.variation = stream.readInt();
|
||||
ParseUtils.readFloatArray(stream, this.location);
|
||||
this.angle = stream.readFloat();
|
||||
ParseUtils.readFloatArray(stream, this.scale);
|
||||
|
||||
if (((mapInformation.getGameVersionMajor() * 100) + mapInformation.getGameVersionMinor()) >= 132) {
|
||||
this.skinId = ParseUtils.readWar3ID(stream);
|
||||
}
|
||||
else {
|
||||
this.skinId = this.id;
|
||||
}
|
||||
|
||||
this.flags = ParseUtils.readUInt8(stream);
|
||||
this.player = stream.readInt();
|
||||
this.unknown = ParseUtils.readUInt16(stream);
|
||||
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
|
||||
import com.etheller.warsmash.util.ParseUtils;
|
||||
import com.etheller.warsmash.util.War3ID;
|
||||
import com.google.common.io.LittleEndianDataInputStream;
|
||||
@ -15,13 +16,14 @@ public class War3MapUnitsDoo {
|
||||
private long unknown = 11;
|
||||
private final List<Unit> units = new ArrayList<>();
|
||||
|
||||
public War3MapUnitsDoo(final LittleEndianDataInputStream stream) throws IOException {
|
||||
public War3MapUnitsDoo(final LittleEndianDataInputStream stream, final War3MapW3i mapInformation)
|
||||
throws IOException {
|
||||
if (stream != null) {
|
||||
this.load(stream);
|
||||
this.load(stream, mapInformation);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean load(final LittleEndianDataInputStream stream) throws IOException {
|
||||
private boolean load(final LittleEndianDataInputStream stream, final War3MapW3i mapInformation) throws IOException {
|
||||
final War3ID firstId = ParseUtils.readWar3ID(stream);
|
||||
if (!MAGIC_NUMBER.equals(firstId)) {
|
||||
return false;
|
||||
@ -33,7 +35,7 @@ public class War3MapUnitsDoo {
|
||||
for (int i = 0, l = stream.readInt(); i < l; i++) {
|
||||
final Unit unit = new Unit();
|
||||
|
||||
unit.load(stream, this.version);
|
||||
unit.load(stream, this.version, mapInformation);
|
||||
|
||||
this.units.add(unit);
|
||||
}
|
||||
|
@ -15,7 +15,10 @@ public class War3MapW3i {
|
||||
private int version;
|
||||
private int saves;
|
||||
private int editorVersion;
|
||||
private final short[] unknown1 = new short[16];
|
||||
private int gameVersionMajor;
|
||||
private int gameVersionMinor;
|
||||
private int gameVersionPatch;
|
||||
private int gameVersionBuild;
|
||||
private String name;
|
||||
private String author;
|
||||
private String description;
|
||||
@ -63,7 +66,10 @@ public class War3MapW3i {
|
||||
this.editorVersion = stream.readInt();
|
||||
|
||||
if (this.version > 27) {
|
||||
ParseUtils.readUInt8Array(stream, this.unknown1);
|
||||
this.gameVersionMajor = stream.readInt();
|
||||
this.gameVersionMinor = stream.readInt();
|
||||
this.gameVersionPatch = stream.readInt();
|
||||
this.gameVersionBuild = stream.readInt();
|
||||
}
|
||||
|
||||
this.name = ParseUtils.readUntilNull(stream);
|
||||
@ -182,7 +188,10 @@ public class War3MapW3i {
|
||||
stream.writeInt(this.editorVersion);
|
||||
|
||||
if (this.version > 27) {
|
||||
ParseUtils.writeUInt8Array(stream, this.unknown1);
|
||||
stream.writeInt(this.gameVersionMajor);
|
||||
stream.writeInt(this.gameVersionMinor);
|
||||
stream.writeInt(this.gameVersionPatch);
|
||||
stream.writeInt(this.gameVersionBuild);
|
||||
}
|
||||
|
||||
ParseUtils.writeWithNullTerminator(stream, this.name);
|
||||
@ -314,10 +323,6 @@ public class War3MapW3i {
|
||||
return this.editorVersion;
|
||||
}
|
||||
|
||||
public short[] getUnknown1() {
|
||||
return this.unknown1;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
@ -453,4 +458,12 @@ public class War3MapW3i {
|
||||
public List<RandomItemTable> getRandomItemTables() {
|
||||
return this.randomItemTables;
|
||||
}
|
||||
|
||||
public int getGameVersionMajor() {
|
||||
return this.gameVersionMajor;
|
||||
}
|
||||
|
||||
public int getGameVersionMinor() {
|
||||
return this.gameVersionMinor;
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,10 @@ public class StandardObjectData {
|
||||
profile.readTXT(this.source.getResourceAsStream("Units\\ItemFunc.txt"), true);
|
||||
profile.readTXT(this.source.getResourceAsStream("Units\\ItemStrings.txt"), true);
|
||||
itemData.readSLK(this.source.getResourceAsStream("Units\\ItemData.slk"));
|
||||
// final InputStream itemSkin = this.source.getResourceAsStream("Units\\ItemSkin.txt");
|
||||
// if (itemSkin != null) {
|
||||
// profile.readTXT(itemSkin, true);
|
||||
// }
|
||||
}
|
||||
catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -195,7 +195,7 @@ public final class War3ObjectDataChangeset {
|
||||
this.kind = chid.asStringValue().charAt(0);
|
||||
break;
|
||||
default:
|
||||
this.kind = 'a';
|
||||
this.kind = this.expected;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.etheller.warsmash.util;
|
||||
|
||||
public class WarsmashConstants {
|
||||
public static final int MAX_PLAYERS = 16;
|
||||
public static final int MAX_PLAYERS = 28;
|
||||
/*
|
||||
* With version, we use 0 for RoC, 1 for TFT emulation, and probably 2+ or
|
||||
* whatever for custom mods and other stuff
|
||||
@ -39,4 +39,5 @@ public class WarsmashConstants {
|
||||
public static final boolean ENABLE_MUSIC = true;
|
||||
public static final boolean LOAD_UNITS_FROM_WORLDEDIT_DATA = false;
|
||||
public static final boolean LOCAL_TEMP_TEST_ALL_PLAYERS_PLAYING = true;
|
||||
public static final boolean CRASH_ON_INCOMPATIBLE_132_FEATURES = false;
|
||||
}
|
||||
|
@ -55,6 +55,9 @@ public class EventObjectEmitterObject extends GenericObject implements EmitterOb
|
||||
|
||||
@Override
|
||||
public Object call(final InputStream data) {
|
||||
if (data == null) {
|
||||
return new MappedData();
|
||||
}
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(data, "utf-8"))) {
|
||||
String line;
|
||||
|
@ -705,10 +705,11 @@ public class MdxComplexInstance extends ModelInstance {
|
||||
public MdxComplexInstance setSequence(final int id) {
|
||||
final MdxModel model = (MdxModel) this.model;
|
||||
|
||||
final int lastSequence = this.sequence;
|
||||
this.sequence = id;
|
||||
|
||||
if (model.ok) {
|
||||
|
||||
final int lastSequence = this.sequence;
|
||||
this.sequence = id;
|
||||
|
||||
final List<Sequence> sequences = model.sequences;
|
||||
|
||||
if ((id < 0) || (id > (sequences.size() - 1))) {
|
||||
@ -789,6 +790,10 @@ public class MdxComplexInstance extends ModelInstance {
|
||||
return this.model.bounds;
|
||||
}
|
||||
else {
|
||||
if (((MdxModel) this.model).sequences.isEmpty()) {
|
||||
System.err.println("Printing diagnostics for corrupted state MdxComplexInstance (about to crash)");
|
||||
System.err.println("Model name: " + ((MdxModel) this.model).name);
|
||||
}
|
||||
final Bounds sequenceBounds = ((MdxModel) this.model).sequences.get(this.sequence).getBounds();
|
||||
if (sequenceBounds.r == 0) {
|
||||
return this.model.bounds;
|
||||
|
@ -244,6 +244,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
|
||||
private GameTurnManager gameTurnManager;
|
||||
|
||||
private War3MapW3i lastLoadedMapInformation;
|
||||
|
||||
public War3MapViewer(final DataSource dataSource, final CanvasProvider canvas, final War3MapConfig mapConfig,
|
||||
final GameTurnManager gameTurnManager) {
|
||||
super(dataSource, canvas);
|
||||
@ -451,6 +453,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
this.localPlayerIndex = localPlayerIndex;
|
||||
|
||||
this.mapMpq = war3Map;
|
||||
this.lastLoadedMapInformation = w3iFile;
|
||||
|
||||
final PathSolver wc3PathSolver = this.wc3PathSolver;
|
||||
|
||||
@ -910,7 +913,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
|
||||
this.walkableObjectsTree = new Quadtree<>(this.terrain.getEntireMap());
|
||||
if (this.doodadsAndDestructiblesLoaded) {
|
||||
this.loadDoodadsAndDestructibles(this.allObjectData);
|
||||
this.loadDoodadsAndDestructibles(this.allObjectData, w3iFile);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("transcription of JS has not loaded a map and has no JS async promises");
|
||||
@ -974,7 +977,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
*/
|
||||
public void loadAfterUI() throws IOException {
|
||||
if (this.unitsAndItemsLoaded) {
|
||||
this.loadUnitsAndItems(this.allObjectData);
|
||||
this.loadUnitsAndItems(this.allObjectData, this.lastLoadedMapInformation);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("transcription of JS has not loaded a map and has no JS async promises");
|
||||
@ -985,13 +988,14 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
this.terrain.initShadows();
|
||||
}
|
||||
|
||||
private void loadDoodadsAndDestructibles(final Warcraft3MapObjectData modifications) throws IOException {
|
||||
private void loadDoodadsAndDestructibles(final Warcraft3MapObjectData modifications, final War3MapW3i w3iFile)
|
||||
throws IOException {
|
||||
this.applyModificationFile(this.doodadsData, this.doodadMetaData, modifications.getDoodads(),
|
||||
WorldEditorDataType.DOODADS);
|
||||
this.applyModificationFile(this.doodadsData, this.destructableMetaData, modifications.getDestructibles(),
|
||||
WorldEditorDataType.DESTRUCTIBLES);
|
||||
|
||||
final War3MapDoo doo = this.mapMpq.readDoodads();
|
||||
final War3MapDoo doo = this.mapMpq.readDoodads(w3iFile);
|
||||
|
||||
for (final com.etheller.warsmash.parsers.w3x.doo.Doodad doodad : doo.getDoodads()) {
|
||||
if ((doodad.getFlags() & 0x2) == 0) {
|
||||
@ -1229,14 +1233,15 @@ public class War3MapViewer extends AbstractMdxModelViewer {
|
||||
|
||||
}
|
||||
|
||||
private void loadUnitsAndItems(final Warcraft3MapObjectData modifications) throws IOException {
|
||||
private void loadUnitsAndItems(final Warcraft3MapObjectData modifications, final War3MapW3i mapInformation)
|
||||
throws IOException {
|
||||
final War3Map mpq = this.mapMpq;
|
||||
this.unitsReady = false;
|
||||
|
||||
this.soundsetNameToSoundset = new HashMap<>();
|
||||
|
||||
if (this.dataSource.has("war3mapUnits.doo") && WarsmashConstants.LOAD_UNITS_FROM_WORLDEDIT_DATA) {
|
||||
final War3MapUnitsDoo dooFile = mpq.readUnits();
|
||||
final War3MapUnitsDoo dooFile = mpq.readUnits(mapInformation);
|
||||
|
||||
// Collect the units and items data.
|
||||
for (final com.etheller.warsmash.parsers.w3x.unitsdoo.Unit unit : dooFile.getUnits()) {
|
||||
|
@ -281,6 +281,9 @@ public class PathingGrid {
|
||||
public boolean isPathable(final float unitX, final float unitY, final MovementType pathingType,
|
||||
final float collisionSize) {
|
||||
if (collisionSize == 0f) {
|
||||
if (!contains(unitX, unitY)) {
|
||||
return false;
|
||||
}
|
||||
return pathingType.isPathable(getPathing(unitX, unitY));
|
||||
}
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
|
@ -108,7 +108,7 @@ public class CUnit extends CWidget {
|
||||
// which fields shouldn't be persisted if we do game state save later
|
||||
private transient CUnitStateNotifier stateNotifier = new CUnitStateNotifier();
|
||||
private transient List<StateListenerUpdate> stateListenersUpdates = new ArrayList<>();
|
||||
private final float acquisitionRange;
|
||||
private float acquisitionRange;
|
||||
private transient static AutoAttackTargetFinderEnum autoAttackTargetFinderEnum = new AutoAttackTargetFinderEnum();
|
||||
|
||||
private transient CBehaviorMove moveBehavior;
|
||||
@ -1221,13 +1221,20 @@ public class CUnit extends CWidget {
|
||||
}
|
||||
|
||||
public boolean isMovementDisabled() {
|
||||
return this.isBuilding();
|
||||
return this.moveBehavior == null;
|
||||
// TODO this used to directly return the state of whether our unit was a
|
||||
// building. Will it be a problem that I changed it?
|
||||
// I was trying to fix attack move on stationary units which was crashing
|
||||
}
|
||||
|
||||
public float getAcquisitionRange() {
|
||||
return this.acquisitionRange;
|
||||
}
|
||||
|
||||
public void setAcquisitionRange(final float acquisitionRange) {
|
||||
this.acquisitionRange = acquisitionRange;
|
||||
}
|
||||
|
||||
public void heal(final CSimulation game, final int lifeToRegain) {
|
||||
setLife(game, Math.min(getLife() + lifeToRegain, getMaximumLife()));
|
||||
}
|
||||
@ -1971,4 +1978,5 @@ public class CUnit extends CWidget {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ public class CUnitType {
|
||||
private final boolean canFlee;
|
||||
private final int priority;
|
||||
private final boolean revivesHeroes;
|
||||
private final int pointValue;
|
||||
|
||||
public CUnitType(final String name, final String legacyName, final War3ID typeId, final int maxLife,
|
||||
final float lifeRegen, final CRegenType lifeRegenType, final int manaInitial, final int manaMaximum,
|
||||
@ -97,7 +98,7 @@ public class CUnitType {
|
||||
final float strengthPerLevel, final int agility, final float agilityPerLevel, final int intelligence,
|
||||
final float intelligencePerLevel, final CPrimaryAttribute primaryAttribute,
|
||||
final List<War3ID> heroAbilityList, final List<String> heroProperNames, final int properNamesCount,
|
||||
final boolean canFlee, final int priority, final boolean revivesHeroes) {
|
||||
final boolean canFlee, final int priority, final boolean revivesHeroes, final int pointValue) {
|
||||
this.name = name;
|
||||
this.legacyName = legacyName;
|
||||
this.typeId = typeId;
|
||||
@ -155,6 +156,7 @@ public class CUnitType {
|
||||
this.canFlee = canFlee;
|
||||
this.priority = priority;
|
||||
this.revivesHeroes = revivesHeroes;
|
||||
this.pointValue = pointValue;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@ -384,4 +386,8 @@ public class CUnitType {
|
||||
public boolean isRevivesHeroes() {
|
||||
return this.revivesHeroes;
|
||||
}
|
||||
|
||||
public int getPointValue() {
|
||||
return this.pointValue;
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ public class CAbilityHero extends AbstractCAbility {
|
||||
this.intelligence = new HeroStatValue(unitType.getStartingIntelligence(), unitType.getIntelligencePerLevel());
|
||||
calculateDerivatedFields(game, unit);
|
||||
|
||||
final int nameIndex = game.getSeededRandom().nextInt(unitType.getProperNamesCount());
|
||||
final int properNamesCount = unitType.getProperNamesCount();
|
||||
final int nameIndex = properNamesCount > 0 ? game.getSeededRandom().nextInt(properNamesCount) : 0;
|
||||
|
||||
String properName;
|
||||
final List<String> heroProperNames = unitType.getHeroProperNames();
|
||||
|
@ -177,6 +177,8 @@ public class CUnitData {
|
||||
private static final War3ID CAN_FLEE = War3ID.fromString("ufle");
|
||||
private static final War3ID PRIORITY = War3ID.fromString("upri");
|
||||
|
||||
private static final War3ID POINT_VALUE = War3ID.fromString("upoi");
|
||||
|
||||
private final CGameplayConstants gameplayConstants;
|
||||
private final MutableObjectData unitData;
|
||||
private final Map<War3ID, CUnitType> unitIdToUnitType = new HashMap<>();
|
||||
@ -324,7 +326,9 @@ public class CUnitData {
|
||||
}
|
||||
final String unitName = unitType.getFieldAsString(NAME, 0);
|
||||
final float acquisitionRange = unitType.getFieldAsFloat(ACQUISITION_RANGE, 0);
|
||||
final float minimumAttackRange = unitType.getFieldAsFloat(MINIMUM_ATTACK_RANGE, 0);
|
||||
// note: uamn expected type int below, not exactly sure why that decision was
|
||||
// made but I'll support it
|
||||
final float minimumAttackRange = unitType.getFieldAsInteger(MINIMUM_ATTACK_RANGE, 0);
|
||||
final EnumSet<CTargetType> targetedAs = CTargetType
|
||||
.parseTargetTypeSet(unitType.getFieldAsString(TARGETED_AS, 0));
|
||||
final String classificationString = unitType.getFieldAsString(CLASSIFICATION, 0);
|
||||
@ -468,6 +472,8 @@ public class CUnitData {
|
||||
final int foodUsed = unitType.getFieldAsInteger(FOOD_USED, 0);
|
||||
final int foodMade = unitType.getFieldAsInteger(FOOD_MADE, 0);
|
||||
|
||||
final int pointValue = unitType.getFieldAsInteger(POINT_VALUE, 0);
|
||||
|
||||
final boolean revivesHeroes = unitType.getFieldAsBoolean(REVIVES_HEROES, 0);
|
||||
|
||||
final String unitsTrainedString = unitType.getFieldAsString(UNITS_TRAINED, 0);
|
||||
@ -567,7 +573,7 @@ public class CUnitData {
|
||||
researchesAvailable, upgradesTo, unitRace, goldCost, lumberCost, foodUsed, foodMade, buildTime,
|
||||
preventedPathingTypes, requiredPathingTypes, propWindow, turnRate, requirements, unitLevel, hero,
|
||||
strength, strPlus, agility, agiPlus, intelligence, intPlus, primaryAttribute, heroAbilityList,
|
||||
heroProperNames, properNamesCount, canFlee, priority, revivesHeroes);
|
||||
heroProperNames, properNamesCount, canFlee, priority, revivesHeroes, pointValue);
|
||||
this.unitIdToUnitType.put(typeId, unitTypeInstance);
|
||||
this.jassLegacyNameToUnitId.put(legacyName, typeId);
|
||||
}
|
||||
|
@ -29,7 +29,11 @@ public class OrderIdUtils {
|
||||
}
|
||||
|
||||
public static int getOrderId(final String orderIdString) {
|
||||
return stringToOrderId.get(orderIdString);
|
||||
final Integer orderId = stringToOrderId.get(orderIdString.toLowerCase());
|
||||
if (orderId == null) {
|
||||
return 0;
|
||||
}
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public static String getStringFromOrderId(final Integer orderId) {
|
||||
|
@ -35,7 +35,6 @@ public class CPathfindingProcessor {
|
||||
this.worldCollision = worldCollision;
|
||||
this.nodes = new Node[pathingGrid.getHeight()][pathingGrid.getWidth()];
|
||||
this.cornerNodes = new Node[pathingGrid.getHeight() + 1][pathingGrid.getWidth() + 1];
|
||||
System.out.println("pathing size: ");
|
||||
for (int i = 0; i < this.nodes.length; i++) {
|
||||
for (int j = 0; j < this.nodes[i].length; j++) {
|
||||
this.nodes[i][j] = new Node(new Point2D.Float(pathingGrid.getWorldX(j), pathingGrid.getWorldY(i)));
|
||||
|
@ -8,15 +8,18 @@ import com.etheller.interpreter.ast.debug.JassException;
|
||||
import com.etheller.interpreter.ast.function.JassFunction;
|
||||
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||
import com.etheller.interpreter.ast.scope.trigger.Trigger;
|
||||
import com.etheller.interpreter.ast.util.CHandle;
|
||||
import com.etheller.warsmash.parsers.jass.scope.CommonTriggerExecutionScope;
|
||||
|
||||
public class CTimerJass extends CTimer {
|
||||
public class CTimerJass extends CTimer implements CHandle {
|
||||
private JassFunction handlerFunc;
|
||||
private final GlobalScope jassGlobalScope;
|
||||
private final int handleId;
|
||||
private final List<Trigger> eventTriggers = new ArrayList<>();
|
||||
|
||||
public CTimerJass(final GlobalScope jassGlobalScope) {
|
||||
public CTimerJass(final GlobalScope jassGlobalScope, final int handleId) {
|
||||
this.jassGlobalScope = jassGlobalScope;
|
||||
this.handleId = handleId;
|
||||
}
|
||||
|
||||
public void setHandlerFunc(final JassFunction handlerFunc) {
|
||||
@ -27,7 +30,9 @@ public class CTimerJass extends CTimer {
|
||||
public void onFire() {
|
||||
final CommonTriggerExecutionScope handlerScope = CommonTriggerExecutionScope.expiringTimer(null, this);
|
||||
try {
|
||||
this.handlerFunc.call(Collections.emptyList(), this.jassGlobalScope, handlerScope);
|
||||
if (this.handlerFunc != null) {
|
||||
this.handlerFunc.call(Collections.emptyList(), this.jassGlobalScope, handlerScope);
|
||||
}
|
||||
}
|
||||
catch (final Exception e) {
|
||||
throw new JassException(this.jassGlobalScope, "Exception during jass time fire", e);
|
||||
@ -47,4 +52,9 @@ public class CTimerJass extends CTimer {
|
||||
public void removeEvent(final Trigger trigger) {
|
||||
this.eventTriggers.remove(trigger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHandleId() {
|
||||
return this.handleId;
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.math.collision.BoundingBox;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
import com.badlogic.gdx.utils.viewport.ExtendViewport;
|
||||
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||
import com.etheller.warsmash.datasources.DataSource;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.AnchorDefinition;
|
||||
@ -168,6 +169,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandCardCommandL
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandErrorListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.MultiSelectionIconListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.QueueIconListener;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog.CScriptDialog;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog.CScriptDialogButton;
|
||||
import com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog.CTimerDialog;
|
||||
import com.hiveworkshop.rms.parsers.mdlx.MdlxLayer.FilterMode;
|
||||
|
||||
@ -3834,4 +3837,43 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
|
||||
public void displayTimedText(final float x, final float y, final float duration, final String message) {
|
||||
showGameMessage(message, duration); // TODO x y
|
||||
}
|
||||
|
||||
public CScriptDialog createScriptDialog(final GlobalScope globalScope) {
|
||||
final SimpleFrame scriptDialog = (SimpleFrame) this.rootFrame.createFrame("ScriptDialog", this.rootFrame, 0, 0);
|
||||
scriptDialog.addAnchor(new AnchorDefinition(FramePoint.TOP, 0, GameUI.convertY(this.uiViewport, -0.05f)));
|
||||
scriptDialog.setVisible(false);
|
||||
final StringFrame scriptDialogTextFrame = (StringFrame) this.rootFrame.getFrameByName("ScriptDialogText", 0);
|
||||
scriptDialog.positionBounds(this.rootFrame, this.uiViewport);
|
||||
return new CScriptDialog(globalScope, scriptDialog, scriptDialogTextFrame);
|
||||
}
|
||||
|
||||
public CScriptDialogButton createScriptDialogButton(final CScriptDialog scriptDialog, final String text,
|
||||
final char hotkey) {
|
||||
// TODO use hotkey
|
||||
final GlueTextButtonFrame scriptDialogButton = (GlueTextButtonFrame) this.rootFrame
|
||||
.createFrame("ScriptDialogButton", scriptDialog.getScriptDialogFrame(), 0, 0);
|
||||
scriptDialogButton.setHeight(GameUI.convertY(this.uiViewport, 0.03f));
|
||||
final StringFrame scriptDialogTextFrame = (StringFrame) this.rootFrame.getFrameByName("ScriptDialogButtonText",
|
||||
0);
|
||||
this.rootFrame.setText(scriptDialogTextFrame, text);
|
||||
scriptDialogButton.addSetPoint(new SetPoint(FramePoint.TOP, scriptDialog.getLastAddedComponent(),
|
||||
FramePoint.BOTTOM, 0, GameUI.convertY(this.uiViewport, -0.005f)));
|
||||
final CScriptDialogButton newButton = new CScriptDialogButton(scriptDialogButton, scriptDialogTextFrame);
|
||||
scriptDialog.addButton(this.rootFrame, this.uiViewport, newButton);
|
||||
return newButton;
|
||||
}
|
||||
|
||||
public void destroyDialog(final CScriptDialog dialog) {
|
||||
this.rootFrame.remove(dialog.getScriptDialogFrame());
|
||||
}
|
||||
|
||||
public void clearDialog(final CScriptDialog dialog) {
|
||||
destroyDialog(dialog);
|
||||
final SimpleFrame scriptDialog = (SimpleFrame) this.rootFrame.createFrame("ScriptDialog", this.rootFrame, 0, 0);
|
||||
scriptDialog.addAnchor(new AnchorDefinition(FramePoint.TOP, 0, GameUI.convertY(this.uiViewport, -0.05f)));
|
||||
scriptDialog.setVisible(false);
|
||||
final StringFrame scriptDialogTextFrame = (StringFrame) this.rootFrame.getFrameByName("ScriptDialogText", 0);
|
||||
scriptDialog.positionBounds(this.rootFrame, this.uiViewport);
|
||||
dialog.reset(scriptDialog, scriptDialogTextFrame);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,92 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||
import com.etheller.interpreter.ast.scope.trigger.RemovableTriggerEvent;
|
||||
import com.etheller.interpreter.ast.scope.trigger.Trigger;
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.GlueTextButtonFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
|
||||
import com.etheller.warsmash.parsers.jass.scope.CommonTriggerExecutionScope;
|
||||
|
||||
public class CScriptDialog {
|
||||
private final GlobalScope globalScope;
|
||||
private SimpleFrame scriptDialogFrame;
|
||||
private StringFrame scriptDialogTextFrame;
|
||||
private UIFrame lastAddedComponent;
|
||||
private final List<Trigger> eventTriggers = new ArrayList<>();
|
||||
|
||||
public CScriptDialog(final GlobalScope globalScope, final SimpleFrame scriptDialogFrame,
|
||||
final StringFrame scriptDialogTextFrame) {
|
||||
this.globalScope = globalScope;
|
||||
this.scriptDialogFrame = scriptDialogFrame;
|
||||
this.scriptDialogTextFrame = scriptDialogTextFrame;
|
||||
this.lastAddedComponent = scriptDialogTextFrame;
|
||||
}
|
||||
|
||||
public SimpleFrame getScriptDialogFrame() {
|
||||
return this.scriptDialogFrame;
|
||||
}
|
||||
|
||||
public StringFrame getScriptDialogTextFrame() {
|
||||
return this.scriptDialogTextFrame;
|
||||
}
|
||||
|
||||
public UIFrame getLastAddedComponent() {
|
||||
return this.lastAddedComponent;
|
||||
}
|
||||
|
||||
public void setTitle(final GameUI rootFrame, final String text) {
|
||||
rootFrame.setText(this.scriptDialogTextFrame, text);
|
||||
}
|
||||
|
||||
public void reset(final SimpleFrame scriptDialogFrame, final StringFrame scriptDialogTextFrame) {
|
||||
this.scriptDialogFrame = scriptDialogFrame;
|
||||
this.scriptDialogTextFrame = scriptDialogTextFrame;
|
||||
this.lastAddedComponent = scriptDialogTextFrame;
|
||||
}
|
||||
|
||||
public void setVisible(final boolean flag) {
|
||||
this.scriptDialogFrame.setVisible(flag);
|
||||
}
|
||||
|
||||
public RemovableTriggerEvent addEvent(final Trigger trigger) {
|
||||
this.eventTriggers.add(trigger);
|
||||
return new RemovableTriggerEvent() {
|
||||
@Override
|
||||
public void remove() {
|
||||
CScriptDialog.this.eventTriggers.remove(trigger);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void onButtonClick(final CScriptDialogButton cScriptDialogButton) {
|
||||
this.scriptDialogFrame.setVisible(false);
|
||||
for (final Trigger trigger : this.eventTriggers) {
|
||||
final CommonTriggerExecutionScope scope = CommonTriggerExecutionScope.triggerDialogScope(trigger, this,
|
||||
cScriptDialogButton);
|
||||
if (trigger.evaluate(this.globalScope, scope)) {
|
||||
trigger.execute(this.globalScope, scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addButton(final GameUI rootFrame, final Viewport uiViewport,
|
||||
final CScriptDialogButton scriptDialogButton) {
|
||||
final GlueTextButtonFrame buttonFrame = scriptDialogButton.getButtonFrame();
|
||||
this.scriptDialogFrame.add(buttonFrame);
|
||||
this.lastAddedComponent = buttonFrame;
|
||||
buttonFrame.positionBounds(rootFrame, uiViewport);
|
||||
this.scriptDialogFrame
|
||||
.setHeight(((this.scriptDialogFrame.getAssignedHeight() + (buttonFrame.getFramePointY(FramePoint.TOP)))
|
||||
- buttonFrame.getFramePointY(FramePoint.BOTTOM)) * 1.5f);
|
||||
this.scriptDialogFrame.positionBounds(rootFrame, uiViewport);
|
||||
scriptDialogButton.setupEvents(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.etheller.warsmash.viewer5.handlers.w3x.ui.dialog;
|
||||
|
||||
import com.etheller.warsmash.parsers.fdf.GameUI;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.GlueTextButtonFrame;
|
||||
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
|
||||
|
||||
public class CScriptDialogButton {
|
||||
private final GlueTextButtonFrame buttonFrame;
|
||||
private final StringFrame buttonText;
|
||||
|
||||
public CScriptDialogButton(final GlueTextButtonFrame buttonFrame, final StringFrame buttonText) {
|
||||
this.buttonFrame = buttonFrame;
|
||||
this.buttonText = buttonText;
|
||||
}
|
||||
|
||||
public GlueTextButtonFrame getButtonFrame() {
|
||||
return this.buttonFrame;
|
||||
}
|
||||
|
||||
public void setText(final GameUI rootFrame, final String text) {
|
||||
rootFrame.setText(this.buttonText, text);
|
||||
}
|
||||
|
||||
public void setupEvents(final CScriptDialog dialog) {
|
||||
this.buttonFrame.setOnClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialog.onButtonClick(CScriptDialogButton.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -523,6 +523,21 @@ public enum ArithmeticSigns implements ArithmeticSign {
|
||||
}
|
||||
|
||||
private static boolean isEqual(final CodeJassValue left, final CodeJassValue right) {
|
||||
return (left.getValue() == right.getValue());
|
||||
if (left == null) {
|
||||
if (right == null) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (right == null) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return (left.getValue() == right.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ public class NativeJassFunction extends AbstractJassFunction {
|
||||
if (this.implementation == null) {
|
||||
System.err.println(
|
||||
"Call to native function that was declared but had no native implementation: " + this.name);
|
||||
return null;
|
||||
return this.returnType.getNullValue();
|
||||
// throw new UnsupportedOperationException(
|
||||
// "Call to native function that was declared but had no native implementation: " + this.name);
|
||||
}
|
||||
|
@ -32,11 +32,15 @@ public final class UserJassFunction extends AbstractJassFunction {
|
||||
for (final JassStatement statement : this.statements) {
|
||||
final JassValue returnValue = statement.execute(globalScope, localScope, triggerScope);
|
||||
if (returnValue != null) {
|
||||
if (returnValue.visit(JassTypeGettingValueVisitor.getInstance()) != this.returnType) {
|
||||
if (!this.returnType.isAssignableFrom(returnValue.visit(JassTypeGettingValueVisitor.getInstance()))) {
|
||||
if ((this.returnType == JassType.NOTHING)
|
||||
&& (returnValue == JassReturnNothingStatement.RETURN_NOTHING_NOTICE)) {
|
||||
return null;
|
||||
}
|
||||
else if ((this.returnType.isNullable())
|
||||
&& (returnValue == JassReturnNothingStatement.RETURN_NOTHING_NOTICE)) {
|
||||
return this.returnType.getNullValue();
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Invalid return type");
|
||||
}
|
||||
|
@ -202,6 +202,10 @@ public final class GlobalScope {
|
||||
final CLimitOp limitOp, final double doubleValue) {
|
||||
final VariableEvent variableEvent = new VariableEvent(trigger, limitOp, doubleValue);
|
||||
final GlobalScopeAssignable assignableGlobal = getAssignableGlobal(varName);
|
||||
if (assignableGlobal == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"registerVariableEvent failed to find var with name: \"" + varName + "\"");
|
||||
}
|
||||
assignableGlobal.add(variableEvent);
|
||||
return new RemovableTriggerEvent() {
|
||||
@Override
|
||||
|
@ -10,14 +10,14 @@ import com.etheller.interpreter.ast.value.JassValue;
|
||||
public final class LocalScope {
|
||||
private final Map<String, Assignable> locals = new HashMap<>();
|
||||
|
||||
public void createLocal(final String name, final JassType type) {
|
||||
this.locals.put(name, new Assignable(type));
|
||||
public Assignable createLocal(final String name, final JassType type) {
|
||||
final Assignable assignable = new Assignable(type);
|
||||
this.locals.put(name, assignable);
|
||||
return assignable;
|
||||
}
|
||||
|
||||
public void createLocal(final String name, final JassType type, final JassValue value) {
|
||||
final Assignable assignable = new Assignable(type);
|
||||
assignable.setValue(value);
|
||||
this.locals.put(name, assignable);
|
||||
createLocal(name, type).setValue(value);
|
||||
}
|
||||
|
||||
public void setLocal(final String name, final JassValue value) {
|
||||
|
@ -65,7 +65,13 @@ public class Trigger {
|
||||
action.call(Collections.emptyList(), globalScope, triggerScope);
|
||||
}
|
||||
catch (final Exception e) {
|
||||
throw new JassException(globalScope, "Exception during Trigger action execute", e);
|
||||
if (e.getMessage().startsWith("Needs to sleep")) {
|
||||
// TODO not good design
|
||||
e.printStackTrace();
|
||||
}
|
||||
else {
|
||||
throw new JassException(globalScope, "Exception during Trigger action execute", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ public class JassArrayedAssignmentStatement implements JassStatement {
|
||||
variable = globalScope.getAssignableGlobal(this.identifier);
|
||||
}
|
||||
if (variable.getValue() == null) {
|
||||
|
||||
throw new RuntimeException("Unable to assign uninitialized array");
|
||||
}
|
||||
final ArrayJassValue arrayValue = variable.getValue().visit(ArrayJassValueVisitor.getInstance());
|
||||
|
@ -1,11 +1,15 @@
|
||||
package com.etheller.interpreter.ast.statement;
|
||||
|
||||
import com.etheller.interpreter.ast.Assignable;
|
||||
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||
import com.etheller.interpreter.ast.scope.LocalScope;
|
||||
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
|
||||
import com.etheller.interpreter.ast.value.ArrayJassType;
|
||||
import com.etheller.interpreter.ast.value.ArrayJassValue;
|
||||
import com.etheller.interpreter.ast.value.IntegerJassValue;
|
||||
import com.etheller.interpreter.ast.value.JassType;
|
||||
import com.etheller.interpreter.ast.value.JassValue;
|
||||
import com.etheller.interpreter.ast.value.visitor.ArrayTypeVisitor;
|
||||
|
||||
public class JassLocalStatement implements JassStatement {
|
||||
private final String identifier;
|
||||
@ -19,11 +23,15 @@ public class JassLocalStatement implements JassStatement {
|
||||
@Override
|
||||
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
final Assignable local = localScope.createLocal(this.identifier, this.type);
|
||||
if (this.type == JassType.INTEGER) {
|
||||
localScope.createLocal(this.identifier, this.type, IntegerJassValue.ZERO);
|
||||
local.setValue(IntegerJassValue.ZERO);
|
||||
}
|
||||
else {
|
||||
localScope.createLocal(this.identifier, this.type);
|
||||
final ArrayJassType arrayType = this.type.visit(ArrayTypeVisitor.getInstance());
|
||||
if (arrayType != null) {
|
||||
local.setValue(new ArrayJassValue(arrayType));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -16,7 +16,11 @@ public class JassReturnStatement implements JassStatement {
|
||||
@Override
|
||||
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
|
||||
final TriggerExecutionScope triggerScope) {
|
||||
return this.expression.evaluate(globalScope, localScope, triggerScope);
|
||||
final JassValue returnVal = this.expression.evaluate(globalScope, localScope, triggerScope);
|
||||
if (returnVal == null) {
|
||||
return JassReturnNothingStatement.RETURN_NOTHING_NOTICE;
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.etheller.interpreter.ast.util;
|
||||
|
||||
public class JassSettings {
|
||||
public static final boolean LOG_FUNCTION_DEFINITIONS = false;
|
||||
public static final int MAX_ARRAY_SIZE = 32768; // so dumb
|
||||
public static boolean DEBUG = true;
|
||||
public static boolean CONTINUE_EXECUTING_ON_ERROR = true;
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ package com.etheller.interpreter.ast.value;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.etheller.interpreter.ast.util.JassSettings;
|
||||
import com.etheller.interpreter.ast.value.visitor.JassTypeGettingValueVisitor;
|
||||
|
||||
public class ArrayJassValue implements JassValue {
|
||||
private final JassValue[] data = new JassValue[8192]; // that's the array size in JASS
|
||||
private final JassValue[] data = new JassValue[JassSettings.MAX_ARRAY_SIZE];
|
||||
private final ArrayJassType type;
|
||||
|
||||
public ArrayJassValue(final ArrayJassType type) {
|
||||
@ -43,8 +44,10 @@ public class ArrayJassValue implements JassValue {
|
||||
"Attempted to set " + this.type.getName() + " to null in array at index " + index + "!");
|
||||
}
|
||||
}
|
||||
if (value.visit(JassTypeGettingValueVisitor.getInstance()) != primitiveType) {
|
||||
throw new IllegalStateException("Illegal type for assignment to " + primitiveType.getName() + " array");
|
||||
final JassType valueType = value.visit(JassTypeGettingValueVisitor.getInstance());
|
||||
if (!primitiveType.isAssignableFrom(valueType)) {
|
||||
throw new IllegalStateException("Illegal type for assignment to " + primitiveType.getName() + " array: "
|
||||
+ (valueType == null ? "null" : valueType.getName()));
|
||||
}
|
||||
this.data[index] = value;
|
||||
}
|
||||
|
@ -3,16 +3,11 @@ package com.etheller.interpreter.ast.value;
|
||||
public class CodeJassType extends PrimitiveJassType {
|
||||
|
||||
public CodeJassType(final String name) {
|
||||
super(name);
|
||||
super(name, new CodeJassValue(null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JassValue getNullValue() {
|
||||
return new CodeJassValue(null);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.etheller.interpreter.ast.value;
|
||||
|
||||
import com.etheller.interpreter.ast.statement.JassReturnNothingStatement;
|
||||
|
||||
public interface JassType {
|
||||
<TYPE> TYPE visit(JassTypeVisitor<TYPE> visitor);
|
||||
|
||||
@ -11,10 +13,11 @@ public interface JassType {
|
||||
|
||||
JassValue getNullValue();
|
||||
|
||||
public static final PrimitiveJassType INTEGER = new PrimitiveJassType("integer");
|
||||
public static final PrimitiveJassType INTEGER = new PrimitiveJassType("integer", IntegerJassValue.ZERO);
|
||||
public static final PrimitiveJassType STRING = new StringJassType("string");
|
||||
public static final PrimitiveJassType CODE = new CodeJassType("code");
|
||||
public static final PrimitiveJassType REAL = new RealJassType("real");
|
||||
public static final PrimitiveJassType BOOLEAN = new PrimitiveJassType("boolean");
|
||||
public static final PrimitiveJassType NOTHING = new PrimitiveJassType("nothing");
|
||||
public static final PrimitiveJassType REAL = new RealJassType("real", RealJassValue.ZERO);
|
||||
public static final PrimitiveJassType BOOLEAN = new PrimitiveJassType("boolean", BooleanJassValue.FALSE);
|
||||
public static final PrimitiveJassType NOTHING = new PrimitiveJassType("nothing",
|
||||
JassReturnNothingStatement.RETURN_NOTHING_NOTICE);
|
||||
}
|
||||
|
@ -2,9 +2,11 @@ package com.etheller.interpreter.ast.value;
|
||||
|
||||
public class PrimitiveJassType implements JassType {
|
||||
private final String name;
|
||||
private final JassValue nullValue;
|
||||
|
||||
public PrimitiveJassType(final String name) {
|
||||
public PrimitiveJassType(final String name, final JassValue nullValue) {
|
||||
this.name = name;
|
||||
this.nullValue = nullValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -29,7 +31,7 @@ public class PrimitiveJassType implements JassType {
|
||||
|
||||
@Override
|
||||
public JassValue getNullValue() {
|
||||
return null;
|
||||
return this.nullValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package com.etheller.interpreter.ast.value;
|
||||
|
||||
public class RealJassType extends PrimitiveJassType {
|
||||
|
||||
public RealJassType(final String name) {
|
||||
super(name);
|
||||
public RealJassType(final String name, final JassValue nullValue) {
|
||||
super(name, nullValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,16 +3,11 @@ package com.etheller.interpreter.ast.value;
|
||||
public class StringJassType extends PrimitiveJassType {
|
||||
|
||||
public StringJassType(final String name) {
|
||||
super(name);
|
||||
super(name, new StringJassValue(null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JassValue getNullValue() {
|
||||
return new StringJassValue(null);
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,10 @@ public class ArithmeticJassValueVisitor implements JassValueVisitor<JassValue> {
|
||||
|
||||
@Override
|
||||
public JassValue accept(final CodeJassValue value) {
|
||||
throw new UnsupportedOperationException("Cannot perform arithmetic on code");
|
||||
if (this.rightHand == null) {
|
||||
return this.sign.apply(value, null);
|
||||
}
|
||||
return this.rightHand.visit(ArithmeticLeftHandCodeJassValueVisitor.INSTANCE.reset(value, this.sign));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,60 @@
|
||||
package com.etheller.interpreter.ast.value.visitor;
|
||||
|
||||
import com.etheller.interpreter.ast.expression.ArithmeticSign;
|
||||
import com.etheller.interpreter.ast.value.ArrayJassValue;
|
||||
import com.etheller.interpreter.ast.value.BooleanJassValue;
|
||||
import com.etheller.interpreter.ast.value.CodeJassValue;
|
||||
import com.etheller.interpreter.ast.value.HandleJassValue;
|
||||
import com.etheller.interpreter.ast.value.IntegerJassValue;
|
||||
import com.etheller.interpreter.ast.value.JassValue;
|
||||
import com.etheller.interpreter.ast.value.JassValueVisitor;
|
||||
import com.etheller.interpreter.ast.value.RealJassValue;
|
||||
import com.etheller.interpreter.ast.value.StringJassValue;
|
||||
|
||||
public class ArithmeticLeftHandCodeJassValueVisitor implements JassValueVisitor<JassValue> {
|
||||
public static final ArithmeticLeftHandCodeJassValueVisitor INSTANCE = new ArithmeticLeftHandCodeJassValueVisitor();
|
||||
private CodeJassValue leftHand;
|
||||
private ArithmeticSign sign;
|
||||
|
||||
public ArithmeticLeftHandCodeJassValueVisitor reset(final CodeJassValue leftHand, final ArithmeticSign sign) {
|
||||
this.leftHand = leftHand;
|
||||
this.sign = sign;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JassValue accept(final BooleanJassValue value) {
|
||||
throw new UnsupportedOperationException("Invalid types for binary operator: code and boolean");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JassValue accept(final IntegerJassValue value) {
|
||||
throw new UnsupportedOperationException("Invalid types for binary operator: code and integer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JassValue accept(final RealJassValue value) {
|
||||
throw new UnsupportedOperationException("Invalid types for binary operator: code and real");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JassValue accept(final StringJassValue value) {
|
||||
throw new UnsupportedOperationException("Invalid types for binary operator: code and string");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JassValue accept(final CodeJassValue value) {
|
||||
return this.sign.apply(this.leftHand, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JassValue accept(final ArrayJassValue value) {
|
||||
throw new UnsupportedOperationException("Invalid types for binary operator: code and array");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JassValue accept(final HandleJassValue value) {
|
||||
throw new UnsupportedOperationException("Invalid types for binary operator: code and handle");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.etheller.interpreter.ast.value.visitor;
|
||||
|
||||
import com.etheller.interpreter.ast.value.ArrayJassType;
|
||||
import com.etheller.interpreter.ast.value.HandleJassType;
|
||||
import com.etheller.interpreter.ast.value.JassTypeVisitor;
|
||||
import com.etheller.interpreter.ast.value.PrimitiveJassType;
|
||||
|
||||
public class ArrayTypeVisitor implements JassTypeVisitor<ArrayJassType> {
|
||||
private static final ArrayTypeVisitor INSTANCE = new ArrayTypeVisitor();
|
||||
|
||||
public static ArrayTypeVisitor getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayJassType accept(final PrimitiveJassType primitiveType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayJassType accept(final ArrayJassType arrayType) {
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayJassType accept(final HandleJassType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -15,6 +15,7 @@ import com.etheller.interpreter.ast.function.UserJassFunction;
|
||||
import com.etheller.interpreter.ast.scope.GlobalScope;
|
||||
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
|
||||
import com.etheller.interpreter.ast.statement.JassStatement;
|
||||
import com.etheller.interpreter.ast.util.JassSettings;
|
||||
|
||||
public class JassProgramVisitor extends JassBaseVisitor<Void> {
|
||||
public static final TriggerExecutionScope EMPTY_TRIGGER_SCOPE = new TriggerExecutionScope(null);
|
||||
@ -45,7 +46,9 @@ public class JassProgramVisitor extends JassBaseVisitor<Void> {
|
||||
}
|
||||
else if (ctx.nativeBlock() != null) {
|
||||
final String text = ctx.nativeBlock().ID().getText();
|
||||
System.out.println("Registering native: " + text);
|
||||
if (JassSettings.LOG_FUNCTION_DEFINITIONS) {
|
||||
System.out.println("Registering native: " + text);
|
||||
}
|
||||
this.jassNativeManager.registerNativeCode(ctx.getStart().getLine(), this.jassFileName, text,
|
||||
this.jassParametersVisitor.visit(ctx.nativeBlock().paramList()),
|
||||
this.jassTypeVisitor.visit(ctx.nativeBlock().type()), this.globals);
|
||||
@ -84,7 +87,9 @@ public class JassProgramVisitor extends JassBaseVisitor<Void> {
|
||||
this.jassTypeVisitor.visit(functionBlockContext.type()));
|
||||
this.globals.defineFunction(ctx.getStart().getLine(), this.jassFileName,
|
||||
functionBlockContext.ID().getText(), userJassFunction);
|
||||
System.out.println("Defining jass user function: " + functionBlockContext.ID().getText());
|
||||
if (JassSettings.LOG_FUNCTION_DEFINITIONS) {
|
||||
System.out.println("Defining jass user function: " + functionBlockContext.ID().getText());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user