/** * eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the * <e-UCM> research group. * * Copyright 2005-2010 <e-UCM> research group. * * You can access a list of all the contributors to eAdventure at: * http://e-adventure.e-ucm.es/contributors * * <e-UCM> is a research group of the Department of Software Engineering * and Artificial Intelligence at the Complutense University of Madrid * (School of Computer Science). * * C Profesor Jose Garcia Santesmases sn, * 28040 Madrid (Madrid), Spain. * * For more info please visit: <http://e-adventure.e-ucm.es> or * <http://www.e-ucm.es> * * **************************************************************************** * * This file is part of eAdventure, version 2.0 * * eAdventure is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * eAdventure 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with eAdventure. If not, see <http://www.gnu.org/licenses/>. */ package ead.importer.subimporters.chapter; import com.google.inject.Inject; import es.eucm.ead.model.assets.drawable.basics.Caption; import es.eucm.ead.model.assets.text.BasicFont; import es.eucm.ead.model.elements.conditions.ANDCond; import es.eucm.ead.model.elements.conditions.EmptyCond; import es.eucm.ead.model.elements.conditions.NOTCond; import es.eucm.ead.model.elements.conditions.OperationCond; import es.eucm.ead.model.elements.conditions.enums.Comparator; import es.eucm.ead.model.elements.effects.TriggerMacroEf; import es.eucm.ead.model.elements.effects.hud.ModifyHUDEf; import es.eucm.ead.model.elements.effects.variables.ChangeFieldEf; import es.eucm.ead.model.elements.events.ConditionedEv; import es.eucm.ead.model.elements.events.SceneElementEv; import es.eucm.ead.model.elements.events.enums.ConditionedEvType; import es.eucm.ead.model.elements.events.enums.SceneElementEvType; import es.eucm.ead.model.elements.extra.EAdList; import es.eucm.ead.model.elements.operations.ElementField; import es.eucm.ead.model.elements.operations.MathOp; import es.eucm.ead.model.elements.operations.SystemFields; import es.eucm.ead.model.elements.operations.ValueOp; import es.eucm.ead.model.elements.scenes.SceneElement; import es.eucm.ead.model.elements.scenes.SceneElementDef; import es.eucm.ead.model.params.variables.EAdVarDef; import es.eucm.ead.model.params.variables.VarDef; import ead.importer.EAdElementImporter; import ead.importer.annotation.ImportAnnotator; import ead.importer.interfaces.EffectsImporterFactory; import es.eucm.ead.tools.StringHandler; import es.eucm.eadventure.common.data.chapter.Timer; import es.eucm.eadventure.common.data.chapter.conditions.Conditions; public class TimerImporter implements EAdElementImporter<Timer, Event> { private static int count = 0; /** * Conditions importer */ private EAdElementImporter<Conditions, Condition> conditionsImporter; private EffectsImporterFactory effectsImporter; private StringHandler stringHandler; protected ImportAnnotator annotator; private static final EAdVarDef<Integer> CURRENT_TIME_VAR = new VarDef<Integer>( "current_time_timer", Integer.class, 0); private static final EAdVarDef<Boolean> RUNNING_VAR = new VarDef<Boolean>( "stopped_timer", Boolean.class, false); private static final EAdVarDef<Boolean> NOT_TRIGGERED_VAR = new VarDef<Boolean>( "stopped_timer", Boolean.class, true); @Inject public TimerImporter( EAdElementImporter<Conditions, Condition> conditionsImporter, EffectsImporterFactory effectsImporter, StringHandler stringHandler, ImportAnnotator annotator) { this.conditionsImporter = conditionsImporter; this.effectsImporter = effectsImporter; this.stringHandler = stringHandler; this.annotator = annotator; } @Override public Event init(Timer oldTimer) { return new ConditionedEv(); } @Override public Event convert(Timer oldTimer, Object object) { ConditionedEv event = (ConditionedEv) object; Condition initCondition = conditionsImporter.init(oldTimer .getInitCond()); initCondition = conditionsImporter.convert(oldTimer.getInitCond(), initCondition); SceneElement timer = getSceneElementForTimer(oldTimer, initCondition); ElementField runningField = new ElementField(timer, RUNNING_VAR); ElementField notTriggeredField = new ElementField(timer, NOT_TRIGGERED_VAR); ElementField visibleField = new ElementField(timer, SceneElement.VAR_VISIBLE); ChangeFieldEf changeVisible = new ChangeFieldEf(visibleField, EmptyCond.TRUE); ElementField currentTimeField = new ElementField(timer, CURRENT_TIME_VAR); ModifyHUDEf modifyHUD = new ModifyHUDEf(timer, true); ChangeFieldEf changeRunning = new ChangeFieldEf(runningField, EmptyCond.TRUE); event.addEffect(ConditionedEvType.CONDITIONS_MET, modifyHUD); event.addEffect(ConditionedEvType.CONDITIONS_MET, changeVisible); event.addEffect(ConditionedEvType.CONDITIONS_MET, new ChangeFieldEf( currentTimeField, new ValueOp(0))); event.addEffect(ConditionedEvType.CONDITIONS_MET, changeRunning); event.addEffect(ConditionedEvType.CONDITIONS_MET, new ChangeFieldEf( notTriggeredField, EmptyCond.FALSE)); event.setRunNotMetConditions(false); event.setCondition(new ANDCond(initCondition, new OperationCond( notTriggeredField))); if (!oldTimer.isShowWhenStopped()) { ConditionedEv visibleEvent = new ConditionedEv(); ChangeFieldEf changeVisibleFalse = new ChangeFieldEf(visibleField, EmptyCond.FALSE); visibleEvent .setCondition(new ANDCond(new OperationCond(visibleField), new NOTCond(new OperationCond(runningField)))); visibleEvent.addEffect(ConditionedEvType.CONDITIONS_MET, changeVisibleFalse); timer.addEvent(visibleEvent); } if (oldTimer.isMultipleStarts()) { ConditionedEv multipleStarts = new ConditionedEv(); multipleStarts.setCondition(initCondition); multipleStarts.addEffect(ConditionedEvType.CONDITIONS_MET, changeRunning); multipleStarts.addEffect(ConditionedEvType.CONDITIONS_MET, changeVisible); multipleStarts.addEffect(ConditionedEvType.CONDITIONS_MET, new ChangeFieldEf(currentTimeField, new ValueOp(0))); timer.addEvent(multipleStarts); } return event; } private SceneElement getSceneElementForTimer(Timer oldTimer, Condition initCondition) { SceneElement timer = new SceneElement(); timer.setVarInitialValue(SceneElement.VAR_ENABLE, false); ElementField currentTimeField = new ElementField(timer, CURRENT_TIME_VAR); ElementField runningField = new ElementField(timer, RUNNING_VAR); ElementField visibleField = new ElementField(timer, SceneElement.VAR_VISIBLE); timer.setVarInitialValue(SceneElement.VAR_VISIBLE, false); timer.setPosition(10, 20 * count - 1); // Appearance if (oldTimer.isShowTime()) { addAppearance(timer, oldTimer, currentTimeField); } // Event to update the timer SceneElementEv updater = new SceneElementEv(); timer.addEvent(updater); // Update current time addUpdateCurrentTime(updater, currentTimeField, runningField); // Check if time expired addEffectsTimeExpired(timer, updater, currentTimeField, visibleField, runningField, oldTimer); // Add effects when stopped addEffectsWhenStopped(timer, oldTimer, runningField, initCondition); return timer; } private void addEffectsWhenStopped(SceneElement timer, Timer oldTimer, ElementField runningField, Condition initCondition) { EAdList<Effect> stopEffects = effectsImporter.getMacroEffects(oldTimer .getPostEffects()); if (stopEffects != null) { Condition stopCondition = null; if (oldTimer.isUsesEndCondition()) { stopCondition = conditionsImporter.init(oldTimer.getEndCond()); stopCondition = conditionsImporter.convert(oldTimer .getEndCond(), stopCondition); } else { stopCondition = new NOTCond(initCondition); } stopCondition = new ANDCond(new OperationCond(runningField), stopCondition); TriggerMacroEf triggerStopEffects = new TriggerMacroEf(); triggerStopEffects.putEffects(EmptyCond.TRUE, stopEffects); ConditionedEv stopEvent = new ConditionedEv(); stopEvent.setCondition(stopCondition); stopEvent.addEffect(ConditionedEvType.CONDITIONS_MET, triggerStopEffects); stopEffects.add(new ChangeFieldEf(runningField, EmptyCond.FALSE)); timer.addEvent(stopEvent); } } private void addEffectsTimeExpired(SceneElement timer, SceneElementEv updater, ElementField currentTimeField, ElementField visibleField, ElementField runningField, Timer oldTimer) { int time = oldTimer.getTime().intValue() * 1000; EAdList<Effect> expiredEffects = effectsImporter .getMacroEffects(oldTimer.getEffects()); if (expiredEffects != null) { TriggerMacroEf triggerExpiredEffects = new TriggerMacroEf(); triggerExpiredEffects.putEffects(EmptyCond.TRUE, expiredEffects); Condition expireCondition = new OperationCond(currentTimeField, time, Comparator.GREATER_EQUAL); // Stop the timer if expires and set current time to its final value time = oldTimer.isRunsInLoop() ? 0 : time; expiredEffects.add(new ChangeFieldEf(currentTimeField, new ValueOp( time))); if (!oldTimer.isRunsInLoop()) { expiredEffects.add(new ChangeFieldEf(runningField, EmptyCond.FALSE)); } ConditionedEv expireEffectsEvent = new ConditionedEv(); expireEffectsEvent.addEffect(ConditionedEvType.CONDITIONS_MET, triggerExpiredEffects); expireEffectsEvent.setCondition(expireCondition); timer.addEvent(expireEffectsEvent); } } private void addUpdateCurrentTime(SceneElementEv updater, ElementField currentTimeField, ElementField runningField) { ChangeFieldEf updateCurrentTime = new ChangeFieldEf(); updateCurrentTime.addField(currentTimeField); updateCurrentTime.setOperation(new MathOp("[0] + [1]", currentTimeField, SystemFields.ELAPSED_TIME_PER_UPDATE)); updateCurrentTime.setCondition(new OperationCond(runningField)); updater.addEffect(SceneElementEvType.ALWAYS, updateCurrentTime); } private void addAppearance(SceneElement timer, Timer oldTimer, ElementField currentTimeField) { Caption text = new Caption(stringHandler.generateNewString()); text.setFont(BasicFont.BIG); MathOp timeOperation = null; if (oldTimer.isCountDown()) timeOperation = new MathOp(oldTimer.getTime() + " - ([0] / 1000)", currentTimeField); else timeOperation = new MathOp("[0] / 1000", currentTimeField); stringHandler.setString(text.getLabel(), oldTimer.getDisplayName() + " [0]"); text.getOperations().add(timeOperation); timer.getDefinition().addAsset(SceneElementDef.appearance, text); } }