package com.pointcliki.dizgruntled.logic;
import java.util.AbstractSet;
import java.util.ArrayList;
import org.json.JSONException;
import org.json.JSONObject;
import com.pointcliki.core.Sprite;
import com.pointcliki.dizgruntled.EffectManager.TriggerEvent;
import com.pointcliki.dizgruntled.GruntzGame;
import com.pointcliki.dizgruntled.InvisibleLogic;
import com.pointcliki.dizgruntled.LogicProperty;
import com.pointcliki.dizgruntled.StringLogicProperty;
import com.pointcliki.dizgruntled.map.Map;
import com.pointcliki.dizgruntled.rez.MonolithWWD;
import com.pointcliki.event.Dispatcher;
import com.pointcliki.event.FrameEvent;
import com.pointcliki.event.Minion;
import com.pointcliki.grid.GridManager;
import com.pointcliki.grid.GridManager.GridEvent;
public class Effect extends InvisibleLogic {
/**
* Serial key
*/
private static final long serialVersionUID = -5446611172846189654L;
public static final String[] MODES = new String[] {"Toggle", "Delay Toggle", "Automatic Toggle", "Landscape", "Secret Level"};
private int fMode = 0;
private String[] fGroups;
private int fTotalTriggers = 0;
private int fDelay = 0;
private int fFlip = 0;
private int fFlop = 0;
private boolean fToggled = false;
private int fLayer = 0;
private String fNewTile = "DEF";
private int fOldTile = 0;
private int fWWDTile = 0;
@Override
public void importFromWWD(String logic, String image, String animation, byte[] data) {
super.importFromWWD(logic, image, animation, data);
// Get groups
ArrayList<String> groups = new ArrayList<String>();
for (int i = 0; i < 24; i++) {
int r = MonolithWWD.readRect(data, i);
if (r > 0) groups.add("#" + r);
}
fDelay = MonolithWWD.readPoints(data);
fFlip = MonolithWWD.readDamage(data);
fFlop = MonolithWWD.readHealth(data);
fGroups = groups.toArray(new String[groups.size()]);
fTotalTriggers = fGroups.length;
// Determine the mode
Sprite sprite = new Sprite(GruntzGame.resourceManager().spritesheet("editor/logics", 17, 17));
if (logic.equals("TileSecretTrigger")) {
sprite.subimage(0, 2);
fMode = 3;
// Get the secret tile and layer
fWWDTile = MonolithWWD.readSmarts(data);
} else if (logic.equals("SecretLevelTrigger")) {
sprite.subimage(2, 2);
fMode = 4;
} else if (fGroups.length == 0) {
fMode = 2;
sprite.subimage(1, 2);
} else if (fDelay > 0 || fFlip > 0) {
fMode = 1;
sprite.subimage(1, 0);
} else {
sprite.subimage(0, 1);
}
addChild(sprite);
}
@Override
public byte[] exportToWWD() {
// TODO Auto-generated method stub
return null;
}
@Override
public void importFromJSON(JSONObject object) {
super.importFromJSON(object);
fMode = object.optInt("mode");
fGroups = object.optString("groups", "").split(" ");
if (fGroups.length == 1 && fGroups[0].equals("")) fGroups = new String[]{};
fTotalTriggers = fGroups.length;
fDelay = object.optInt("delay", 0);
fFlip = object.optInt("flip", 0);
fFlop = object.optInt("flop", 0);
fLayer = object.optInt("layer", 0);
fNewTile = object.optString("tile", "DEF");
Sprite sprite = new Sprite(GruntzGame.resourceManager().spritesheet("editor/logics", 17, 17));
if (fMode == 0) sprite.subimage(0, 1);
else if (fMode == 1) sprite.subimage(1, 0);
else if (fMode == 2) sprite.subimage(1, 2);
else if (fMode == 3) sprite.subimage(0, 2);
else sprite.subimage(2, 2);
addChild(sprite);
}
private String groupString() {
if (fGroups.length == 0) return null;
StringBuilder sb = new StringBuilder("");
for (String s: fGroups) sb.append(s + " ");
if (sb.length() == 0) return sb.toString();
return sb.substring(0, sb.length() - 1);
}
@Override
public JSONObject exportToJSON() throws JSONException {
JSONObject obj = super.exportToJSON();
obj.put("mode", fMode);
if (fMode != 2 && fGroups.length > 0) obj.put("groups", groupString());
if (fMode != 0 && fDelay > 0) obj.put("delay", fDelay);
if (fMode != 0 && fFlip > 0) obj.put("flip", fFlip);
if (fMode == 2 && fFlop > 0 && fFlop != fFlip) obj.put("flop", fFlop);
if (fMode == 3 && fLayer > 0) obj.put("layer", fLayer);
if (fMode == 3 && !fNewTile.equals("DEF")) obj.put("tile", fNewTile);
return obj;
}
@Override
public void init(Map map) {
// Init
super.init(map);
// Get the traits
AbstractSet<String> traits = map.traits(fTile);
// Correct flop
if (fFlop == 0) fFlop = fFlip;
if (fWWDTile > 0) {
// Find the tile layer that has this type
for (int i = 0; i < map().tilesetCount(); i++) {
byte b = map().tileset(i).wapValue(fWWDTile);
if (b > 1) {
fNewTile = map().tileset(i).type(b);
fLayer = i;
break;
}
}
}
if (!map.editing()) {
Minion<TriggerEvent> minion = new Minion<TriggerEvent>() {
@Override
public long run(Dispatcher<TriggerEvent> dispatcher, String type, TriggerEvent event) {
trigger(event.count(), event.on());
return Minion.CONTINUE;
}
};
// Iterate through groups and add the Trigger to the LogicManager
for (String group: fGroups) effectManager().dispatcher().addMinion(group, minion);
// Low pyramid
if (traits.contains("lowPyramid")) fToggled = true;
// Red pyramids
if (traits.contains("redPyramid")) map().populateRedPyramidLogics(this);
// Contribute to time delay
if (traits.contains("timePyramid"))
for (String group: fGroups) effectManager().contributeTimeDelay(group, fDelay + fFlip);
// Mark as a stateful tile
if (traits.contains("trigger")) map().markStatefulTile(fTile);
// Trigger if no group
if (fTotalTriggers == 0) trigger(0, true);
}
}
@Override
public void initProperties() {
StringLogicProperty mode = new StringLogicProperty("mode") {
@Override
public String description() {
return "The mode of the effect";
}
@Override
public String value() {
return MODES[fMode];
}
@Override
public String[] choices() {
return MODES;
}
@Override
public void choice(int i) {
fMode = i;
initProperties();
}
};
StringLogicProperty group = new StringLogicProperty("group") {
@Override
public String description() {
return "The group(s) of the effect";
}
@Override
public String value() {
return groupString();
}
@Override
public String[] choices() {
return null;
}
@Override
public void value(String s) {
fGroups = s.split(" ");
}
};
StringLogicProperty delay = new StringLogicProperty("delay") {
@Override
public String description() {
return "The delay of the effect";
}
@Override
public String value() {
return fDelay + "";
}
@Override
public String[] choices() {
return null;
}
@Override
public void value(String s) {
try {
fDelay = Integer.parseInt(s);
} catch (Exception e) {
fDelay = 0;
}
}
};
StringLogicProperty flip = new StringLogicProperty("flip time") {
@Override
public String description() {
return "The flip duration of the effect";
}
@Override
public String value() {
return fFlip + "";
}
@Override
public String[] choices() {
return null;
}
@Override
public void value(String s) {
try {
fFlip = Integer.parseInt(s);
} catch (Exception e) {
fFlip = 0;
}
}
};
StringLogicProperty flop = new StringLogicProperty("flop time") {
@Override
public String description() {
return "The flop duration of the effect";
}
@Override
public String value() {
return fFlop + "";
}
@Override
public String[] choices() {
return null;
}
@Override
public void value(String s) {
try {
fFlop = Integer.parseInt(s);
} catch (Exception e) {
fFlop = 0;
}
}
};
StringLogicProperty tileset = new StringLogicProperty("tile layer") {
@Override
public String description() {
return "The layer index of the tile to change";
}
@Override
public String value() {
return fLayer + "";
}
@Override
public String[] choices() {
return null;
}
@Override
public void value(String s) {
try {
fLayer = Integer.parseInt(s);
} catch (Exception e) {
fLayer = 0;
}
}
};
StringLogicProperty type = new StringLogicProperty("tile type") {
@Override
public String description() {
return "The type of the replacement tile";
}
@Override
public String value() {
return fNewTile;
}
@Override
public String[] choices() {
return null;
}
@Override
public void value(String s) {
fNewTile = s;
}
};
if (fMode == 0) fProperties = new LogicProperty[] {mode, group};
else if (fMode == 1) fProperties = new LogicProperty[] {mode, group, delay, flip};
else if (fMode == 2) fProperties = new LogicProperty[] {mode, delay, flip, flop};
else if (fMode == 3) fProperties = new LogicProperty[] {mode, delay, flip, tileset, type};
else fProperties = new LogicProperty[] {mode};
}
@Override
public String name() {
return "Effect";
}
private void trigger(final int count, final boolean on) {
// Get traits
AbstractSet<String> traits = map().traits(fTile);
// Check for trigger
if (traits.contains("trigger") || fMode == 3) {
// Check for delay
if (fDelay > 0) {
frameManager().queue(new Minion<FrameEvent>() {
@Override
public long run(Dispatcher<FrameEvent> dispatcher, String type, FrameEvent event) {
if (fMode == 3) swap();
else toggle(count, on);
return Minion.FINISH;
}
}, (long) Math.floor(timeManager().frameDuration(fDelay)));
} else {
if (fMode == 3) swap();
else toggle(count, on);
}
}
}
private void swap() {
// Record old tile
fOldTile = map().tile(fLayer, fTile.x(), fTile.y());
mapManager().parent().manager(GridManager.class).dispatcher().dispatch(fTile, "tilechange", new GridEvent());
// Swap with new tile
int tileid = map().tileset(fLayer).tile(fNewTile);
if (tileid >= 0) {
map().tile(fLayer, fTile.x(), fTile.y(), tileid);
// Queue if flip
frameManager().queue(new Minion<FrameEvent>() {
@Override
public long run(Dispatcher<FrameEvent> dispatcher, String type, FrameEvent event) {
map().tile(fLayer, fTile.x(), fTile.y(), fOldTile);
mapManager().parent().manager(GridManager.class).dispatcher().dispatch(fTile, "tilechange", new GridEvent());
return Minion.FINISH;
}
}, (long) Math.floor(timeManager().frameDuration(fFlip)));
}
}
private void toggle(final int count, final boolean on) {
// Get traits
AbstractSet<String> traits = map().traits(fTile);
// Check for many pyramid
if (traits.contains("manyPyramid")) {
// Update total triggers to wait for
if (on) fTotalTriggers--;
else fTotalTriggers++;
// Check to put down
if ((fTotalTriggers > 0 && fToggled) || (fTotalTriggers < 1 && !fToggled)) {
// Mark checkpoint to disable checkpoint switches
for (String group: fGroups) effectManager().checkpoint(group);
// Trigger
map().tileToggle(fTile);
fToggled = !fToggled;
}
} else if (traits.contains("orangePyramid")) {
if (fToggled != on) {
// Trigger
map().tileToggle(fTile);
fToggled = on;
}
} else {
// Trigger
map().tileToggle(fTile);
fToggled = !fToggled;
}
// Queue if flip
if (fToggled && fFlip > 0) {
frameManager().queue(new Minion<FrameEvent>() {
@Override
public long run(Dispatcher<FrameEvent> dispatcher, String type, FrameEvent event) {
toggle(count, false);
return Minion.FINISH;
}
}, (long) Math.floor(timeManager().frameDuration(fFlip)));
}
if (!fToggled && fFlop > 0 && !traits.contains("timePyramid")) {
frameManager().queue(new Minion<FrameEvent>() {
@Override
public long run(Dispatcher<FrameEvent> dispatcher, String type, FrameEvent event) {
toggle(count, true);
return Minion.FINISH;
}
}, (long) Math.floor(timeManager().frameDuration(fFlop)));
}
}
}