159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage jme3test.input.combomoves; 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.app.SimpleApplication; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.font.BitmapText; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.input.KeyInput; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.input.controls.ActionListener; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.input.controls.KeyTrigger; 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.ColorRGBA; 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.Spatial.CullHint; 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.ArrayList; 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.HashSet; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.List; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class TestComboMoves extends SimpleApplication implements ActionListener { 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private HashSet<String> pressedMappings = new HashSet<String>(); 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ComboMove fireball; 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ComboMoveExecution fireballExec; 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private BitmapText fireballText; 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ComboMove shuriken; 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ComboMoveExecution shurikenExec; 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private BitmapText shurikenText; 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ComboMove jab; 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ComboMoveExecution jabExec; 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private BitmapText jabText; 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ComboMove punch; 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ComboMoveExecution punchExec; 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private BitmapText punchText; 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ComboMove currentMove = null; 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private float currentMoveCastTime = 0; 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private float time = 0; 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static void main(String[] args){ 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TestComboMoves app = new TestComboMoves(); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta app.start(); 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void simpleInitApp() { 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setDisplayFps(false); 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setDisplayStatView(false); 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Create debug text 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BitmapText helpText = new BitmapText(guiFont); 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta helpText.setLocalTranslation(0, settings.getHeight(), 0); 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta helpText.setText("Moves:\n" + 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "Fireball: Down, Down+Right, Right\n"+ 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "Shuriken: Left, Down, Attack1(Z)\n"+ 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "Jab: Attack1(Z)\n"+ 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "Punch: Attack1(Z), Attack1(Z)\n"); 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta guiNode.attachChild(helpText); 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireballText = new BitmapText(guiFont); 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireballText.setColor(ColorRGBA.Orange); 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireballText.setLocalTranslation(0, fireballText.getLineHeight(), 0); 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta guiNode.attachChild(fireballText); 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shurikenText = new BitmapText(guiFont); 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shurikenText.setColor(ColorRGBA.Cyan); 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shurikenText.setLocalTranslation(0, shurikenText.getLineHeight()*2f, 0); 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta guiNode.attachChild(shurikenText); 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta jabText = new BitmapText(guiFont); 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta jabText.setColor(ColorRGBA.Red); 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta jabText.setLocalTranslation(0, jabText.getLineHeight()*3f, 0); 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta guiNode.attachChild(jabText); 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punchText = new BitmapText(guiFont); 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punchText.setColor(ColorRGBA.Green); 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punchText.setLocalTranslation(0, punchText.getLineHeight()*4f, 0); 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta guiNode.attachChild(punchText); 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_LEFT)); 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_RIGHT)); 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("Up", new KeyTrigger(KeyInput.KEY_UP)); 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("Down", new KeyTrigger(KeyInput.KEY_DOWN)); 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addMapping("Attack1", new KeyTrigger(KeyInput.KEY_Z)); 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta inputManager.addListener(this, "Left", "Right", "Up", "Down", "Attack1"); 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireball = new ComboMove("Fireball"); 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireball.press("Down").notPress("Right").done(); 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireball.press("Right", "Down").done(); 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireball.press("Right").notPress("Down").done(); 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireball.notPress("Right", "Down").done(); 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireball.setUseFinalState(false); // no waiting on final state 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shuriken = new ComboMove("Shuriken"); 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shuriken.press("Left").notPress("Down", "Attack1").done(); 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shuriken.press("Down").notPress("Attack1").timeElapsed(0.11f).done(); 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shuriken.press("Attack1").notPress("Left").timeElapsed(0.11f).done(); 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shuriken.notPress("Left", "Down", "Attack1").done(); 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta jab = new ComboMove("Jab"); 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta jab.setPriority(0.5f); // make jab less important than other moves 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta jab.press("Attack1").done(); 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punch = new ComboMove("Punch"); 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punch.press("Attack1").done(); 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punch.notPress("Attack1").done(); 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punch.press("Attack1").done(); 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireballExec = new ComboMoveExecution(fireball); 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shurikenExec = new ComboMoveExecution(shuriken); 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta jabExec = new ComboMoveExecution(jab); 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punchExec = new ComboMoveExecution(punch); 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void simpleUpdate(float tpf){ 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta time += tpf; 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // check every frame if any executions are expired 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shurikenExec.updateExpiration(time); 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta shurikenText.setText("Shuriken Exec: " + shurikenExec.getDebugString()); 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireballExec.updateExpiration(time); 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fireballText.setText("Fireball Exec: " + fireballExec.getDebugString()); 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta jabExec.updateExpiration(time); 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta jabText.setText("Jab Exec: " + jabExec.getDebugString()); 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punchExec.updateExpiration(time); 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta punchText.setText("Punch Exec: " + punchExec.getDebugString()); 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (currentMove != null){ 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentMoveCastTime -= tpf; 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (currentMoveCastTime <= 0){ 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta System.out.println("DONE CASTING " + currentMove.getMoveName()); 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentMoveCastTime = 0; 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentMove = null; 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void onAction(String name, boolean isPressed, float tpf) { 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (isPressed){ 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pressedMappings.add(name); 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta pressedMappings.remove(name); 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // the pressed mappings was changed. update combo executions 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<ComboMove> invokedMoves = new ArrayList<ComboMove>(); 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (shurikenExec.updateState(pressedMappings, time)){ 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta invokedMoves.add(shuriken); 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (fireballExec.updateState(pressedMappings, time)){ 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta invokedMoves.add(fireball); 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (jabExec.updateState(pressedMappings, time)){ 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta invokedMoves.add(jab); 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (punchExec.updateState(pressedMappings, time)){ 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta invokedMoves.add(punch); 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (invokedMoves.size() > 0){ 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // choose move with highest priority 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float priority = 0; 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ComboMove toExec = null; 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (ComboMove move : invokedMoves){ 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (move.getPriority() > priority){ 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta priority = move.getPriority(); 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta toExec = move; 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (currentMove != null && currentMove.getPriority() > toExec.getPriority()){ 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentMove = toExec; 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta currentMoveCastTime = currentMove.getCastTime(); 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //System.out.println("CASTING " + currentMove.getMoveName()); 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 218