├── required files ├── config │ └── setting │ │ └── profile.cfg └── res │ ├── bgm │ └── joker.ogg │ ├── graphics │ ├── jevil.png │ ├── conveyor.png │ ├── iceblock.png │ ├── particle.png │ ├── scanner.png │ ├── cargoreturn.png │ ├── blank_black_24b.png │ ├── blank_white_24b.png │ ├── conveyorreverse.png │ ├── examResultText.png │ ├── efficiency_grades.png │ ├── frame_inner_white.png │ └── frame_outer_white.png │ └── se │ └── zeroxfc │ ├── bonus.wav │ ├── horn.wav │ ├── icicle.wav │ ├── rise.wav │ ├── steam.wav │ ├── wind1.wav │ ├── wind2.wav │ ├── wind3.wav │ ├── bigclear.wav │ ├── bonuspop.wav │ ├── landing.wav │ ├── noclear.wav │ ├── bombexplode.wav │ ├── explosion1.wav │ ├── explosion2.wav │ ├── explosion3.wav │ ├── explosion4.wav │ ├── linescanned.wav │ ├── nolanding.wav │ ├── normalclear.wav │ ├── timereduce.wav │ ├── zerofreeze.wav │ ├── timeincrease.wav │ ├── fireworkexplode.wav │ ├── fireworklaunch.wav │ ├── groundcrackle1.wav │ ├── groundcrackle2.wav │ ├── groundcrackle3.wav │ └── linescannermove.wav ├── GitHub ModePile Banner-Final.png ├── src └── zeroxfc │ └── nullpo │ └── custom │ ├── libs │ ├── types │ │ ├── FloatFunction.java │ │ ├── ToFloatFunction.java │ │ ├── LazyLoadException.java │ │ ├── RuntimeMusic.java │ │ ├── Box.java │ │ ├── ObjectAlignment.java │ │ ├── tuples │ │ │ ├── IntPair.java │ │ │ ├── FloatPair.java │ │ │ ├── DoublePair.java │ │ │ └── Pair.java │ │ ├── RuntimeImage.java │ │ ├── ModeSettings.java │ │ ├── LazyReference.java │ │ └── ImageChunk.java │ ├── effects │ │ ├── Effect.java │ │ └── ScorePopup.java │ ├── RenderCommand.java │ ├── annotations │ │ ├── DebugOps.java │ │ └── Debug.java │ ├── ArrayRandomiser.java │ ├── WeightedRandomiser.java │ ├── LevelTableBuilder.java │ ├── backgroundtypes │ │ ├── BackgroundNoAnim.java │ │ └── BackgroundImageSequenceAnim.java │ ├── ScrollingMarqueeText.java │ ├── particles │ │ ├── BlockBasedEmitter.java │ │ ├── ParticleEmitterBase.java │ │ ├── BlockParticle.java │ │ └── BlockParticleCollection.java │ ├── SideWaveText.java │ ├── StaticFlyInText.java │ └── ShakingText.java │ ├── modes │ ├── objects │ │ ├── minesweeper │ │ │ └── GridSpace.java │ │ ├── seasons │ │ │ ├── NextAndFieldState.java │ │ │ ├── RewindBlock.java │ │ │ └── BlockVortex.java │ │ ├── expressshipping │ │ │ ├── GamePiece.java │ │ │ ├── PieceFactory.java │ │ │ ├── I1.java │ │ │ ├── O4.java │ │ │ ├── X5.java │ │ │ ├── I2.java │ │ │ ├── Z5.java │ │ │ ├── S5.java │ │ │ ├── I3.java │ │ │ ├── S4.java │ │ │ ├── Z4.java │ │ │ ├── I4.java │ │ │ ├── L3.java │ │ │ ├── Stairs6.java │ │ │ ├── J4.java │ │ │ ├── L4.java │ │ │ └── P5.java │ │ ├── gemswap │ │ │ ├── ScoreEvent.java │ │ │ ├── Gem.java │ │ │ ├── Lightning.java │ │ │ ├── NormalGem.java │ │ │ ├── EmptyGem.java │ │ │ ├── PowerGem.java │ │ │ ├── HypercubeGem.java │ │ │ └── StarGem.java │ │ └── twothousandandfortyeight │ │ │ └── GridSpace2048.java │ └── Tetratiotris.java │ ├── wallkick │ ├── SuperRandomWallkick.java │ ├── ClassicLenientWallkick.java │ ├── STX1Wallkick.java │ ├── SuperDTETWallkick.java │ └── SomeRandomShittyRotationSystemWallkick.java │ └── random │ └── DroughtedPieceBiasRandomizer.java ├── ci-build-task.sh ├── .gitignore ├── .github └── workflows │ └── main.yml └── CONTRIBUTING.md /required files/config/setting/profile.cfg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /GitHub ModePile Banner-Final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/GitHub ModePile Banner-Final.png -------------------------------------------------------------------------------- /required files/res/bgm/joker.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/bgm/joker.ogg -------------------------------------------------------------------------------- /required files/res/graphics/jevil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/jevil.png -------------------------------------------------------------------------------- /required files/res/graphics/conveyor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/conveyor.png -------------------------------------------------------------------------------- /required files/res/graphics/iceblock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/iceblock.png -------------------------------------------------------------------------------- /required files/res/graphics/particle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/particle.png -------------------------------------------------------------------------------- /required files/res/graphics/scanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/scanner.png -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/bonus.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/bonus.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/horn.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/horn.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/icicle.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/icicle.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/rise.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/rise.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/steam.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/steam.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/wind1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/wind1.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/wind2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/wind2.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/wind3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/wind3.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/bigclear.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/bigclear.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/bonuspop.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/bonuspop.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/landing.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/landing.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/noclear.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/noclear.wav -------------------------------------------------------------------------------- /required files/res/graphics/cargoreturn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/cargoreturn.png -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/bombexplode.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/bombexplode.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/explosion1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/explosion1.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/explosion2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/explosion2.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/explosion3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/explosion3.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/explosion4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/explosion4.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/linescanned.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/linescanned.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/nolanding.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/nolanding.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/normalclear.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/normalclear.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/timereduce.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/timereduce.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/zerofreeze.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/zerofreeze.wav -------------------------------------------------------------------------------- /required files/res/graphics/blank_black_24b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/blank_black_24b.png -------------------------------------------------------------------------------- /required files/res/graphics/blank_white_24b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/blank_white_24b.png -------------------------------------------------------------------------------- /required files/res/graphics/conveyorreverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/conveyorreverse.png -------------------------------------------------------------------------------- /required files/res/graphics/examResultText.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/examResultText.png -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/timeincrease.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/timeincrease.wav -------------------------------------------------------------------------------- /required files/res/graphics/efficiency_grades.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/efficiency_grades.png -------------------------------------------------------------------------------- /required files/res/graphics/frame_inner_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/frame_inner_white.png -------------------------------------------------------------------------------- /required files/res/graphics/frame_outer_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/graphics/frame_outer_white.png -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/fireworkexplode.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/fireworkexplode.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/fireworklaunch.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/fireworklaunch.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/groundcrackle1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/groundcrackle1.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/groundcrackle2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/groundcrackle2.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/groundcrackle3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/groundcrackle3.wav -------------------------------------------------------------------------------- /required files/res/se/zeroxfc/linescannermove.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MF42-DZH/ModePile/HEAD/required files/res/se/zeroxfc/linescannermove.wav -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/FloatFunction.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | // Why isn't this in the Java 8 standard library? 4 | 5 | @FunctionalInterface 6 | public interface FloatFunction { 7 | R apply(float arg); 8 | } 9 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/ToFloatFunction.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | // Why isn't this in the Java 8 standard library? 4 | 5 | @FunctionalInterface 6 | public interface ToFloatFunction { 7 | float applyAsFloat(T arg); 8 | } 9 | -------------------------------------------------------------------------------- /ci-build-task.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | curl -L -O https://github.com/nullpomino/nullpomino/archive/refs/tags/v7.5.0.tar.gz 4 | tar -xf ./v7.5.0.tar.gz 5 | cp -a ./nullpomino-7.5.0/* . 6 | mkdir -p ./bin 7 | find -wholename "./src/*.java" > .TMPSRC 8 | javac -source 8 -target 8 -encoding utf8 -sourcepath ./src -d ./bin -cp ./lib/*:. @.TMPSRC 9 | rm -rf ./bin/biz ./bin/com ./bin/mu ./bin/net ./bin/org 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore IDE junk. 2 | /.idea/* 3 | /.vscode/* 4 | 5 | # Ignore everything that isn't the project. 6 | /* 7 | 8 | # Un-ignore everything to do with the project. 9 | !/required files 10 | !/src/network/nightshade 11 | !/src/mandl 12 | !/src/zeroxfc 13 | !/POST_BUILD_INSTALLATION_v1.14.txt 14 | !/README.md 15 | !/USAGE.txt 16 | !/GitHub ModePile Banner-Final.png 17 | !/LICENCE 18 | !/CONTRIBUTING.md 19 | !/build.bat 20 | !/build.sh 21 | !/Dockerfile 22 | !/.github/* 23 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/effects/Effect.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.effects; 2 | 3 | import mu.nu.nullpo.game.event.EventReceiver; 4 | import mu.nu.nullpo.game.play.GameEngine; 5 | import zeroxfc.nullpo.custom.libs.CustomResourceHolder; 6 | 7 | public interface Effect { 8 | void update(); 9 | 10 | boolean shouldNull(); 11 | 12 | void draw(GameEngine engine, EventReceiver receiver, int playerID, int[] args, CustomResourceHolder customHolder); 13 | } 14 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/RenderCommand.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs; 2 | 3 | class RenderCommand { 4 | public RenderType renderType; 5 | public Object[] args; 6 | 7 | private RenderCommand() { 8 | // Use other constructor. 9 | } 10 | 11 | public RenderCommand(RenderType renderType, Object[] args) { 12 | this.renderType = renderType; 13 | this.args = args; 14 | } 15 | 16 | public enum RenderType { 17 | Rectangle, Arc, Oval 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/minesweeper/GridSpace.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.minesweeper; 2 | 3 | public class GridSpace { 4 | public int surroundingMines; 5 | public boolean isMine; 6 | public boolean uncovered; 7 | public boolean flagged; 8 | public boolean question; 9 | 10 | public GridSpace(boolean isMine) { 11 | uncovered = false; 12 | this.isMine = isMine; 13 | surroundingMines = 0; 14 | flagged = false; 15 | question = false; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/LazyLoadException.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | /** Signifies that an exception has occurred while lazy-loading a value. */ 4 | public class LazyLoadException extends RuntimeException { 5 | 6 | public LazyLoadException() {} 7 | 8 | public LazyLoadException(String message) { 9 | super(message); 10 | } 11 | 12 | public LazyLoadException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | 16 | public LazyLoadException(Throwable cause) { 17 | super(cause); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: ModePile Pack CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | container: 13 | image: 0xfc963f18dc21/misc-build-images:jdk8-alpine-curl 14 | steps: 15 | - name: Clone the Pack 16 | uses: actions/checkout@v4 17 | - name: Build the Pack 18 | run: sh ./ci-build-task.sh 19 | - name: Export the built class files 20 | uses: actions/upload-artifact@v4 21 | with: 22 | name: bin-classes 23 | path: ./bin 24 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/RuntimeMusic.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | public abstract class RuntimeMusic { 4 | public final M music; 5 | 6 | protected RuntimeMusic(M music) { 7 | this.music = music; 8 | } 9 | 10 | public static class Slick extends RuntimeMusic { 11 | public Slick(org.newdawn.slick.Music music) { 12 | super(music); 13 | } 14 | } 15 | 16 | public static class SDL extends RuntimeMusic { 17 | public SDL(sdljava.mixer.MixMusic music) { 18 | super(music); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/seasons/NextAndFieldState.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.seasons; 2 | 3 | import mu.nu.nullpo.game.component.Field; 4 | import mu.nu.nullpo.game.component.Piece; 5 | import mu.nu.nullpo.game.play.GameEngine; 6 | 7 | // Holds the state of the next, hold and field. 8 | public class NextAndFieldState { 9 | public final int nextPosition; 10 | public final Field field; 11 | public final Piece holdPiece; 12 | 13 | public NextAndFieldState(GameEngine engine) { 14 | this.nextPosition = engine.nextPieceCount; 15 | this.field = new Field(engine.field); 16 | this.holdPiece = engine.holdPieceObject == null ? null : new Piece(engine.holdPieceObject); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/GamePiece.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | public interface GamePiece { 4 | int getScore(); 5 | 6 | int getWidth(); 7 | 8 | int getHeight(); 9 | 10 | int getX(); 11 | 12 | int getY(); 13 | 14 | int[] getLocation(); 15 | 16 | int[][] getContents(); 17 | 18 | int[] getCursorOffset(); 19 | 20 | double getConveyorYOffset(); 21 | 22 | int getState(); 23 | 24 | int getColour(); 25 | 26 | int[][] getConveyorBoundingBox(); 27 | 28 | int[][][] getCursorBoundingBox(); 29 | 30 | int getPowerup(); 31 | 32 | void setPowerup(int powerup); 33 | 34 | void rotate(); 35 | 36 | void setLocation(int x, int y); 37 | } 38 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/annotations/DebugOps.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.annotations; 2 | 3 | import org.apache.log4j.Logger; 4 | 5 | /** 6 | * Operations which streamline the use of {@link Debug}. 7 | */ 8 | public final class DebugOps { 9 | /** If the passed in object is annotated with {@code Debug}, perform an action. */ 10 | public static void ifDebug(T object, Runnable action) { 11 | if (object.getClass().isAnnotationPresent(Debug.class)) action.run(); 12 | } 13 | 14 | /** Trace an object if the context object is annotated with {@code Debug} */ 15 | public static T trace(Logger log, C object, T toTrace) { 16 | ifDebug(object, () -> log.trace(toTrace.toString())); 17 | return toTrace; 18 | } 19 | 20 | // Don't need to instantiate this class. 21 | private DebugOps() {} 22 | } 23 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/gemswap/ScoreEvent.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.gemswap; 2 | 3 | public class ScoreEvent { 4 | private final int scoreValue; 5 | private final int x; 6 | private final int y; 7 | private final int origin; 8 | private final int colour; 9 | 10 | public ScoreEvent(int scoreValue, int x, int y, int origin, int colour) { 11 | this.scoreValue = scoreValue; 12 | this.x = x; 13 | this.y = y; 14 | this.origin = origin; 15 | this.colour = colour; 16 | } 17 | 18 | public int getColour() { 19 | return colour; 20 | } 21 | 22 | public int getOrigin() { 23 | return origin; 24 | } 25 | 26 | public int getScoreValue() { 27 | return scoreValue; 28 | } 29 | 30 | public int getX() { 31 | return x; 32 | } 33 | 34 | public int getY() { 35 | return y; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/annotations/Debug.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.annotations; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Annotation used for marking that an object instance contains debug code. 7 | * Due to the way Java annotations work, the usage of the annotation looks something like: 8 | * 9 | *
10 |  *     final Object foo = new @Debug Object() {};
11 |  *     foo.getClass().isAnnotationPresent(Debug.class); // true
12 | * 13 | * Which does create an anonymous class instance of the type you are trying to debug. 14 | * This means the {@code @Debug} annotation WILL NOT WORK with {@code final} 15 | * classes, as you will not be able to make an anonymous instance of that class. 16 | *

17 | * Use {@link DebugOps} for helpers for using this annotation, and ensure to remove all 18 | * instances of this annotation being used before making a public release! 19 | */ 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target({ ElementType.TYPE, ElementType.TYPE_USE }) 22 | public @interface Debug {} 23 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/Box.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | import java.util.function.Function; 4 | 5 | /** A generic mutable box for one value. */ 6 | public class Box { 7 | private V value; 8 | 9 | public Box(V value) { 10 | this.setValue(value); 11 | } 12 | 13 | public Box map(Function func) { 14 | return new Box<>(func.apply(value)); 15 | } 16 | 17 | public Box ap(Box> func) { 18 | return new Box<>(func.value.apply(value)); 19 | } 20 | 21 | public Box flatMap(Function> func) { 22 | return func.apply(value); 23 | } 24 | 25 | public void modify(Function func) { 26 | setValue(func.apply(getValue())); 27 | } 28 | 29 | public void share(Box vw) { 30 | this.setValue(vw.getValue()); 31 | } 32 | 33 | public V getValue() { 34 | return value; 35 | } 36 | 37 | public void setValue(V value) { 38 | this.value = value; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/ObjectAlignment.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | /** Object alignment selector enum. Represents which corner or midpoint is used as an anchor. */ 4 | public enum ObjectAlignment { 5 | /** Object is drawn downwards and to the right of the coordinate. */ 6 | TOP_LEFT, 7 | 8 | /** Object is drawn downwards and to both sides of the coordinate. */ 9 | TOP_MIDDLE, 10 | 11 | /** Object is drawn downwards and to the left of the coordinate. */ 12 | TOP_RIGHT, 13 | 14 | /** Object is drawn outwards and to the right of the coordinate. */ 15 | MIDDLE_LEFT, 16 | 17 | /** Object is drawn outwards centred on the coordinate. */ 18 | MIDDLE_MIDDLE, 19 | 20 | /** Object is drawn outwards and to the left of the coordinate. */ 21 | MIDDLE_RIGHT, 22 | 23 | /** Object is drawn upwards and to the right of the coordinate. */ 24 | BOTTOM_LEFT, 25 | 26 | /** Object is drawn upwards and to both sides of the coordinate. */ 27 | BOTTOM_MIDDLE, 28 | 29 | /** Object is drawn upwards and to the left of the coordinate. */ 30 | BOTTOM_RIGHT 31 | } -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/twothousandandfortyeight/GridSpace2048.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.twothousandandfortyeight; 2 | 3 | public class GridSpace2048 { 4 | private int value; 5 | private boolean merged; 6 | 7 | public GridSpace2048(int value) { 8 | this.value = value; 9 | this.merged = false; 10 | } 11 | 12 | public GridSpace2048(int value, boolean merged) { 13 | this.value = value; 14 | this.merged = merged; 15 | } 16 | 17 | public GridSpace2048() { 18 | this(0); 19 | } 20 | 21 | public boolean isEqual(GridSpace2048 gridSpace) { 22 | return value == gridSpace.getValue(); 23 | } 24 | 25 | public int getValue() { 26 | return value; 27 | } 28 | 29 | public void setValue(int value) { 30 | this.value = value; 31 | } 32 | 33 | public boolean getMerged() { 34 | return merged; 35 | } 36 | 37 | public void setMerged(boolean merged) { 38 | this.merged = merged; 39 | } 40 | 41 | public GridSpace2048 clone() { 42 | return new GridSpace2048(value, merged); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/ArrayRandomiser.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.Random; 6 | import mu.nu.nullpo.gui.swing.ResourceHolderSwing; 7 | import org.apache.log4j.Logger; 8 | // import java.util.Iterator; 9 | // import java.util.List; 10 | 11 | public class ArrayRandomiser { 12 | /** 13 | * Log 14 | */ 15 | static Logger log = Logger.getLogger(ResourceHolderSwing.class); 16 | // Internal randomiser 17 | private final Random randomiser; 18 | 19 | public ArrayRandomiser() { 20 | randomiser = new Random(); 21 | } 22 | 23 | public ArrayRandomiser(long seed) { 24 | randomiser = new Random(seed); 25 | } 26 | 27 | public int[] permute(int[] arr) { 28 | int[] h = arr.clone(); 29 | 30 | ArrayList copy = new ArrayList(); 31 | for (int integer : arr) { 32 | copy.add(integer); 33 | } 34 | 35 | Collections.shuffle(copy, randomiser); 36 | 37 | for (int i = 0; i < copy.size(); i++) { 38 | h[i] = copy.get(i).intValue(); 39 | } 40 | 41 | return h; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/tuples/IntPair.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types.tuples; 2 | 3 | import java.util.Objects; 4 | import java.util.function.IntFunction; 5 | 6 | /** Specialized instance of pairs for primitive integers. */ 7 | public class IntPair { 8 | public static IntPair of(int valL, int valR) { 9 | return new IntPair(valL, valR); 10 | } 11 | 12 | // Instance data: 13 | public final int valL; 14 | public final int valR; 15 | 16 | private IntPair(int valL, int valR) { 17 | this.valL = valL; 18 | this.valR = valR; 19 | } 20 | 21 | public Pair boxed() { 22 | return Pair.of(valL, valR); 23 | } 24 | 25 | public Pair mapToPair(IntFunction funcL, IntFunction funcR) { 26 | return Pair.of(funcL.apply(valL), funcR.apply(valR)); 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (o == null || getClass() != o.getClass()) return false; 32 | IntPair intPair = (IntPair) o; 33 | return valL == intPair.valL && valR == intPair.valR; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return Objects.hash(valL, valR); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/tuples/FloatPair.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types.tuples; 2 | 3 | import java.util.Objects; 4 | import zeroxfc.nullpo.custom.libs.types.FloatFunction; 5 | 6 | /** Specialized instance of pairs for primitive floats. */ 7 | public class FloatPair { 8 | public static FloatPair of(float valL, float valR) { 9 | return new FloatPair(valL, valR); 10 | } 11 | 12 | // Instance data: 13 | public final float valL; 14 | public final float valR; 15 | 16 | private FloatPair(float valL, float valR) { 17 | this.valL = valL; 18 | this.valR = valR; 19 | } 20 | 21 | public Pair boxed() { 22 | return Pair.of(valL, valR); 23 | } 24 | 25 | public Pair mapToPair(FloatFunction funcL, FloatFunction funcR) { 26 | return Pair.of(funcL.apply(valL), funcR.apply(valR)); 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (o == null || getClass() != o.getClass()) return false; 32 | FloatPair floatPair = (FloatPair) o; 33 | return valL == floatPair.valL && valR == floatPair.valR; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return Objects.hash(valL, valR); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/tuples/DoublePair.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types.tuples; 2 | 3 | import java.util.Objects; 4 | import java.util.function.DoubleFunction; 5 | 6 | /** Specialized instance of pairs for primitive doubles. */ 7 | public class DoublePair { 8 | public static DoublePair of(double valL, double valR) { 9 | return new DoublePair(valL, valR); 10 | } 11 | 12 | // Instance data: 13 | public final double valL; 14 | public final double valR; 15 | 16 | private DoublePair(double valL, double valR) { 17 | this.valL = valL; 18 | this.valR = valR; 19 | } 20 | 21 | public Pair boxed() { 22 | return Pair.of(valL, valR); 23 | } 24 | 25 | public Pair mapToPair(DoubleFunction funcL, DoubleFunction funcR) { 26 | return Pair.of(funcL.apply(valL), funcR.apply(valR)); 27 | } 28 | 29 | @Override 30 | public boolean equals(Object o) { 31 | if (o == null || getClass() != o.getClass()) return false; 32 | DoublePair doublePair = (DoublePair) o; 33 | return valL == doublePair.valL && valR == doublePair.valR; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return Objects.hash(valL, valR); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/gemswap/Gem.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.gemswap; 2 | 3 | import java.util.ArrayList; 4 | 5 | public interface Gem { 6 | int getID(); 7 | 8 | int getColour(); 9 | 10 | void setColour(int colour); 11 | 12 | int[] getLocation(); 13 | 14 | boolean getRecentSwap(); 15 | 16 | void setRecentSwap(boolean isRecentSwap); 17 | 18 | boolean getRecentFall(); 19 | 20 | void setRecentFall(boolean isRecentFall); 21 | 22 | boolean getMatchedHorizontal(); 23 | 24 | void setMatchedHorizontal(boolean isMatched); 25 | 26 | boolean getMatchedVertical(); 27 | 28 | void setMatchedVertical(boolean isMatched); 29 | 30 | boolean getSpecial(); 31 | 32 | boolean getActionConducted(); 33 | 34 | void setActionConducted(boolean isConduted); 35 | 36 | boolean getDestroy(); 37 | 38 | void setDestroy(boolean shouldDestroy); 39 | 40 | void setLocation(int x, int y); 41 | 42 | Gem getSelf(); 43 | 44 | // Modifies field. This method is reserved for special gems. 45 | /* 46 | * TODO: Find a way to resolve special gem creation if two 47 | * fall at the same time to complete its match type. 48 | */ 49 | int conductAction(GemField field, int[] args, ArrayList eventList); 50 | } 51 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/tuples/Pair.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types.tuples; 2 | 3 | import java.util.Objects; 4 | import java.util.function.ToDoubleFunction; 5 | import java.util.function.ToIntFunction; 6 | import zeroxfc.nullpo.custom.libs.types.ToFloatFunction; 7 | 8 | /** Generic pair of objects. */ 9 | public final class Pair { 10 | public static Pair of(L valL, R valR) { 11 | return new Pair<>(valL, valR); 12 | } 13 | 14 | // Instance data: 15 | public final L valL; 16 | public final R valR; 17 | 18 | private Pair(L valL, R valR) { 19 | this.valL = valL; 20 | this.valR = valR; 21 | } 22 | 23 | public IntPair mapToIntPair(ToIntFunction funcL, ToIntFunction funcR) { 24 | return IntPair.of(funcL.applyAsInt(valL), funcR.applyAsInt(valR)); 25 | } 26 | 27 | public DoublePair mapToDoublePair(ToDoubleFunction funcL, ToDoubleFunction funcR) { 28 | return DoublePair.of(funcL.applyAsDouble(valL), funcR.applyAsDouble(valR)); 29 | } 30 | 31 | public FloatPair mapToFloatPair(ToFloatFunction funcL, ToFloatFunction funcR) { 32 | return FloatPair.of(funcL.applyAsFloat(valL), funcR.applyAsFloat(valR)); 33 | } 34 | 35 | @Override 36 | public boolean equals(Object o) { 37 | if (o == null || getClass() != o.getClass()) return false; 38 | Pair pair = (Pair) o; 39 | return Objects.equals(valL, pair.valL) && Objects.equals(valR, pair.valR); 40 | } 41 | 42 | @Override 43 | public int hashCode() { 44 | return Objects.hash(valL, valR); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/wallkick/SuperRandomWallkick.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.wallkick; 2 | 3 | import mu.nu.nullpo.game.component.Controller; 4 | import mu.nu.nullpo.game.component.Field; 5 | import mu.nu.nullpo.game.component.Piece; 6 | import mu.nu.nullpo.game.component.WallkickResult; 7 | import mu.nu.nullpo.game.subsystem.wallkick.StandardWallkick; 8 | import zeroxfc.nullpo.custom.libs.ArrayRandomiser; 9 | 10 | public class SuperRandomWallkick extends StandardWallkick { 11 | /* 12 | * Wallkick 13 | */ 14 | public WallkickResult executeWallkick(int x, int y, int rtDir, int rtOld, int rtNew, boolean allowUpward, Piece piece, Field field, Controller ctrl) { 15 | int[][][] kicktable = getKickTable(x, y, rtDir, rtOld, rtNew, allowUpward, piece, field, ctrl); 16 | 17 | int[] arr = new int[kicktable[rtOld].length]; 18 | for (int i = 0; i < arr.length; i++) { 19 | arr[i] = i; 20 | } 21 | 22 | int v = 0; 23 | for (int i : ctrl.buttonTime) { 24 | v += i; 25 | } 26 | 27 | ArrayRandomiser randomiser = new ArrayRandomiser(rtOld + rtNew + piece.id + field.getHighestBlockY() + v); 28 | arr = randomiser.permute(arr); 29 | 30 | for (int i : arr) { 31 | int x2 = kicktable[rtOld][i][0]; 32 | int y2 = kicktable[rtOld][i][1]; 33 | 34 | if (piece.big) { 35 | x2 *= 2; 36 | y2 *= 2; 37 | } 38 | 39 | if ((y2 >= 0) || (allowUpward)) { 40 | if (!piece.checkCollision(x + x2, y + y2, rtNew, field)) { 41 | return new WallkickResult(x2, y2, rtNew); 42 | } 43 | } 44 | } 45 | 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/RuntimeImage.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | /** Abstract representation of an image the game uses, independent of runtime. */ 4 | public abstract class RuntimeImage { 5 | public final I image; 6 | 7 | protected RuntimeImage(I image) { 8 | this.image = image; 9 | } 10 | 11 | /** Get width of image. */ 12 | public abstract int getWidth(); 13 | 14 | /** Get height of image. */ 15 | public abstract int getHeight(); 16 | 17 | /** Slick runtime image. */ 18 | public static class Slick extends RuntimeImage { 19 | public Slick(org.newdawn.slick.Image image) { 20 | super(image); 21 | } 22 | 23 | @Override 24 | public int getWidth() { 25 | return image.getWidth(); 26 | } 27 | 28 | @Override 29 | public int getHeight() { 30 | return image.getHeight(); 31 | } 32 | } 33 | 34 | /** Swing runtime image. */ 35 | public static class Swing extends RuntimeImage { 36 | public Swing(java.awt.Image image) { 37 | super(image); 38 | } 39 | 40 | @Override 41 | public int getWidth() { 42 | return image.getWidth(null); 43 | } 44 | 45 | @Override 46 | public int getHeight() { 47 | return image.getHeight(null); 48 | } 49 | } 50 | 51 | /** SDL runtime image. */ 52 | public static class SDL extends RuntimeImage { 53 | public SDL(sdljava.video.SDLSurface image) { 54 | super(image); 55 | } 56 | 57 | @Override 58 | public int getWidth() { 59 | return image.getHeight(); 60 | } 61 | 62 | @Override 63 | public int getHeight() { 64 | return image.getHeight(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/seasons/RewindBlock.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.seasons; 2 | 3 | import mu.nu.nullpo.game.component.Block; 4 | import mu.nu.nullpo.game.event.EventReceiver; 5 | import zeroxfc.nullpo.custom.libs.DoubleVector; 6 | import zeroxfc.nullpo.custom.libs.Interpolation; 7 | import zeroxfc.nullpo.custom.libs.RendererExtension; 8 | import zeroxfc.nullpo.custom.libs.types.ObjectAlignment; 9 | 10 | public class RewindBlock { 11 | private final int maxLife; 12 | private int life; 13 | 14 | private final DoubleVector position; 15 | private final DoubleVector velocity; 16 | private final DoubleVector acceleration; 17 | 18 | private final Block block; 19 | 20 | public RewindBlock(int maxLife, int startLife, DoubleVector position, DoubleVector velocity, DoubleVector acceleration, Block block) { 21 | this.maxLife = maxLife; 22 | this.life = startLife; 23 | 24 | this.position = position; 25 | this.velocity = velocity; 26 | this.acceleration = acceleration; 27 | this.block = new Block(block); 28 | } 29 | 30 | public boolean update() { 31 | if (++life <= 0) return life >= maxLife; 32 | 33 | velocity.add(acceleration); 34 | position.add(velocity); 35 | 36 | return life >= maxLife; 37 | } 38 | 39 | public void draw(RendererExtension extension, EventReceiver receiver) { 40 | if (life <= 0) return; 41 | 42 | extension.drawAlignedScaledBlock( 43 | receiver, 44 | (int) position.getX(), (int) position.getY(), 45 | ObjectAlignment.MIDDLE_MIDDLE, 46 | block.getDrawColor(), 47 | block.skin, 48 | block.getAttribute(Block.BLOCK_ATTRIBUTE_BONE), 49 | 0f, 50 | block.alpha, 51 | Interpolation.lerp(1f, 1.5f, life / (double) maxLife), 52 | block.attribute 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/WeightedRandomiser.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs; 2 | 3 | import java.util.Random; 4 | 5 | public class WeightedRandomiser { 6 | private final Random localRandom; 7 | private int[] results; 8 | private int[] cumulativeWeightList; 9 | private int maxWeight; 10 | 11 | public WeightedRandomiser(int[] weightArr, long seed) { 12 | int numberOfZeroes = 0; 13 | for (int i : weightArr) { 14 | if (i == 0) numberOfZeroes++; 15 | } 16 | 17 | cumulativeWeightList = new int[weightArr.length - numberOfZeroes]; 18 | results = new int[weightArr.length - numberOfZeroes]; 19 | maxWeight = 0; 20 | 21 | int ctr = 0; 22 | for (int i = 0; i < weightArr.length; i++) { 23 | if (weightArr[i] != 0) { 24 | maxWeight += weightArr[i]; 25 | cumulativeWeightList[ctr] = maxWeight; 26 | results[ctr] = i; 27 | 28 | ctr++; 29 | } 30 | } 31 | 32 | localRandom = new Random(seed); 33 | } 34 | 35 | public void setWeights(int[] weightArr) { 36 | int numberOfZeroes = 0; 37 | for (int i : weightArr) { 38 | if (i == 0) numberOfZeroes++; 39 | } 40 | 41 | cumulativeWeightList = new int[weightArr.length - numberOfZeroes]; 42 | results = new int[weightArr.length - numberOfZeroes]; 43 | maxWeight = 0; 44 | 45 | int ctr = 0; 46 | for (int i = 0; i < weightArr.length; i++) { 47 | if (weightArr[i] != 0) { 48 | maxWeight += weightArr[i]; 49 | cumulativeWeightList[ctr] = maxWeight; 50 | results[ctr] = i; 51 | 52 | ctr++; 53 | } 54 | } 55 | } 56 | 57 | public int getMax() { 58 | return results[results.length - 1]; 59 | } 60 | 61 | public int nextInt() { 62 | int gVal = localRandom.nextInt(maxWeight) + 1; 63 | int result = 0; 64 | for (int i = 0; i < cumulativeWeightList.length; i++) { 65 | if (cumulativeWeightList[i] >= gVal) { 66 | result = i; 67 | break; 68 | } 69 | } 70 | 71 | return results[result]; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/wallkick/ClassicLenientWallkick.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.wallkick; 2 | 3 | import mu.nu.nullpo.game.component.Controller; 4 | import mu.nu.nullpo.game.component.Field; 5 | import mu.nu.nullpo.game.component.Piece; 6 | import mu.nu.nullpo.game.component.WallkickResult; 7 | import mu.nu.nullpo.game.subsystem.wallkick.Wallkick; 8 | 9 | public class ClassicLenientWallkick implements Wallkick { 10 | private static final int[][] BASE_WALLKICK = { 11 | { -1, 0 }, 12 | { 1, 0 }, 13 | { 0, 1 }, 14 | { 0, -1 } 15 | }; 16 | private static final int[][] I_WALLKICK = { 17 | { -1, 0 }, 18 | { 1, 0 }, 19 | { -2, 0 }, 20 | { 2, 0 }, 21 | { 0, 1 }, 22 | { 0, -1 } 23 | }; 24 | 25 | /** 26 | * Execute a wallkick 27 | * 28 | * @param x X-coordinate 29 | * @param y Y-coordinate 30 | * @param rtDir Rotation button used (-1: left rotation, 1: right rotation, 2: 180-degree rotation) 31 | * @param rtOld Direction before rotation 32 | * @param rtNew Direction after rotation 33 | * @param allowUpward If true, upward wallkicks are allowed. 34 | * @param piece Current piece 35 | * @param field Current field 36 | * @param ctrl Button input status (it may be null, when controlled by an AI) 37 | * @return WallkickResult object, or null if you don't want a kick 38 | */ 39 | public WallkickResult executeWallkick(int x, int y, int rtDir, int rtOld, int rtNew, boolean allowUpward, Piece piece, Field field, Controller ctrl) { 40 | int x2, y2; 41 | 42 | int[][] WALLKICK = (piece.id == Piece.PIECE_I) ? I_WALLKICK : BASE_WALLKICK; 43 | 44 | for (int i = 0; i < WALLKICK.length; i++) { 45 | if (rtDir < 0 || rtDir == 2) { 46 | x2 = WALLKICK[i][0]; 47 | } else { 48 | x2 = -WALLKICK[i][0]; 49 | } 50 | y2 = WALLKICK[i][1]; 51 | 52 | if (piece.big) { 53 | x2 *= 2; 54 | y2 *= 2; 55 | } 56 | 57 | if (piece.checkCollision(x + x2, y + y2, rtNew, field) == false) { 58 | return new WallkickResult(x2, y2, rtNew); 59 | } 60 | } 61 | return null; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/wallkick/STX1Wallkick.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.wallkick; 2 | 3 | import mu.nu.nullpo.game.component.Controller; 4 | import mu.nu.nullpo.game.component.Field; 5 | import mu.nu.nullpo.game.component.Piece; 6 | import mu.nu.nullpo.game.component.WallkickResult; 7 | import mu.nu.nullpo.game.subsystem.wallkick.Wallkick; 8 | 9 | public class STX1Wallkick implements Wallkick { 10 | // These kicks are for CW. CCW just inverts the X direction. 11 | private static final int[][] BASE_ROTATION_KICKS = { 12 | { -1, 0 }, { 1, 0 }, 13 | { 0, 1 }, { -1, 1 }, { 1, 1 }, 14 | { 0, -1 }, 15 | }; 16 | 17 | // Check rtOld for if the I-piece is flat or not. Same comment regarding direction. 18 | private static final int[][] CW_ROTATION_KICKS_I_PIECE_FLAT = { 19 | { -1, 0 }, { 1, 0 }, 20 | { 0, 1 }, { -1, 1 }, { 1, 1 }, 21 | { 0, 2 }, 22 | { 0, -2 } 23 | }; 24 | 25 | // Same comment regarding direction. 26 | private static final int[][] CW_ROTATION_KICKS_I_PIECE_VERTICAL = { 27 | { -1, 0 }, { 1, 0 }, 28 | { 0, 1 }, { -1, 1 }, { 1, 1 }, 29 | { -2, 0 }, { 2, 0 } 30 | }; 31 | 32 | @Override 33 | public WallkickResult executeWallkick(int x, int y, int rtDir, int rtOld, int rtNew, boolean allowUpward, Piece piece, Field field, Controller ctrl) { 34 | final WallkickResult baseKick = getWallkickResult(x, y, rtDir, rtNew, piece, field, BASE_ROTATION_KICKS); 35 | if (baseKick != null) return baseKick; 36 | 37 | if (piece.id != Piece.PIECE_I) return null; 38 | 39 | final int[][] selectedKicksI = rtOld == Piece.DIRECTION_UP || rtOld == Piece.DIRECTION_DOWN ? CW_ROTATION_KICKS_I_PIECE_FLAT : CW_ROTATION_KICKS_I_PIECE_VERTICAL; 40 | return getWallkickResult(x, y, rtDir, rtNew, piece, field, selectedKicksI); 41 | } 42 | 43 | private WallkickResult getWallkickResult(int x, int y, int rtDir, int rtNew, Piece piece, Field field, int[][] selectedKicksI) { 44 | for (int[] basicTest : selectedKicksI) { 45 | int tX = rtDir == -1 ? -basicTest[0] : basicTest[0]; 46 | int tY = basicTest[1]; 47 | 48 | if (piece.big) { 49 | tX *= 2; 50 | tY *= 2; 51 | } 52 | 53 | if (!piece.checkCollision(x + tX, y + tY, rtNew, field)) { 54 | return new WallkickResult(tX, tY, rtNew); 55 | } 56 | } 57 | 58 | return null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/gemswap/Lightning.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.gemswap; 2 | 3 | import java.util.Random; 4 | import mu.nu.nullpo.game.event.EventReceiver; 5 | import mu.nu.nullpo.game.play.GameEngine; 6 | import zeroxfc.nullpo.custom.libs.effects.Effect; 7 | import zeroxfc.nullpo.custom.libs.Interpolation; 8 | import zeroxfc.nullpo.custom.libs.CustomResourceHolder; 9 | 10 | public class Lightning implements Effect { 11 | public static final int MAX_LIFETIME = 120; 12 | 13 | private final int[] locationStart; 14 | private final int[] locationEnd; 15 | private final Random localRandom; 16 | private int lifeTime; 17 | 18 | public Lightning(int[] startPoint, int[] endPoint, long seed) { 19 | locationStart = startPoint; 20 | locationEnd = endPoint; 21 | lifeTime = 0; 22 | 23 | localRandom = new Random(seed); 24 | } 25 | 26 | @Override 27 | public void update() { 28 | lifeTime++; 29 | } 30 | 31 | @Override 32 | public boolean shouldNull() { 33 | return lifeTime >= MAX_LIFETIME; 34 | } 35 | 36 | @Override 37 | public void draw(GameEngine engine, EventReceiver receiver, int playerID, int[] args, CustomResourceHolder customHolder) { 38 | if (customHolder != null) { 39 | for (int i = 0; i <= args[0]; i++) { 40 | int[] drawLocation = new int[] { 41 | Interpolation.lerp(locationStart[0], locationEnd[0], (double) i / args[0]), 42 | Interpolation.lerp(locationStart[1], locationEnd[1], (double) i / args[0]) 43 | }; 44 | 45 | customHolder.drawImage(engine, "particle", drawLocation[0] + (localRandom.nextInt(9) - 4), drawLocation[1] + (localRandom.nextInt(9) - 4), 0, 0, 2, 2, 160, 255, 255, 255, 1.0f); 46 | customHolder.drawImage(engine, "particle", drawLocation[0] + (localRandom.nextInt(9) - 4), drawLocation[1] + (localRandom.nextInt(9) - 4), 0, 0, 2, 2, 200, 255, 255, 255, 1.0f); 47 | customHolder.drawImage(engine, "particle", drawLocation[0] + (localRandom.nextInt(9) - 4), drawLocation[1] + (localRandom.nextInt(9) - 4), 0, 0, 2, 2, 240, 255, 255, 255, 1.0f); 48 | customHolder.drawImage(engine, "particle", drawLocation[0] + (localRandom.nextInt(9) - 4), drawLocation[1] + (localRandom.nextInt(9) - 4), 0, 0, 2, 2, 255, 255, 255, 255, 1.0f); 49 | } 50 | } else { 51 | return; 52 | } 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/LevelTableBuilder.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs; 2 | 3 | import java.util.NavigableMap; 4 | import java.util.TreeMap; 5 | import java.util.function.IntFunction; 6 | import org.apache.log4j.Logger; 7 | 8 | /** 9 | * Helper utility for building level-based value tables. Essentially a generified version of 10 | * SpeedTableBuilder but for things other than SpeedParam instances. 11 | *
12 | * Use the static createNew method to start creating a table. 13 | */ 14 | public final class LevelTableBuilder { 15 | private static final Logger log = Logger.getLogger(LevelTableBuilder.class); 16 | 17 | private final NavigableMap levelValues; 18 | private final LevelTableBuilder outer = this; 19 | 20 | public static LevelTableBuilder.ModifiableLevelTable createNew() { 21 | return new LevelTableBuilder().new ModifiableLevelTable(); 22 | } 23 | 24 | private LevelTableBuilder() { 25 | levelValues = new TreeMap<>(); 26 | } 27 | 28 | private void verifyLevel(int changeLevel) { 29 | if (levelValues.isEmpty()) return; 30 | 31 | final int maxLevel = levelValues.descendingKeySet().first(); 32 | if (maxLevel <= changeLevel) return; 33 | 34 | final RuntimeException exc = new IllegalArgumentException("Level change is lower than or equal to previous level change: " + maxLevel + " -> " + changeLevel); 35 | 36 | log.error(exc); 37 | throw exc; 38 | } 39 | 40 | public final class ModifiableLevelTable { 41 | private ModifiableLevelTable() {} 42 | 43 | public ModifiableLevelTable clear() { 44 | levelValues.clear(); 45 | return this; 46 | } 47 | 48 | public ModifiableLevelTable addValue(T value, int changeLevel) { 49 | verifyLevel(changeLevel); 50 | levelValues.put(changeLevel, value); 51 | 52 | return this; 53 | } 54 | 55 | public FinalizedLevelTable addTerminalValue(T value) { 56 | addValue(value, Integer.MAX_VALUE); 57 | return outer.new FinalizedLevelTable(); 58 | } 59 | } 60 | 61 | public final class FinalizedLevelTable { 62 | private FinalizedLevelTable() {} 63 | 64 | public IntFunction buildLevelTable() { 65 | final TreeMap finalizedTable = new TreeMap<>(levelValues); 66 | return level -> finalizedTable.higherEntry(level).getValue(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | **There are not many rules, but they are the following:** 4 | 5 | 1. **Do not modify the vanilla source files that are not in this repository, even if it's to make some of its fields public.** This is to **maintain cross-mod compatibility**. If necessary, use reflection, wrapper classes or extension classes. This is the most important guideline. We do not want to 'lock-in' users to only using ModePile and no other mods. 6 | 2. **If making engine-dependent methods, make sure as much equal support is to be given to all three engines (Slick, Swing and SDL) as possible.** This is to provide an equal experience to every user, no matter their choice of engine to run. If some features/functionality is impossible (or far too slow) to implement in a certain engine, do not worry too much about skipping engine parity. 7 | * If any one engine needs to be prioritised for a feature, ensure it at least works in the **Slick** engine frontend, as that is the most commonly-used frontend for NullpoMino. 8 | 3. **Javadoc comments are essential on complex libraries.** Modes and mode-specific objects can be left alone at the contributor's discretion, but an explanation must be given if asked. 9 | 4. **If making your own modes, libraries or other class files to go into this pack, make your own root folder in the *src* directory (e.g. if you want your root to be *johndoe*, make a *johndoe* package root in the *src* folder).** This is for organisation purposes, and to give credit where credit is due. This also applies to any custom SFX that you use, but not custom images or BGM. 10 | * It is recommended that your packages follow the `[root].nullpo.custom` format that the existing packages use, with `modes` as the next subpackage for gamemodes and `libs` for library code. Any more packages underneath the two is up to your discretion. 11 | 12 | **There are also a few optional guidelines that serve to make other contributors' lives easier:** 13 | 14 | 1. **Make simpler/less-specific overloads of methods in libraries if existing methods are complicated.** This makes general-use cases easier to type and debug. 15 | 2. **When making *onCustom*-centric modes, try to use the structure similar to that in *GameEngine*.** This makes code easier to organise and debug. 16 | 17 | **Style guide:** 18 | 19 | There is no specific style guideline to follow, but in general, 4-space indents and the OTBS style of braces are preferred. 20 | 21 | ```java 22 | public int foo() { 23 | return 0; // Indented with 4 space (\x20, 32d) characters, not tabs. 24 | } 25 | ``` 26 | 27 | Of course: 28 | 29 | - Be polite. 30 | - Be efficient. 31 | - Have a plan to fix every bug you find. 32 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/ModeSettings.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | import java.util.function.Supplier; 4 | import mu.nu.nullpo.game.event.EventReceiver; 5 | import mu.nu.nullpo.game.play.GameManager; 6 | import mu.nu.nullpo.util.CustomProperties; 7 | import zeroxfc.nullpo.custom.libs.ProfileProperties; 8 | 9 | /** Representation of an object that holds the settings that a mode uses. */ 10 | public abstract class ModeSettings { 11 | private final String propRoot; 12 | public final ProfileProperties playerProperties; 13 | 14 | protected ModeSettings(String propRoot, ProfileProperties playerProperties) { 15 | this.propRoot = propRoot; 16 | this.playerProperties = playerProperties; 17 | } 18 | 19 | // Construct a property path for settings and rankings. 20 | protected final String propPath(Object... path) { 21 | final StringBuilder sb = new StringBuilder(propRoot); 22 | for (Object obj : path) sb.append('.').append(obj.toString()); 23 | 24 | return sb.toString(); 25 | } 26 | 27 | public abstract void loadSetting(CustomProperties prop, boolean isReplay); 28 | public abstract void saveSetting(CustomProperties prop, boolean forReplay); 29 | 30 | public abstract void loadSettingPlayer(ProfileProperties prop); 31 | public abstract void saveSettingPlayer(ProfileProperties prop); 32 | 33 | public abstract void loadRanking(GameManager owner, String ruleName); 34 | public abstract void saveRanking(GameManager owner, String ruleName); 35 | 36 | public abstract void loadRankingPlayer(ProfileProperties prop, String ruleName); 37 | public abstract void saveRankingPlayer(ProfileProperties prop, String ruleName); 38 | 39 | public void commitSettingAndRank(EventReceiver receiver, GameManager owner) { 40 | receiver.saveModeConfig(owner.modeConfig); 41 | } 42 | 43 | public void commitPlayerSettingAndRank(ProfileProperties playerProperties) { 44 | if (!playerProperties.isLoggedIn()) return; 45 | playerProperties.saveProfileConfig(); 46 | } 47 | 48 | // Ranking order helper. 49 | protected enum Order { 50 | LT(-1), EQ(0), GT(1); 51 | public final int compareValue; 52 | 53 | public static Order fromCompare(int cmp) { 54 | if (cmp < 0) return LT; 55 | else if (cmp > 0) return GT; 56 | else return EQ; 57 | } 58 | 59 | Order(int compareValue) { 60 | this.compareValue = compareValue; 61 | } 62 | 63 | public Order fold(Supplier other) { 64 | if (this == EQ) return other.get(); 65 | else return this; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/backgroundtypes/BackgroundNoAnim.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.backgroundtypes; 2 | 3 | import mu.nu.nullpo.game.play.GameEngine; 4 | import zeroxfc.nullpo.custom.libs.CustomResourceHolder; 5 | 6 | public class BackgroundNoAnim extends AnimatedBackgroundHook { 7 | // private CustomResourceHolder customHolder; 8 | 9 | { 10 | ID = AnimatedBackgroundHook.ANIMATION_NONE; 11 | setImageName("localBG"); 12 | } 13 | 14 | /** 15 | * Almost redundant background. 16 | */ 17 | public BackgroundNoAnim(int bgNumber) { 18 | if (bgNumber < 0 || bgNumber > 19) bgNumber = 0; 19 | 20 | customHolder = new CustomResourceHolder(); 21 | customHolder.loadImage("res/graphics/back" + bgNumber + ".png", imageName); 22 | 23 | log.debug("Non-custom static background (" + bgNumber + ") created."); 24 | } 25 | 26 | public BackgroundNoAnim(String filePath) { 27 | customHolder = new CustomResourceHolder(); 28 | customHolder.loadImage(filePath, imageName); 29 | 30 | log.debug("Custom static background created (File Path: " + filePath + ")."); 31 | } 32 | 33 | @Override 34 | public void update() { 35 | // EMPTY 36 | } 37 | 38 | @Override 39 | public void reset() { 40 | // EMPTY 41 | } 42 | 43 | @Override 44 | public void draw(GameEngine engine, int playerID) { 45 | customHolder.drawImage(engine, imageName, 0, 0); 46 | } 47 | 48 | @Override 49 | public void setBG(int bg) { 50 | customHolder.loadImage("res/graphics/back" + bg + ".png", imageName); 51 | log.debug("Non-custom static background modified (New BG: " + bg + ")."); 52 | } 53 | 54 | @Override 55 | public void setBG(String filePath) { 56 | customHolder.loadImage(filePath, imageName); 57 | log.debug("Custom static background modified (New File Path: " + filePath + ")."); 58 | } 59 | 60 | /** 61 | * Allows the hot-swapping of pre-loaded BGs from a storage instance of a CustomResourceHolder. 62 | * 63 | * @param holder Storage instance 64 | * @param name Image name 65 | */ 66 | @Override 67 | public void setBGFromHolder(CustomResourceHolder holder, String name) { 68 | customHolder.putImageAt(holder.getImageAt(name), imageName); 69 | log.debug("Custom static background modified (New Image Reference: " + name + ")."); 70 | } 71 | 72 | /** 73 | * This last one is important. In the case that any of the child types are used, it allows identification. 74 | * The identification can be used to allow casting during operations. 75 | * 76 | * @return Identification number of child class. 77 | */ 78 | @Override 79 | public int getID() { 80 | return ID; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/PieceFactory.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | public class PieceFactory { 4 | /** 5 | * Pieces Available 6 | */ 7 | public static final int PIECE_I1 = 0, 8 | PIECE_I2 = 1, 9 | PIECE_I3 = 2, 10 | PIECE_L3 = 3, 11 | PIECE_I4 = 4, 12 | PIECE_L4 = 5, 13 | PIECE_J4 = 6, 14 | PIECE_S4 = 7, 15 | PIECE_Z4 = 8, 16 | PIECE_O4 = 9, 17 | PIECE_T4 = 10, 18 | PIECE_P5 = 11, 19 | PIECE_Q5 = 12, 20 | PIECE_U5 = 13, 21 | PIECE_X5 = 14, 22 | PIECE_S5 = 15, 23 | PIECE_Z5 = 16, 24 | PIECE_Stairs6 = 17, 25 | PIECE_Cross6 = 18; 26 | 27 | public static final int PIECE_COUNT = 19; 28 | 29 | /** 30 | * Creates a piece. 31 | * 32 | * @param id Piece ID. Use one of the static IDs in this class. 33 | * @param x Pixel X-coordinate. 34 | * @param y Pixel Y-coordinate. 35 | * @return The piece, whose top-left located at (x, y) in the pixel grid. 36 | */ 37 | public static GamePiece getPiece(int id, int x, int y) { 38 | switch (id) { 39 | case PIECE_I1: 40 | return new I1(x, y); 41 | case PIECE_I2: 42 | return new I2(x, y); 43 | case PIECE_I3: 44 | return new I3(x, y); 45 | case PIECE_L3: 46 | return new L3(x, y); 47 | case PIECE_I4: 48 | return new I4(x, y); 49 | case PIECE_L4: 50 | return new L4(x, y); 51 | case PIECE_J4: 52 | return new J4(x, y); 53 | case PIECE_S4: 54 | return new S4(x, y); 55 | case PIECE_Z4: 56 | return new Z4(x, y); 57 | case PIECE_O4: 58 | return new O4(x, y); 59 | case PIECE_T4: 60 | return new T4(x, y); 61 | case PIECE_P5: 62 | return new P5(x, y); 63 | case PIECE_Q5: 64 | return new Q5(x, y); 65 | case PIECE_U5: 66 | return new U5(x, y); 67 | case PIECE_X5: 68 | return new X5(x, y); 69 | case PIECE_S5: 70 | return new S5(x, y); 71 | case PIECE_Z5: 72 | return new Z5(x, y); 73 | case PIECE_Stairs6: 74 | return new Stairs6(x, y); 75 | case PIECE_Cross6: 76 | return new Cross6(x, y); 77 | default: 78 | return null; 79 | } 80 | } 81 | 82 | public static GamePiece getPiece(int id, int x, int y, int powerUp) { 83 | GamePiece piece = getPiece(id, x, y); 84 | piece.setPowerup(powerUp); 85 | 86 | return piece; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/effects/ScorePopup.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.effects; 2 | 3 | import mu.nu.nullpo.game.event.EventReceiver; 4 | import mu.nu.nullpo.game.play.GameEngine; 5 | import zeroxfc.nullpo.custom.libs.CustomResourceHolder; 6 | 7 | public class ScorePopup implements Effect { 8 | private static final int MAX_TIME_FULL_SIZE = 90; 9 | private static final int MAX_LIFETIME = 120; 10 | private static final int TIME_SIZE_STABLE = 60; 11 | private static final double THREEpiOVERtwo = Math.PI * (3.0 / 2.0); 12 | private static final double piOVERtwo = Math.PI * (1.0 / 2.0); 13 | 14 | private final String value; 15 | private final float baseDim; 16 | private final float baseSize; 17 | private final int[] location; 18 | private final int colour; 19 | private int lifeTime; 20 | private float size; 21 | private int[] offsets; 22 | 23 | public ScorePopup(int score, int[] position, int colour, float baseSize) { 24 | value = String.valueOf(score); 25 | 26 | location = position; 27 | offsets = new int[2]; 28 | lifeTime = 0; 29 | size = 0f; 30 | this.colour = colour; 31 | this.baseSize = baseSize; 32 | baseDim = baseSize * 16; 33 | } 34 | 35 | @Override 36 | public void update() { 37 | lifeTime++; 38 | 39 | if (lifeTime <= TIME_SIZE_STABLE) { 40 | size = baseSize * (float) (Math.abs(Math.sin(THREEpiOVERtwo * ((double) lifeTime / TIME_SIZE_STABLE)))); 41 | 42 | float baseLength = baseDim * value.length(); 43 | int offsetX = (int) (((baseLength * size)) / 2); 44 | int offsetY = (int) (((baseDim * size)) / 2); 45 | 46 | offsets = new int[] { offsetX, offsetY }; 47 | 48 | if (lifeTime % 2 == 0) location[1] -= 1; 49 | } else if (lifeTime <= MAX_TIME_FULL_SIZE) { 50 | offsets = new int[] { (int) ((baseDim * value.length() * baseSize) / 2), (int) ((baseSize * baseDim) / 2) }; 51 | size = baseSize; 52 | } else { 53 | size = baseSize * (float) (Math.abs(Math.cos(piOVERtwo * ((double) (lifeTime - MAX_TIME_FULL_SIZE) / (MAX_LIFETIME - MAX_TIME_FULL_SIZE))))); 54 | 55 | float baseLength = baseDim * value.length(); 56 | int offsetX = (int) (((baseLength * size)) / 2); 57 | int offsetY = (int) (((baseDim * size)) / 2); 58 | 59 | offsets = new int[] { offsetX, offsetY }; 60 | } 61 | } 62 | 63 | @Override 64 | public boolean shouldNull() { 65 | return lifeTime >= MAX_LIFETIME; 66 | } 67 | 68 | @Override 69 | public void draw(GameEngine engine, EventReceiver receiver, int playerID, int[] args, CustomResourceHolder customHolder) { 70 | receiver.drawDirectFont(engine, playerID, location[0] - offsets[0], location[1] - offsets[1], value, colour, size); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/ScrollingMarqueeText.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs; 2 | 3 | import mu.nu.nullpo.game.play.GameEngine; 4 | 5 | public class ScrollingMarqueeText { 6 | // Text size index names 7 | public static final int SIZE_SMALL = 0, 8 | SIZE_NORMAL = 1, 9 | SIZE_LARGE = 2; 10 | 11 | // Sizes of texts 12 | private static final int[] SIZES = { 8, 16, 32 }; 13 | 14 | // Float sizes 15 | private static final float[] SCALES_FLOAT = { 0.5f, 1f, 2f }; 16 | 17 | // Excess length 18 | private static final int EXCESS_LENGTH = 5; 19 | 20 | // Whole string 21 | private String mainHeadingString; 22 | 23 | // Whole text string 24 | private String mainTextString; 25 | 26 | // Main colour 27 | private final int headingColour; 28 | 29 | // Text colour 30 | private final int textColour; 31 | 32 | /* 33 | * Create a staff roll. 34 | */ 35 | public ScrollingMarqueeText(String[] headingArray, String[] textArray, int hColour, int tColour) { 36 | // Strings that make up the headings 37 | // Strings that fill the info under the headings 38 | headingColour = hColour; 39 | textColour = tColour; 40 | 41 | mainHeadingString = ""; 42 | mainTextString = ""; 43 | 44 | StringBuilder mHS = new StringBuilder(mainHeadingString); 45 | StringBuilder mTS = new StringBuilder(mainTextString); 46 | for (int i = 0; i < headingArray.length; i++) { 47 | mHS.append(new String(new char[headingArray[i].length()]).replace("\0", " ")).append(" ").append(textArray[i]).append((i < headingArray.length - 1) ? " / " : ""); 48 | mTS.append(headingArray[i]).append(" ").append(new String(new char[textArray[i].length()]).replace("\0", " ")).append((i < headingArray.length - 1) ? " / " : ""); 49 | } 50 | 51 | mainHeadingString = mHS.toString(); 52 | mainTextString = mTS.toString(); 53 | } 54 | 55 | /** 56 | * Automatically draw the roll at a certain Y value. 57 | * 58 | * @param engine Current GameEngine instance 59 | * @param y Y-coordinate to draw on 60 | * @param size Size of text to draw with 61 | * @param progress Progress of the roll (0: start, 1: end) 62 | */ 63 | public void drawAtY(GameEngine engine, double y, int size, double progress) { 64 | int mainOffset1 = (int) (40 * SIZES[size] / SCALES_FLOAT[size]) - (int) ((progress) * ((40 * SIZES[size]) + ((mainHeadingString.length() + EXCESS_LENGTH) * SIZES[size]))); 65 | int mainOffset2 = (int) (40 * SIZES[size] / SCALES_FLOAT[size]) - (int) ((progress) * ((40 * SIZES[size]) + ((mainTextString.length() + EXCESS_LENGTH) * SIZES[size]))); 66 | GameTextUtilities.drawDirectText(engine, mainOffset1, (int) (y * SIZES[size]), GameTextUtilities.Text.custom(mainHeadingString, headingColour, SCALES_FLOAT[size])); 67 | GameTextUtilities.drawDirectText(engine, mainOffset2, (int) (y * SIZES[size]), GameTextUtilities.Text.custom(mainTextString, textColour, SCALES_FLOAT[size])); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/particles/BlockBasedEmitter.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.particles; 2 | 3 | import mu.nu.nullpo.game.component.Block; 4 | import mu.nu.nullpo.game.component.Piece; 5 | 6 | public interface BlockBasedEmitter { 7 | default boolean checkLowestBlock(Piece piece, int blockIndex) { 8 | if (blockIndex > piece.getMaxBlock() || blockIndex < 0) return false; 9 | 10 | for (int i = 0; i < piece.getMaxBlock(); ++i) { 11 | if (i == blockIndex) continue; 12 | if (piece.dataX[piece.direction][i] == piece.dataX[piece.direction][blockIndex] && piece.dataY[piece.direction][i] > piece.dataY[piece.direction][blockIndex]) return false; 13 | } 14 | 15 | return true; 16 | } 17 | 18 | default int[] getColorForBlock(Block block) { 19 | int red, green, blue; 20 | 21 | switch (block.color) { 22 | case Block.BLOCK_COLOR_RED: 23 | case Block.BLOCK_COLOR_GEM_RED: 24 | red = 255; 25 | green = 32; 26 | blue = 32; 27 | break; 28 | case Block.BLOCK_COLOR_ORANGE: 29 | case Block.BLOCK_COLOR_GEM_ORANGE: 30 | red = 255; 31 | green = 128; 32 | blue = 0; 33 | break; 34 | case Block.BLOCK_COLOR_SQUARE_GOLD_1: 35 | case Block.BLOCK_COLOR_SQUARE_GOLD_2: 36 | case Block.BLOCK_COLOR_SQUARE_GOLD_3: 37 | case Block.BLOCK_COLOR_SQUARE_GOLD_4: 38 | case Block.BLOCK_COLOR_SQUARE_GOLD_5: 39 | case Block.BLOCK_COLOR_SQUARE_GOLD_6: 40 | case Block.BLOCK_COLOR_SQUARE_GOLD_7: 41 | case Block.BLOCK_COLOR_SQUARE_GOLD_8: 42 | case Block.BLOCK_COLOR_SQUARE_GOLD_9: 43 | case Block.BLOCK_COLOR_YELLOW: 44 | case Block.BLOCK_COLOR_GEM_YELLOW: 45 | red = 255; 46 | green = 255; 47 | blue = 0; 48 | break; 49 | case Block.BLOCK_COLOR_GREEN: 50 | case Block.BLOCK_COLOR_GEM_GREEN: 51 | red = 32; 52 | green = 255; 53 | blue = 32; 54 | break; 55 | case Block.BLOCK_COLOR_CYAN: 56 | case Block.BLOCK_COLOR_GEM_CYAN: 57 | red = 0; 58 | green = 255; 59 | blue = 255; 60 | break; 61 | case Block.BLOCK_COLOR_BLUE: 62 | case Block.BLOCK_COLOR_GEM_BLUE: 63 | red = 32; 64 | green = 32; 65 | blue = 255; 66 | break; 67 | case Block.BLOCK_COLOR_PURPLE: 68 | case Block.BLOCK_COLOR_GEM_PURPLE: 69 | red = 128; 70 | green = 32; 71 | blue = 255; 72 | break; 73 | default: 74 | red = 255; 75 | green = 255; 76 | blue = 255; 77 | break; 78 | } 79 | 80 | return new int[] { red, green, blue }; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/particles/ParticleEmitterBase.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.particles; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.event.EventReceiver; 5 | import org.apache.log4j.Logger; 6 | import zeroxfc.nullpo.custom.libs.BufferedPrimitiveDrawingHook; 7 | import zeroxfc.nullpo.custom.libs.CustomResourceHolder; 8 | 9 | public abstract class ParticleEmitterBase

{ 10 | /** 11 | * Default colour set shared by all emitters.
12 | * In order: Gray, Red, Orange, Yellow, Green, Cyan, Blue, Purple
13 | * Parameters: Red, Green, Blue, Alpha, Variance 14 | */ 15 | public static final int[][] DEF_COLOURS = { 16 | new int[] { 240, 240, 240, 235, 20 }, 17 | new int[] { 240, 30, 0, 235, 20 }, 18 | new int[] { 240, 130, 0, 235, 20 }, 19 | new int[] { 240, 240, 0, 235, 20 }, 20 | new int[] { 30, 240, 0, 235, 20 }, 21 | new int[] { 0, 240, 240, 235, 20 }, 22 | new int[] { 0, 30, 240, 235, 20 }, 23 | new int[] { 210, 0, 210, 235, 20 } 24 | }; 25 | /** 26 | * Debug logger 27 | */ 28 | protected static final Logger log = Logger.getLogger(ParticleEmitterBase.class); 29 | /** 30 | * Particle container 31 | */ 32 | protected ArrayList particles = new ArrayList<>(); 33 | 34 | /** 35 | * Drawing buffer 36 | */ 37 | protected final BufferedPrimitiveDrawingHook drawingQueue; 38 | 39 | protected ParticleEmitterBase(CustomResourceHolder customGraphics) { 40 | drawingQueue = new BufferedPrimitiveDrawingHook(customGraphics); 41 | } 42 | 43 | /** 44 | * Update method. Used to update all partcles. 45 | */ 46 | public void update() { 47 | if (particles.isEmpty()) return; 48 | for (int i = particles.size() - 1; i >= 0; i--) { 49 | boolean res = particles.get(i).update(); 50 | if (res) { 51 | particles.remove(i); 52 | } 53 | } 54 | } 55 | 56 | /** 57 | * Draw the particles to the current renderer. 58 | * 59 | * @param receiver Renderer to use 60 | */ 61 | public void draw(EventReceiver receiver) { 62 | if (particles.isEmpty()) return; 63 | for (Particle p : particles) { 64 | if (p.position.getX() < 0 || p.position.getX() > 640) continue; 65 | if (p.position.getY() < 0 || p.position.getY() > 480) continue; 66 | 67 | p.draw(drawingQueue); 68 | } 69 | drawingQueue.renderAll(receiver); 70 | } 71 | 72 | /** 73 | * Add particles directly to the collection. 74 | * 75 | * @param particle Particle to add 76 | */ 77 | public void addSpecific(Particle particle) { 78 | particles.add(particle); 79 | } 80 | 81 | /** 82 | * Add some number of particles or particle groups. 83 | * Varies upon child class. 84 | * 85 | * @param num Number of particles / particle groups. 86 | * @param params Parameters to pass onto the particles. 87 | */ 88 | public abstract void addNumber(int num, P params); 89 | } -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/LazyReference.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | import java.util.concurrent.Callable; 4 | import java.util.function.Supplier; 5 | 6 | /** 7 | * A wrapper for values which allows the values to be lazy-loaded rather than strictly loaded. The 8 | * intrinsic memory overhead for this class comes from the fact that it itself takes up space, 9 | * along with a reference to the internal value supplier The lazy-loaded value can throw 10 | * exceptions, but those will be wrapped with a special exception, {@link LazyLoadException}. 11 | * 12 | *

Lazy values are only ever loaded once. Every call of get() after the first will 13 | * load the same instance of the value. 14 | * 15 | * @param Apparent type of value being lazy-loaded. 16 | */ 17 | public class LazyReference { 18 | 19 | private final Callable getter; 20 | private T value; 21 | private boolean evaluated = false; 22 | 23 | // No outside instantiation is needed. The static methods perform all of the instantiation. 24 | private LazyReference(Callable getter) { 25 | this.getter = getter; 26 | } 27 | 28 | /** 29 | * Make a lazy-loaded value from a callable object. In general, once can use a callable object 30 | * directly, or use a lambda instead: 31 | * 32 | *

{@code () -> value
33 |    *
34 |    * or
35 |    *
36 |    * () -> {
37 |    *   ...
38 |    *   return value;
39 |    * }}
40 | * 41 | * @param callable Callable object to load from. 42 | * @param Apparent type of lazy-loaded value. 43 | * @return Lazy-loader that loads from the given callable. 44 | */ 45 | public static LazyReference fromCallable(Callable callable) { 46 | return new LazyReference<>(callable::call); 47 | } 48 | 49 | /** 50 | * Make a lazy-loaded value from a supplier object. In general, once can use a supplier object 51 | * directly, or use a lambda instead: 52 | * 53 | *
{@code () -> value
54 |    *
55 |    * or
56 |    *
57 |    * () -> {
58 |    *   ...
59 |    *   return value;
60 |    * }}
61 | * 62 | * @param supplier Supplier object to load from. 63 | * @param Apparent type of lazy-loaded value. 64 | * @return Lazy-loader that loads from the given supplier. 65 | */ 66 | public static LazyReference fromSupplier(Supplier supplier) { 67 | return new LazyReference<>(supplier::get); 68 | } 69 | 70 | /** 71 | * Lazy-load the value and return it. If an error occurs, a {@link LazyLoadException} will be 72 | * thrown, with the cause exception nested inside. 73 | * 74 | * @return The lazily-loaded value. If this has already been called before, gets the 75 | * already-loaded value. 76 | */ 77 | public T getValue() { 78 | if (value == null) { 79 | evaluated = true; 80 | 81 | try { 82 | value = getter.call(); 83 | } catch (Exception e) { 84 | throw new LazyLoadException("Exception when lazy-loading object.", e); 85 | } 86 | } 87 | 88 | return value; 89 | } 90 | 91 | /** Utility for checking if the object has already been evaluated and loaded. */ 92 | public boolean isEvaluated() { 93 | return evaluated; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/wallkick/SuperDTETWallkick.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, NullNoname 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | * Neither the name of NullNoname nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package zeroxfc.nullpo.custom.wallkick; 30 | 31 | import mu.nu.nullpo.game.component.Controller; 32 | import mu.nu.nullpo.game.component.Field; 33 | import mu.nu.nullpo.game.component.Piece; 34 | import mu.nu.nullpo.game.component.WallkickResult; 35 | import mu.nu.nullpo.game.subsystem.wallkick.Wallkick; 36 | 37 | /** 38 | * DTET Wallkick - An extension of the Classic Wallkick system for DRS by Zircean 39 | * Modified by 0xFC963F18DC21 to add a 1 up floorkick 40 | */ 41 | public class SuperDTETWallkick implements Wallkick { 42 | /** 43 | * Wallkick table 44 | */ 45 | private static final int[][] WALLKICK = new int[][] { { -1, 0 }, { 1, 0 }, { 0, 1 }, { -1, 1 }, { 1, 1 }, { 0, -1 } }; 46 | 47 | /* 48 | * Wallkick main method 49 | */ 50 | public WallkickResult executeWallkick(int x, int y, int rtDir, int rtOld, int rtNew, boolean allowUpward, Piece piece, Field field, Controller ctrl) { 51 | int x2, y2; 52 | 53 | for (int[] ints : WALLKICK) { 54 | if (rtDir < 0 || rtDir == 2) { 55 | x2 = ints[0]; 56 | } else { 57 | x2 = -ints[0]; 58 | } 59 | y2 = ints[1]; 60 | 61 | if (piece.big) { 62 | x2 *= 2; 63 | y2 *= 2; 64 | } 65 | 66 | if (!piece.checkCollision(x + x2, y + y2, rtNew, field)) { 67 | return new WallkickResult(x2, y2, rtNew); 68 | } 69 | } 70 | return null; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/wallkick/SomeRandomShittyRotationSystemWallkick.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.wallkick; 2 | 3 | import mu.nu.nullpo.game.component.Controller; 4 | import mu.nu.nullpo.game.component.Field; 5 | import mu.nu.nullpo.game.component.Piece; 6 | import mu.nu.nullpo.game.component.WallkickResult; 7 | import mu.nu.nullpo.game.subsystem.wallkick.Wallkick; 8 | 9 | public class SomeRandomShittyRotationSystemWallkick implements Wallkick { 10 | // So basically, it's a symmetric spiral checker. 11 | // The bigger the field width, the more checks it performs. 12 | 13 | @Override 14 | public WallkickResult executeWallkick(int x, int y, int rtDir, int rtOld, int rtNew, boolean allowUpward, 15 | Piece piece, Field field, Controller ctrl) { 16 | int x2 = 0; 17 | int y2 = 0; 18 | int offsetRadius = field.getWidth() + 1; 19 | if (piece.big) offsetRadius = (field.getWidth() / 2) + 1; 20 | int dx = 1; 21 | int dy = 1; 22 | int m = 1; // not sure what this is for... 23 | int iter = 0; 24 | 25 | while (iter < Math.pow(offsetRadius, 2)) { 26 | while ((2 * x2 * dx) < m) { 27 | // STH 28 | if (iter >= Math.pow(offsetRadius, 2)) break; 29 | 30 | int x3 = x2; 31 | x3 *= (rtDir == 1) ? 1 : -1; 32 | 33 | if (piece.big) { 34 | x3 *= 2; 35 | y2 *= 2; 36 | } 37 | 38 | if ((!piece.checkCollision(x + x3, y + y2, rtNew, field))) { 39 | if (!(x3 == 0 && y2 == 0)) { 40 | return new WallkickResult(x3, y2, rtNew); 41 | } 42 | } 43 | 44 | iter++; 45 | x2 += dx; 46 | } 47 | while ((2 * y2 * dy) < m) { 48 | // STH 49 | if (iter >= Math.pow(offsetRadius, 2)) break; 50 | 51 | int x3 = x2; 52 | x3 *= (rtDir == 1) ? 1 : -1; 53 | 54 | if (piece.big) { 55 | x3 *= 2; 56 | y2 *= 2; 57 | } 58 | 59 | if ((!piece.checkCollision(x + x3, y + y2, rtNew, field))) { 60 | if (!(x3 == 0 && y2 == 0)) { 61 | return new WallkickResult(x3, y2, rtNew); 62 | } 63 | } 64 | 65 | iter++; 66 | y2 += dy; 67 | } 68 | dx *= -1; 69 | dy *= -1; 70 | m++; 71 | } 72 | 73 | /* 74 | for (int i = 0; i < Math.pow(argX, 2); i++) { 75 | // Spirals are swine. 76 | // They are a son of a mother-less goat. 77 | 78 | I really have no goddamn clue. 79 | 80 | if ((-argX/2 < x2) && 81 | (x2 <= argX/2) && 82 | (-argY/2 < y2) && 83 | (y2 <= argY/2)) { 84 | x3 = x2; 85 | x3 *= (rtDir == 1) ? -1 : 1; 86 | 87 | if (piece.big) 88 | { 89 | x3 *= 2; y2 *= 2; 90 | } 91 | 92 | if ((piece.checkCollision(x + x3, y + y2, rtNew, field) == false)) { 93 | if (!(x3 == 0 && y2 == 0)) { 94 | return new WallkickResult(x3, y2, rtNew); 95 | } 96 | } 97 | } 98 | 99 | if ((x2 == y2) || 100 | (x2 < 0 && x2 == -y2) || 101 | (x2 > 0 && x2 == (1-y2))) { 102 | int temp = dx; 103 | dx = -dy; 104 | dy = temp; 105 | } 106 | 107 | x2 += dx; 108 | y2 += dy; 109 | 110 | } 111 | */ 112 | 113 | return null; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/random/DroughtedPieceBiasRandomizer.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.random; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Piece; 5 | import net.omegaboshi.nullpomino.game.subsystem.randomizer.Randomizer; 6 | 7 | public class DroughtedPieceBiasRandomizer extends Randomizer { 8 | private static final int ROLLS_INITIAL = 6; 9 | private static final int ROLLS = 3; 10 | 11 | private static final int INITIAL_PIECES = 4; 12 | 13 | int pieceCount; 14 | int[] counters; 15 | ArrayList history; 16 | 17 | @Override 18 | public void init() { 19 | pieceCount = pieces.length; 20 | counters = new int[pieceCount]; 21 | 22 | history = new ArrayList<>(); 23 | 24 | history.add(Piece.PIECE_O); // LEAST RECENT 25 | history.add(Piece.PIECE_S); // -- 26 | history.add(Piece.PIECE_Z); // -- 27 | history.add(Piece.PIECE_O); // MOST RECENT 28 | } 29 | 30 | /** 31 | * This is overridden as changing piece count screws with the counter averages.
32 | * Therefore this calso calls init(). 33 | * 34 | * @param pieceEnable Array of enabled pieces. 35 | */ 36 | @Override 37 | public void setPieceEnable(boolean[] pieceEnable) { 38 | int piece = 0; 39 | for (int i = 0; i < Piece.PIECE_COUNT; i++) { 40 | if (pieceEnable[i]) piece++; 41 | } 42 | pieces = new int[piece]; 43 | piece = 0; 44 | for (int i = 0; i < Piece.PIECE_COUNT; i++) { 45 | if (pieceEnable[i]) { 46 | pieces[piece] = i; 47 | piece++; 48 | } 49 | } 50 | 51 | init(); 52 | } 53 | 54 | @Override 55 | public int next() { 56 | if (pieceCount == 1) return pieces[0]; 57 | 58 | int v = -1; 59 | double divisor = 0; 60 | double[] rawChances = new double[pieceCount]; 61 | double[] finalChances = new double[pieceCount]; 62 | 63 | int total = 0; 64 | 65 | // Get total pieces rolled 66 | for (int i : counters) total += i; 67 | 68 | // Get raw chances and the final divisor for the values 69 | for (int i = 0; i < pieceCount; i++) { 70 | rawChances[i] = 1 - ((double) counters[i] / total); 71 | divisor += rawChances[i]; 72 | } 73 | 74 | // Find final values 75 | for (int i = 0; i < pieceCount; i++) { 76 | double chance = rawChances[i] / divisor; 77 | for (int j = 0; j < i; j++) { 78 | chance += rawChances[j] / divisor; 79 | } 80 | 81 | finalChances[i] = chance; 82 | } 83 | 84 | // Roll up to three times to get piece that is not in history 85 | for (int i = 0; i < (total < INITIAL_PIECES ? ROLLS_INITIAL : ROLLS); i++) { 86 | double val = r.nextDouble(); 87 | int idx = 0; 88 | for (int j = 1; j < pieceCount; j++) { 89 | if (val < finalChances[j] && val >= finalChances[j - 1]) idx = j; 90 | } 91 | 92 | v = pieces[idx]; 93 | if (!history.contains(v)) { 94 | counters[idx]++; 95 | break; 96 | } else if (i == 2) { 97 | counters[idx]++; 98 | } 99 | } 100 | 101 | // Add piece to history 102 | appendHistory(v); 103 | return v; 104 | } 105 | 106 | private void appendHistory(int i) { 107 | history.remove(0); 108 | history.add(i); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/gemswap/NormalGem.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.gemswap; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class NormalGem implements Gem { 6 | /** 7 | * Gem ID 8 | */ 9 | private static final int ID = GemField.GEMID_NORMAL; 10 | private final boolean special; 11 | /** 12 | * Class properties. 13 | */ 14 | private int[] location; 15 | private int colour; 16 | private boolean recentSwap; 17 | private boolean recentFall; 18 | private boolean matchedHorizontal; 19 | private boolean matchedVertical; 20 | private boolean actionConducted; 21 | private boolean destroy; 22 | 23 | public NormalGem(int x, int y, int colour) { 24 | location = new int[] { x, y }; 25 | this.colour = colour; 26 | 27 | recentSwap = false; 28 | recentFall = false; 29 | matchedHorizontal = false; 30 | matchedVertical = false; 31 | actionConducted = false; 32 | special = false; 33 | destroy = false; 34 | } 35 | 36 | @Override 37 | public int getID() { 38 | return ID; 39 | } 40 | 41 | @Override 42 | public int getColour() { 43 | return colour; 44 | } 45 | 46 | @Override 47 | public void setColour(int colour) { 48 | this.colour = colour; 49 | } 50 | 51 | @Override 52 | public int[] getLocation() { 53 | return location; 54 | } 55 | 56 | @Override 57 | public boolean getRecentSwap() { 58 | return recentSwap; 59 | } 60 | 61 | @Override 62 | public void setRecentSwap(boolean isRecentSwap) { 63 | recentSwap = isRecentSwap; 64 | } 65 | 66 | @Override 67 | public boolean getRecentFall() { 68 | return recentFall; 69 | } 70 | 71 | @Override 72 | public void setRecentFall(boolean isRecentFall) { 73 | recentFall = isRecentFall; 74 | } 75 | 76 | @Override 77 | public void setLocation(int x, int y) { 78 | location = new int[] { x, y }; 79 | } 80 | 81 | @Override 82 | public int conductAction(GemField field, int[] args, ArrayList eventList) { 83 | actionConducted = true; 84 | 85 | return 0; 86 | } 87 | 88 | @Override 89 | public boolean getSpecial() { 90 | return special; 91 | } 92 | 93 | @Override 94 | public boolean getMatchedHorizontal() { 95 | return matchedHorizontal; 96 | } 97 | 98 | @Override 99 | public void setMatchedHorizontal(boolean isMatched) { 100 | matchedHorizontal = isMatched; 101 | } 102 | 103 | @Override 104 | public boolean getMatchedVertical() { 105 | return matchedVertical; 106 | } 107 | 108 | @Override 109 | public void setMatchedVertical(boolean isMatched) { 110 | matchedVertical = isMatched; 111 | } 112 | 113 | @Override 114 | public boolean getActionConducted() { 115 | return actionConducted; 116 | } 117 | 118 | @Override 119 | public void setActionConducted(boolean isConduted) { 120 | actionConducted = isConduted; 121 | } 122 | 123 | @Override 124 | public Gem getSelf() { 125 | return new NormalGem(location[0], location[1], colour); 126 | } 127 | 128 | @Override 129 | public boolean getDestroy() { 130 | // TODO Auto-generated method stub 131 | return destroy; 132 | } 133 | 134 | @Override 135 | public void setDestroy(boolean shouldDestroy) { 136 | // TODO Auto-generated method stub 137 | destroy = shouldDestroy; 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/gemswap/EmptyGem.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.gemswap; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class EmptyGem implements Gem { 7 | /** 8 | * Gem ID 9 | */ 10 | private static final int ID = GemField.GEMID_EMPTY; 11 | private final boolean special; 12 | /** 13 | * Class properties. 14 | */ 15 | private int[] location; 16 | private int colour; 17 | private boolean recentSwap; 18 | private boolean recentFall; 19 | private boolean matchedHorizontal; 20 | private boolean matchedVertical; 21 | private boolean actionConducted; 22 | private boolean destroy; 23 | 24 | public EmptyGem(int x, int y) { 25 | location = new int[] { x, y }; 26 | colour = Block.BLOCK_COLOR_NONE; 27 | 28 | recentSwap = false; 29 | recentFall = false; 30 | matchedHorizontal = false; 31 | matchedVertical = false; 32 | actionConducted = false; 33 | special = false; 34 | destroy = false; 35 | } 36 | 37 | @Override 38 | public int getID() { 39 | return ID; 40 | } 41 | 42 | @Override 43 | public int getColour() { 44 | return colour; 45 | } 46 | 47 | @Override 48 | public void setColour(int colour) { 49 | this.colour = colour; 50 | } 51 | 52 | @Override 53 | public int[] getLocation() { 54 | return location; 55 | } 56 | 57 | @Override 58 | public boolean getRecentSwap() { 59 | return recentSwap; 60 | } 61 | 62 | @Override 63 | public void setRecentSwap(boolean isRecentSwap) { 64 | recentSwap = isRecentSwap; 65 | } 66 | 67 | @Override 68 | public boolean getRecentFall() { 69 | return recentFall; 70 | } 71 | 72 | @Override 73 | public void setRecentFall(boolean isRecentFall) { 74 | recentFall = isRecentFall; 75 | } 76 | 77 | @Override 78 | public void setLocation(int x, int y) { 79 | location = new int[] { x, y }; 80 | } 81 | 82 | @Override 83 | public int conductAction(GemField field, int[] args, ArrayList eventList) { 84 | actionConducted = true; 85 | 86 | return 0; 87 | } 88 | 89 | @Override 90 | public boolean getSpecial() { 91 | return special; 92 | } 93 | 94 | @Override 95 | public boolean getMatchedHorizontal() { 96 | return matchedHorizontal; 97 | } 98 | 99 | @Override 100 | public void setMatchedHorizontal(boolean isMatched) { 101 | matchedHorizontal = isMatched; 102 | } 103 | 104 | @Override 105 | public boolean getMatchedVertical() { 106 | return matchedVertical; 107 | } 108 | 109 | @Override 110 | public void setMatchedVertical(boolean isMatched) { 111 | matchedVertical = isMatched; 112 | } 113 | 114 | @Override 115 | public boolean getActionConducted() { 116 | return actionConducted; 117 | } 118 | 119 | @Override 120 | public void setActionConducted(boolean isConduted) { 121 | actionConducted = isConduted; 122 | } 123 | 124 | @Override 125 | public Gem getSelf() { 126 | return new EmptyGem(location[0], location[1]); 127 | } 128 | 129 | @Override 130 | public boolean getDestroy() { 131 | // TODO Auto-generated method stub 132 | return destroy; 133 | } 134 | 135 | @Override 136 | public void setDestroy(boolean shouldDestroy) { 137 | // TODO Auto-generated method stub 138 | destroy = false; 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/SideWaveText.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs; 2 | 3 | import mu.nu.nullpo.game.event.EventReceiver; 4 | import mu.nu.nullpo.game.play.GameEngine; 5 | import zeroxfc.nullpo.custom.libs.types.ObjectAlignment; 6 | 7 | public class SideWaveText { 8 | public static final int MaxLifeTime = 120; 9 | private static final DoubleVector VerticalVelocity = new DoubleVector(0, -1 * (4.0 / 5.0), false); 10 | private final String text; 11 | private final double offsetMax; 12 | private final double sinFrequency; 13 | private final boolean big; 14 | private final boolean lClear; 15 | private DoubleVector position; 16 | private double xOffset; 17 | private double sinPhase; 18 | private int lifeTime; 19 | 20 | /** 21 | * Creates a Super Collapse II-styled score popup that flies away.
22 | * For now, drawing is manual. 23 | * 24 | * @param x X-coordinate of centre (?) 25 | * @param y Y-coordinate of centre (?) 26 | * @param frequency Waving frequency 27 | * @param offsetWidth Max offset 28 | * @param text Text to draw 29 | * @param big Should it be double size? 30 | * @param largeclear Should it flash and actually wave? 31 | */ 32 | public SideWaveText(int x, int y, double frequency, double offsetWidth, String text, boolean big, boolean largeclear) { 33 | this.text = text; 34 | position = new DoubleVector(x, y, false); 35 | 36 | sinPhase = 0.0; 37 | sinFrequency = frequency; 38 | offsetMax = offsetWidth; 39 | this.big = big; 40 | lClear = largeclear; 41 | 42 | xOffset = 0; 43 | lifeTime = 0; 44 | } 45 | 46 | /** 47 | * Updates the instance to a new position. 48 | */ 49 | public void update() { 50 | sinPhase += sinFrequency * ((Math.PI * 2) / 60); 51 | 52 | xOffset = offsetMax * (Math.sin(sinPhase) / 2.0); 53 | 54 | position = DoubleVector.add(position, VerticalVelocity); 55 | 56 | lifeTime++; 57 | } 58 | 59 | /** 60 | * Gets the current location of the text for manual drawing. 61 | * 62 | * @return A 2-long int[] in the format { x, y } 63 | */ 64 | public int[] getLocation() { 65 | return new int[] { (int) (position.getX() + xOffset), (int) position.getY() }; 66 | } 67 | 68 | /** 69 | * Automatic drawing of the text object. 70 | * 71 | * @param receiver Renderer to draw on 72 | * @param engine Current GameEngine instance 73 | * @param playerID Current player ID 74 | * @param flag true ? orange : yellow 75 | */ 76 | public void drawCentral(EventReceiver receiver, GameEngine engine, int playerID, boolean flag) { 77 | int[] location = getLocation(); 78 | final int x = location[0]; 79 | final int y = location[1]; 80 | 81 | int color = EventReceiver.COLOR_ORANGE; 82 | if (flag) color = EventReceiver.COLOR_YELLOW; 83 | 84 | float scale = 0; 85 | float baseScale = big ? 2 : 1; 86 | if (lifeTime < 24) { 87 | scale = baseScale; 88 | } else { 89 | scale = baseScale - (baseScale * ((float) (lifeTime - 24) / 96)); 90 | } 91 | 92 | GameTextUtilities.drawDirectTextAlign(engine, x, y, ObjectAlignment.MIDDLE_MIDDLE, text, color, scale); 93 | } 94 | 95 | public int getLifeTime() { 96 | return lifeTime; 97 | } 98 | 99 | public boolean getBig() { 100 | return big; 101 | } 102 | 103 | public boolean getLargeClear() { 104 | return lClear; 105 | } 106 | 107 | public String getText() { 108 | return text; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/seasons/BlockVortex.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.seasons; 2 | 3 | import java.util.Deque; 4 | import java.util.LinkedList; 5 | import java.util.Random; 6 | import mu.nu.nullpo.game.component.Block; 7 | import mu.nu.nullpo.game.event.EventReceiver; 8 | import zeroxfc.nullpo.custom.libs.DoubleVector; 9 | import zeroxfc.nullpo.custom.libs.Interpolation; 10 | import zeroxfc.nullpo.custom.libs.MathHelper; 11 | import zeroxfc.nullpo.custom.libs.RendererExtension; 12 | import zeroxfc.nullpo.custom.libs.types.ObjectAlignment; 13 | 14 | public class BlockVortex { 15 | private static final int MAX_PROGRESS = 90; 16 | 17 | private final Deque instances = new LinkedList<>(); 18 | 19 | public void add(Random rand, int colour, int blockSkin) { 20 | final BlockInstance bi = new BlockInstance(colour, blockSkin); 21 | final DoubleVector origin = new DoubleVector(40, 2 * Math.PI * rand.nextDouble(), true); 22 | final DoubleVector end = new DoubleVector(Math.sqrt(400d * 400d + 320d * 320d), origin.getDirection(), true); 23 | final DoubleVector control = new DoubleVector( 24 | 120 + rand.nextDouble() * 240, 25 | origin.getDirection() + (Math.PI * rand.nextDouble() * 0.75), 26 | true 27 | ); 28 | 29 | bi.maxProgress = MAX_PROGRESS + (rand.nextInt(61) - 30); 30 | 31 | bi.startX = (int) origin.getX() + 320; 32 | bi.startY = (int) origin.getY() + 240; 33 | 34 | bi.endX = (int) end.getX() + 320; 35 | bi.endY = (int) end.getY() + 240; 36 | 37 | bi.controlX = (int) control.getX() + 320; 38 | bi.controlY = (int) control.getY() + 240; 39 | 40 | instances.add(bi); 41 | } 42 | 43 | public void update() { 44 | instances.removeIf(bi -> (bi.progress++) > bi.maxProgress); 45 | } 46 | 47 | public void draw(RendererExtension rendererExtension, EventReceiver receiver) { 48 | for (BlockInstance bi : instances) { 49 | bi.draw(rendererExtension, receiver); 50 | } 51 | } 52 | 53 | private static class BlockInstance { 54 | private final Block blockForDraw; 55 | 56 | public final int colour; 57 | public final int blockSkin; 58 | 59 | public int progress; 60 | public int maxProgress; 61 | 62 | public int startX, startY; 63 | public int endX, endY; 64 | public int controlX, controlY; 65 | 66 | public BlockInstance(int colour, int blockSkin) { 67 | this.colour = colour; 68 | this.blockSkin = blockSkin; 69 | this.blockForDraw = new Block(colour, blockSkin); 70 | 71 | progress = 0; 72 | } 73 | 74 | public void draw(RendererExtension ext, EventReceiver receiver) { 75 | final double lerpVal = progress / (double) maxProgress; 76 | 77 | final int x1 = Interpolation.lerp(startX, controlX, lerpVal); 78 | final int x2 = Interpolation.lerp(controlX, endX, lerpVal); 79 | final int anchorX = Interpolation.lerp(x1, x2, lerpVal); 80 | 81 | final int y1 = Interpolation.lerp(startY, controlY, lerpVal); 82 | final int y2 = Interpolation.lerp(controlY, endY, lerpVal); 83 | final int anchorY = Interpolation.lerp(y1, y2, lerpVal); 84 | 85 | ext.drawAlignedScaledBlock( 86 | receiver, 87 | anchorX, anchorY, 88 | ObjectAlignment.MIDDLE_MIDDLE, 89 | blockForDraw.getDrawColor(), blockSkin, 90 | false, 91 | MathHelper.clamp(Interpolation.lerp(0.625f, 0.125f, lerpVal), 0.0f, 0.5f), 92 | 1f, 93 | Interpolation.lerp(1f, 4f, lerpVal), 94 | Block.BLOCK_ATTRIBUTE_VISIBLE 95 | ); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/Tetratiotris.java: -------------------------------------------------------------------------------- 1 | //package zeroxfc.nullpo.custom.modes; 2 | // 3 | //import mu.nu.nullpo.game.component.Piece; 4 | //import mu.nu.nullpo.game.event.EventReceiver; 5 | //import mu.nu.nullpo.game.play.GameEngine; 6 | //import zeroxfc.nullpo.custom.libs.ProfileProperties; 7 | //import java.math.BigDecimal; 8 | //import java.util.*; 9 | // 10 | //public class Tetratiotris extends MarathonModeBase { 11 | // /** 12 | // * POWERS 13 | // */ 14 | // private BigDecimal POWER_SINGLE = new BigDecimal( 1.01 ); 15 | // private BigDecimal POWER_DOUBLE = new BigDecimal( 1.02 ); 16 | // private BigDecimal POWER_TRIPLE = new BigDecimal( 1.04 ); 17 | // private BigDecimal POWER_TETRIS = new BigDecimal( 1.08 ); 18 | // 19 | // /** 20 | // * Rankings' scores 21 | // */ 22 | // private BigDecimal[] rankingScore; 23 | // 24 | // /** 25 | // * Rankings' line counts 26 | // */ 27 | // private int[] rankingLines; 28 | // 29 | // /** 30 | // * Rankings' times 31 | // */ 32 | // private int[] rankingTime; 33 | // 34 | // // PROFILE 35 | // private ProfileProperties playerProperties = null; 36 | // private boolean showPlayerStats = false; 37 | // private static final int headerColour = EventReceiver.COLOR_RED; 38 | // private int rankingRankPlayer = -1; 39 | // private BigDecimal[] rankingScorePlayer; 40 | // private int[] rankingTimePlayer; 41 | // private int[] rankingLinesPlayer; 42 | // private String PLAYER_NAME = null; 43 | // 44 | // /** 45 | // * The good hard drop effect 46 | // */ 47 | // private ArrayList< int[] > pCoordList = null; 48 | // private Piece cPiece = null; 49 | // 50 | // /** 51 | // * Last score before increase 52 | // */ 53 | // private BigDecimal scoreBefore = new BigDecimal( 0 ); 54 | // 55 | // /** 56 | // * Mode name 57 | // */ 58 | // @Override 59 | // public String getName() { 60 | // return "TETRATIOTRIS"; 61 | // } 62 | // 63 | // /* 64 | // * Initialization 65 | // */ 66 | // @Override 67 | // public void playerInit( GameEngine engine, int playerID ) { 68 | // owner = engine.owner; 69 | // receiver = engine.owner.receiver; 70 | // lastscore = 0; 71 | // scgettime = 0; 72 | // lastevent = EVENT_NONE; 73 | // lastb2b = false; 74 | // lastcombo = 0; 75 | // lastpiece = 0; 76 | // bgmlv = 0; 77 | // 78 | // rankingRank = -1; 79 | // rankingScore = new BigDecimal[ RANKING_MAX ]; 80 | // for ( int i = 0; i < RANKING_MAX; ++i ) rankingScore[ i ] = new BigDecimal( 0 ); 81 | // rankingLines = new int[ RANKING_MAX ]; 82 | // rankingTime = new int[ RANKING_MAX ]; 83 | // 84 | // if ( playerProperties == null ) { 85 | // playerProperties = new ProfileProperties( headerColour ); 86 | // showPlayerStats = false; 87 | // } 88 | // 89 | // rankingRankPlayer = -1; 90 | // rankingScorePlayer = new BigDecimal[ RANKING_MAX ]; 91 | // for ( int i = 0; i < RANKING_MAX; ++i ) rankingScorePlayer[ i ] = new BigDecimal( 0 ); 92 | // rankingLinesPlayer = new int[ RANKING_MAX ]; 93 | // rankingTimePlayer = new int[ RANKING_MAX ]; 94 | // 95 | // pCoordList = new ArrayList<>(); 96 | // cPiece = null; 97 | // 98 | // netPlayerInit( engine, playerID ); 99 | // 100 | // if ( owner.replayMode == false ) { 101 | // loadSetting( owner.modeConfig ); 102 | // loadRanking( owner.modeConfig, engine.ruleopt.strRuleName ); 103 | // version = CURRENT_VERSION; 104 | // } else { 105 | // loadSetting( owner.replayProp ); 106 | // if ( version == 0 && owner.replayProp.getProperty( "tetratiotris.endless", false ) ) goaltype = 2; 107 | // 108 | // // NET: Load name 109 | // netPlayerName = engine.owner.replayProp.getProperty( "$playerID.net.netPlayerName", "" ); 110 | // } 111 | // 112 | // engine.owner.backgroundStatus.bg = startlevel; 113 | // engine.framecolor = GameEngine.FRAME_COLOR_PINK; 114 | // } 115 | // 116 | // // EXTENSIONS 117 | // private BigDecimal lerp( BigDecimal v0, BigDecimal v1, BigDecimal t ) { 118 | // return ( t.multiply( v1 ) ).add( ( ( new BigDecimal( 1 ) ).subtract( t ) ).multiply( v0 ) ); 119 | // } 120 | //} 121 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/I1.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class I1 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 1 } 10 | } 11 | }; 12 | private final int state; 13 | private int[] location; 14 | private int powerup; 15 | 16 | public I1(int x, int y) { 17 | location = new int[] { x, y }; 18 | state = 0; 19 | powerup = 0; 20 | } 21 | 22 | @Override 23 | public int getPowerup() { 24 | return powerup; 25 | } 26 | 27 | @Override 28 | public void setPowerup(int powerup) { 29 | this.powerup = powerup; 30 | } 31 | 32 | @Override 33 | public int getScore() { 34 | return 25; 35 | } 36 | 37 | @Override 38 | public int getWidth() { 39 | return 1; 40 | } 41 | 42 | @Override 43 | public int getHeight() { 44 | return 1; 45 | } 46 | 47 | @Override 48 | public int getX() { 49 | return location[0]; 50 | } 51 | 52 | @Override 53 | public int getY() { 54 | return location[1]; 55 | } 56 | 57 | @Override 58 | public int[] getLocation() { 59 | return location; 60 | } 61 | 62 | @Override 63 | public int[][] getContents() { 64 | return contents[state]; 65 | } 66 | 67 | @Override 68 | public int[] getCursorOffset() { 69 | return new int[] { 0, 0 }; 70 | } 71 | 72 | @Override 73 | public double getConveyorYOffset() { 74 | return 0.0; 75 | } 76 | 77 | @Override 78 | public int getState() { 79 | return state; 80 | } 81 | 82 | @Override 83 | public int getColour() { 84 | return Block.BLOCK_COLOR_RED; 85 | } 86 | 87 | @Override 88 | public int[][] getConveyorBoundingBox() { 89 | int minX, minY, maxX, maxY; 90 | 91 | minX = contents[0][0].length - 1; 92 | minY = contents[0].length - 1; 93 | maxX = 0; 94 | maxY = 0; 95 | 96 | for (int y = 0; y < contents[0].length; y++) { 97 | for (int x = 0; x < contents[0][0].length; x++) { 98 | if (contents[state][y][x] != 0) { 99 | if (x < minX) minX = x; 100 | if (y < minY) minY = y; 101 | if (x > maxX) maxX = x; 102 | if (y > maxY) maxY = y; 103 | } 104 | } 105 | } 106 | 107 | maxX++; 108 | maxY++; 109 | 110 | int[] tlc, brc; 111 | tlc = new int[] { 112 | location[0] + (minX * 16), 113 | location[1] + (minY * 16) 114 | }; 115 | brc = new int[] { 116 | location[0] + (maxX * 16), 117 | location[1] + (maxY * 16) 118 | }; 119 | 120 | return new int[][] { tlc, brc }; 121 | } 122 | 123 | @Override 124 | public int[][][] getCursorBoundingBox() { 125 | ArrayList boxes = new ArrayList<>(); 126 | 127 | for (int y = 0; y < contents[state].length; y++) { 128 | for (int x = 0; x < contents[state][0].length; x++) { 129 | if (contents[state][y][x] != 0) { 130 | boxes.add( 131 | new int[][] { 132 | new int[] { 133 | location[0] + (x * 16), 134 | location[1] + (y * 16) 135 | }, 136 | new int[] { 137 | location[0] + ((x + 1) * 16), 138 | location[1] + ((y + 1) * 16) 139 | } 140 | } 141 | ); 142 | } 143 | } 144 | } 145 | 146 | int[][][] arr = new int[boxes.size()][][]; 147 | 148 | int i = 0; 149 | for (int[][] iss : boxes) { 150 | arr[i] = iss.clone(); 151 | i++; 152 | } 153 | 154 | return arr; 155 | } 156 | 157 | @Override 158 | public void rotate() { 159 | // DO NOTHING. 160 | } 161 | 162 | @Override 163 | public void setLocation(int x, int y) { 164 | location = new int[] { x, y }; 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/StaticFlyInText.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs; 2 | 3 | import java.util.Random; 4 | import mu.nu.nullpo.game.play.GameEngine; 5 | 6 | public class StaticFlyInText { 7 | // String to draw 8 | private final String mainString; 9 | 10 | // Timings 11 | private final int flyInTime; 12 | // Vector array of positions 13 | private final DoubleVector[] letterPositions; 14 | // Start location 15 | private final DoubleVector[] startLocation; 16 | // Destination vector 17 | private final DoubleVector[] destinationLocation; 18 | // Text scale 19 | private final float textScale; 20 | // Lifetime variable 21 | private int currentLifetime; 22 | // Colour 23 | private int textColour; 24 | 25 | /** 26 | * Create a text object that has its letters fly in from various points on the edges and stays in one spot. 27 | * 28 | * @param text String to draw. 29 | * @param destinationX X-position of pixel of destination. 30 | * @param destinationY Y-position of pixel of destination. 31 | * @param timeIn Frames to fly in. 32 | * @param colour Text colour. 33 | * @param scale Text scale (0.5f, 1.0f, 2.0f). 34 | * @param seed Random seed for position. 35 | */ 36 | public StaticFlyInText(String text, int destinationX, int destinationY, int timeIn, int colour, float scale, long seed) { 37 | mainString = text; 38 | flyInTime = timeIn; 39 | textColour = colour; 40 | textScale = scale; 41 | 42 | // Randomiser for start pos 43 | final Random positionRandomiser = new Random(seed); 44 | 45 | letterPositions = new DoubleVector[mainString.length()]; 46 | startLocation = new DoubleVector[mainString.length()]; 47 | destinationLocation = new DoubleVector[mainString.length()]; 48 | 49 | int sMod = 16; 50 | if (textScale == 2.0f) sMod = 32; 51 | if (textScale == 0.5f) sMod = 16; 52 | 53 | for (int i = 0; i < mainString.length(); i++) { 54 | int startX = 0, startY = 0; 55 | DoubleVector position = DoubleVector.zero(); 56 | 57 | double dec1 = positionRandomiser.nextDouble(); 58 | double dec2 = positionRandomiser.nextDouble(); 59 | 60 | if (dec1 < 0.5) { 61 | startX = -sMod; 62 | if (dec2 < 0.5) startX = 41 * sMod; 63 | 64 | startY = (positionRandomiser.nextInt(32 * sMod)) - sMod; 65 | } else { 66 | startY = -sMod; 67 | if (dec2 < 0.5) startY = 31 * sMod; 68 | 69 | startX = (positionRandomiser.nextInt(42 * sMod)) - sMod; 70 | } 71 | 72 | position = new DoubleVector(startX, startY, false); 73 | 74 | letterPositions[i] = position; 75 | startLocation[i] = position; 76 | destinationLocation[i] = new DoubleVector(destinationX + (sMod * i), destinationY, false); 77 | } 78 | 79 | currentLifetime = 0; 80 | } 81 | 82 | public int getTextColour() { 83 | return textColour; 84 | } 85 | 86 | public void setTextColour(int textColour) { 87 | this.textColour = textColour; 88 | } 89 | 90 | /** 91 | * Updates the position and lifetime of this object. 92 | */ 93 | public void update() { 94 | if (currentLifetime < flyInTime) { 95 | currentLifetime++; 96 | 97 | for (int i = 0; i < letterPositions.length; i++) { 98 | int v1 = (int) (Interpolation.lerp(startLocation[i].getX(), destinationLocation[i].getX(), ((double) (currentLifetime) / flyInTime))); 99 | int v2 = (int) (Interpolation.lerp(startLocation[i].getY(), destinationLocation[i].getY(), ((double) (currentLifetime) / flyInTime))); 100 | letterPositions[i] = new DoubleVector(v1, v2, false); 101 | } 102 | } 103 | } 104 | 105 | /** 106 | * Draws the text at its current position. 107 | */ 108 | public void draw(GameEngine engine) { 109 | for (int j = 0; j < letterPositions.length; j++) { 110 | GameTextUtilities.drawDirectText( 111 | engine, 112 | (int) letterPositions[j].getX(), (int) letterPositions[j].getY(), 113 | GameTextUtilities.Text.custom(String.valueOf(mainString.charAt(j)), textColour, textScale) 114 | ); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/O4.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class O4 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 1, 1 }, 10 | new int[] { 1, 1 } 11 | } 12 | }; 13 | private final int state; 14 | private int[] location; 15 | private int powerup; 16 | 17 | public O4(int x, int y) { 18 | location = new int[] { x, y }; 19 | state = 0; 20 | powerup = 0; 21 | } 22 | 23 | @Override 24 | public int getPowerup() { 25 | return powerup; 26 | } 27 | 28 | @Override 29 | public void setPowerup(int powerup) { 30 | this.powerup = powerup; 31 | } 32 | 33 | @Override 34 | public int getScore() { 35 | return 100; 36 | } 37 | 38 | @Override 39 | public int getWidth() { 40 | return 2; 41 | } 42 | 43 | @Override 44 | public int getHeight() { 45 | return 2; 46 | } 47 | 48 | @Override 49 | public int getX() { 50 | return location[0]; 51 | } 52 | 53 | @Override 54 | public int getY() { 55 | return location[1]; 56 | } 57 | 58 | @Override 59 | public int[] getLocation() { 60 | return location; 61 | } 62 | 63 | @Override 64 | public int[][] getContents() { 65 | return contents[state]; 66 | } 67 | 68 | @Override 69 | public int[] getCursorOffset() { 70 | return new int[] { 0, 0 }; 71 | } 72 | 73 | @Override 74 | public double getConveyorYOffset() { 75 | return 0.5; 76 | } 77 | 78 | @Override 79 | public int getState() { 80 | return state; 81 | } 82 | 83 | @Override 84 | public int getColour() { 85 | return Block.BLOCK_COLOR_GREEN; 86 | } 87 | 88 | @Override 89 | public int[][] getConveyorBoundingBox() { 90 | int minX, minY, maxX, maxY; 91 | 92 | minX = contents[0][0].length - 1; 93 | minY = contents[0].length - 1; 94 | maxX = 0; 95 | maxY = 0; 96 | 97 | for (int y = 0; y < contents[0].length; y++) { 98 | for (int x = 0; x < contents[0][0].length; x++) { 99 | if (contents[state][y][x] != 0) { 100 | if (x < minX) minX = x; 101 | if (y < minY) minY = y; 102 | if (x > maxX) maxX = x; 103 | if (y > maxY) maxY = y; 104 | } 105 | } 106 | } 107 | 108 | maxX++; 109 | maxY++; 110 | 111 | int[] tlc, brc; 112 | tlc = new int[] { 113 | location[0] + (minX * 16), 114 | location[1] + (minY * 16) 115 | }; 116 | brc = new int[] { 117 | location[0] + (maxX * 16), 118 | location[1] + (maxY * 16) 119 | }; 120 | 121 | return new int[][] { tlc, brc }; 122 | } 123 | 124 | @Override 125 | public int[][][] getCursorBoundingBox() { 126 | ArrayList boxes = new ArrayList<>(); 127 | 128 | for (int y = 0; y < contents[state].length; y++) { 129 | for (int x = 0; x < contents[state][0].length; x++) { 130 | if (contents[state][y][x] != 0) { 131 | boxes.add( 132 | new int[][] { 133 | new int[] { 134 | location[0] + (x * 16), 135 | location[1] + (y * 16) 136 | }, 137 | new int[] { 138 | location[0] + ((x + 1) * 16), 139 | location[1] + ((y + 1) * 16) 140 | } 141 | } 142 | ); 143 | } 144 | } 145 | } 146 | 147 | int[][][] arr = new int[boxes.size()][][]; 148 | 149 | int i = 0; 150 | for (int[][] iss : boxes) { 151 | arr[i] = iss.clone(); 152 | i++; 153 | } 154 | 155 | return arr; 156 | } 157 | 158 | @Override 159 | public void rotate() { 160 | // DO NOTHING. 161 | } 162 | 163 | @Override 164 | public void setLocation(int x, int y) { 165 | location = new int[] { x, y }; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/backgroundtypes/BackgroundImageSequenceAnim.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.backgroundtypes; 2 | 3 | import mu.nu.nullpo.game.play.GameEngine; 4 | import zeroxfc.nullpo.custom.libs.CustomResourceHolder; 5 | 6 | public class BackgroundImageSequenceAnim extends AnimatedBackgroundHook { 7 | private final int frameTime; 8 | private final int frameCount; 9 | private final boolean pingPong; 10 | private int currentTick; 11 | private int currentFrame; 12 | private boolean forward; 13 | 14 | { 15 | ID = AnimatedBackgroundHook.ANIMATION_IMAGE_SEQUENCE_ANIM; 16 | } 17 | 18 | public BackgroundImageSequenceAnim(String[] filePaths, int frameTime, boolean pingPong) { 19 | customHolder = new CustomResourceHolder(); 20 | 21 | for (int i = 0; i < filePaths.length; i++) { 22 | customHolder.loadImage(filePaths[i], "frame" + i); 23 | 24 | int[] dim = customHolder.getImageDimensions("frame" + i); 25 | if (dim[0] != 640 || dim[1] != 480) 26 | log.warn("Image at " + filePaths[i] + " is not 640x480. It may not render correctly."); 27 | } 28 | 29 | this.frameTime = frameTime; 30 | this.pingPong = pingPong; 31 | this.frameCount = filePaths.length; 32 | 33 | setup(); 34 | 35 | log.debug("Sequence frame animation background created (Frames: " + filePaths.length + ")."); 36 | } 37 | 38 | private void setup() { 39 | forward = true; 40 | currentFrame = 0; 41 | currentTick = 0; 42 | } 43 | 44 | 45 | /** 46 | * Performs an update tick on the background. Advisably used in onLast. 47 | */ 48 | @Override 49 | public void update() { 50 | currentTick++; 51 | if (currentTick >= frameTime) { 52 | currentTick = 0; 53 | 54 | if (pingPong) { 55 | if (forward) currentFrame++; 56 | else currentFrame--; 57 | 58 | if (currentFrame >= frameCount) { 59 | currentFrame -= 2; 60 | forward = false; 61 | } else if (currentFrame < 0) { 62 | currentFrame++; 63 | forward = true; 64 | } 65 | } else { 66 | currentFrame = (currentFrame + 1) % frameCount; 67 | } 68 | } 69 | } 70 | 71 | /** 72 | * Resets the background to its base state. 73 | */ 74 | @Override 75 | public void reset() { 76 | setup(); 77 | } 78 | 79 | /** 80 | * Draws the background to the game screen. 81 | * 82 | * @param engine Current GameEngine instance 83 | * @param playerID Current player ID (1P = 0) 84 | */ 85 | @Override 86 | public void draw(GameEngine engine, int playerID) { 87 | String i = "frame" + currentFrame; 88 | customHolder.drawOffsetImage(engine, i, 0, 0, 640, 480, 0, 0, 640, 480, 255, 255, 255, 255); 89 | } 90 | 91 | /** 92 | * Change BG to one of the default ones. 93 | * 94 | * @param bg New BG number 95 | */ 96 | @Override 97 | public void setBG(int bg) { 98 | log.warn("Image Sequence animation backgrounds do not support this operation. Please create a new instance."); 99 | } 100 | 101 | /** 102 | * Change BG to a custom BG using its file path. 103 | * 104 | * @param filePath File path of new background 105 | */ 106 | @Override 107 | public void setBG(String filePath) { 108 | log.warn("Image Sequence animation backgrounds do not support this operation. Please create a new instance."); 109 | } 110 | 111 | /** 112 | * Allows the hot-swapping of pre-loaded BGs from a storage instance of a CustomResourceHolder. 113 | * 114 | * @param holder Storage instance 115 | * @param name Image name 116 | */ 117 | @Override 118 | public void setBGFromHolder(CustomResourceHolder holder, String name) { 119 | log.warn("Image Sequence animation backgrounds do not support this operation. Please create a new instance."); 120 | } 121 | 122 | /** 123 | * This last one is important. In the case that any of the child types are used, it allows identification. 124 | * The identification can be used to allow casting during operations. 125 | * 126 | * @return Identification number of child class. 127 | */ 128 | @Override 129 | public int getID() { 130 | return ID; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/X5.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class X5 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 0, 1, 0 }, 10 | new int[] { 1, 1, 1 }, 11 | new int[] { 0, 1, 0 } 12 | } 13 | }; 14 | private final int state; 15 | private int[] location; 16 | private int powerup; 17 | 18 | public X5(int x, int y) { 19 | location = new int[] { x, y }; 20 | state = 0; 21 | powerup = 0; 22 | } 23 | 24 | @Override 25 | public int getPowerup() { 26 | return powerup; 27 | } 28 | 29 | @Override 30 | public void setPowerup(int powerup) { 31 | this.powerup = powerup; 32 | } 33 | 34 | @Override 35 | public int getScore() { 36 | return 725; 37 | } 38 | 39 | @Override 40 | public int getWidth() { 41 | return 3; 42 | } 43 | 44 | @Override 45 | public int getHeight() { 46 | return 3; 47 | } 48 | 49 | @Override 50 | public int getX() { 51 | return location[0]; 52 | } 53 | 54 | @Override 55 | public int getY() { 56 | return location[1]; 57 | } 58 | 59 | @Override 60 | public int[] getLocation() { 61 | return location; 62 | } 63 | 64 | @Override 65 | public int[][] getContents() { 66 | return contents[state]; 67 | } 68 | 69 | @Override 70 | public int[] getCursorOffset() { 71 | return new int[] { 1, 1 }; 72 | } 73 | 74 | @Override 75 | public double getConveyorYOffset() { 76 | return 1.0; 77 | } 78 | 79 | @Override 80 | public int getState() { 81 | return state; 82 | } 83 | 84 | @Override 85 | public int getColour() { 86 | return Block.BLOCK_COLOR_YELLOW; 87 | } 88 | 89 | @Override 90 | public int[][] getConveyorBoundingBox() { 91 | int minX, minY, maxX, maxY; 92 | 93 | minX = contents[0][0].length - 1; 94 | minY = contents[0].length - 1; 95 | maxX = 0; 96 | maxY = 0; 97 | 98 | for (int y = 0; y < contents[0].length; y++) { 99 | for (int x = 0; x < contents[0][0].length; x++) { 100 | if (contents[state][y][x] != 0) { 101 | if (x < minX) minX = x; 102 | if (y < minY) minY = y; 103 | if (x > maxX) maxX = x; 104 | if (y > maxY) maxY = y; 105 | } 106 | } 107 | } 108 | 109 | maxX++; 110 | maxY++; 111 | 112 | int[] tlc, brc; 113 | tlc = new int[] { 114 | location[0] + (minX * 16), 115 | location[1] + (minY * 16) 116 | }; 117 | brc = new int[] { 118 | location[0] + (maxX * 16), 119 | location[1] + (maxY * 16) 120 | }; 121 | 122 | return new int[][] { tlc, brc }; 123 | } 124 | 125 | @Override 126 | public int[][][] getCursorBoundingBox() { 127 | ArrayList boxes = new ArrayList<>(); 128 | 129 | for (int y = 0; y < contents[state].length; y++) { 130 | for (int x = 0; x < contents[state][0].length; x++) { 131 | if (contents[state][y][x] != 0) { 132 | boxes.add( 133 | new int[][] { 134 | new int[] { 135 | location[0] + (x * 16), 136 | location[1] + (y * 16) 137 | }, 138 | new int[] { 139 | location[0] + ((x + 1) * 16), 140 | location[1] + ((y + 1) * 16) 141 | } 142 | } 143 | ); 144 | } 145 | } 146 | } 147 | 148 | int[][][] arr = new int[boxes.size()][][]; 149 | 150 | int i = 0; 151 | for (int[][] iss : boxes) { 152 | arr[i] = iss.clone(); 153 | i++; 154 | } 155 | 156 | return arr; 157 | } 158 | 159 | @Override 160 | public void rotate() { 161 | // DO NOTHING 162 | } 163 | 164 | @Override 165 | public void setLocation(int x, int y) { 166 | location = new int[] { x, y }; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/gemswap/PowerGem.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.gemswap; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class PowerGem implements Gem { 6 | /** 7 | * Gem ID 8 | */ 9 | private static final int ID = GemField.GEMID_POWER; 10 | private final boolean special; 11 | /** 12 | * Class properties. 13 | */ 14 | private int[] location; 15 | private int colour; 16 | private boolean recentSwap; 17 | private boolean recentFall; 18 | private boolean matchedHorizontal; 19 | private boolean matchedVertical; 20 | private boolean actionConducted; 21 | private boolean destroy; 22 | 23 | public PowerGem(int x, int y, int colour) { 24 | location = new int[] { x, y }; 25 | this.colour = colour; 26 | 27 | recentSwap = false; 28 | recentFall = false; 29 | matchedHorizontal = false; 30 | matchedVertical = false; 31 | actionConducted = false; 32 | special = true; 33 | destroy = false; 34 | } 35 | 36 | @Override 37 | public int getID() { 38 | return ID; 39 | } 40 | 41 | @Override 42 | public int getColour() { 43 | return colour; 44 | } 45 | 46 | @Override 47 | public void setColour(int colour) { 48 | this.colour = colour; 49 | } 50 | 51 | @Override 52 | public int[] getLocation() { 53 | return location; 54 | } 55 | 56 | @Override 57 | public boolean getRecentSwap() { 58 | return recentSwap; 59 | } 60 | 61 | @Override 62 | public void setRecentSwap(boolean isRecentSwap) { 63 | recentSwap = isRecentSwap; 64 | } 65 | 66 | @Override 67 | public boolean getRecentFall() { 68 | return recentFall; 69 | } 70 | 71 | @Override 72 | public void setRecentFall(boolean isRecentFall) { 73 | recentFall = isRecentFall; 74 | } 75 | 76 | @Override 77 | public void setLocation(int x, int y) { 78 | location = new int[] { x, y }; 79 | } 80 | 81 | @Override 82 | public int conductAction(GemField field, int[] args, ArrayList eventList) { 83 | int ctr = 0; 84 | 85 | int[][] testLocations = { 86 | { -1, -1 }, { 0, -1 }, { 1, -1 }, 87 | { -1, 0 }, { 1, 0 }, 88 | { -1, 1 }, { 0, 1 }, { 1, 1 } 89 | }; 90 | 91 | for (int[] is : testLocations) { 92 | int tX = location[0] + is[0]; 93 | int tY = location[1] + is[1]; 94 | 95 | if (field.getCell(tX, tY) != null) { 96 | if (field.getCell(tX, tY).getID() != GemField.GEMID_EMPTY && 97 | !field.getCell(tX, tY).getActionConducted()) { 98 | ctr++; 99 | field.getCell(tX, tY).conductAction(field, new int[] { colour }, eventList); 100 | field.getCell(tX, tY).setDestroy(true); 101 | } 102 | } 103 | } 104 | 105 | actionConducted = true; 106 | eventList.add(new ScoreEvent(ctr, location[0], location[1], ID, colour)); 107 | 108 | return ctr; 109 | } 110 | 111 | @Override 112 | public boolean getSpecial() { 113 | return special; 114 | } 115 | 116 | @Override 117 | public boolean getMatchedHorizontal() { 118 | return matchedHorizontal; 119 | } 120 | 121 | @Override 122 | public void setMatchedHorizontal(boolean isMatched) { 123 | matchedHorizontal = isMatched; 124 | } 125 | 126 | @Override 127 | public boolean getMatchedVertical() { 128 | return matchedVertical; 129 | } 130 | 131 | @Override 132 | public void setMatchedVertical(boolean isMatched) { 133 | matchedVertical = isMatched; 134 | } 135 | 136 | @Override 137 | public boolean getActionConducted() { 138 | return actionConducted; 139 | } 140 | 141 | @Override 142 | public void setActionConducted(boolean isConduted) { 143 | actionConducted = isConduted; 144 | } 145 | 146 | @Override 147 | public Gem getSelf() { 148 | return new PowerGem(location[0], location[1], colour); 149 | } 150 | 151 | @Override 152 | public boolean getDestroy() { 153 | // TODO Auto-generated method stub 154 | return destroy; 155 | } 156 | 157 | @Override 158 | public void setDestroy(boolean shouldDestroy) { 159 | // TODO Auto-generated method stub 160 | destroy = shouldDestroy; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/particles/BlockParticle.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.particles; 2 | 3 | import java.util.Random; 4 | import mu.nu.nullpo.game.component.Block; 5 | import mu.nu.nullpo.game.event.EventReceiver; 6 | import mu.nu.nullpo.game.play.GameEngine; 7 | import zeroxfc.nullpo.custom.libs.DoubleVector; 8 | import zeroxfc.nullpo.custom.libs.RendererExtension; 9 | 10 | public class BlockParticle { 11 | // Lifetime 12 | private final int maxLifetime; 13 | // Block for use in texture. 14 | private final Block objectTexture; 15 | // Position 16 | private DoubleVector position; 17 | // Velocity 18 | private DoubleVector velocity; 19 | // Size 20 | private float size; 21 | // Current time alive 22 | private int currentLifetime; 23 | 24 | // Flash 25 | private boolean isFlashing; 26 | 27 | private final RendererExtension rendererExtension; 28 | 29 | /** 30 | * Creates a block particle. 31 | * 32 | * @param block Block to import parameters from. 33 | * @param position Starting location. 34 | * @param maxVelocity Highest absolute speed. 35 | * @param timeToLive Frames to live. 36 | * @param randomiser Randomiser used for setting speed and direction. 37 | */ 38 | public BlockParticle(Block block, RendererExtension rendererExtension, DoubleVector position, double maxVelocity, int timeToLive, boolean flash, Random randomiser) { 39 | objectTexture = new Block(); 40 | objectTexture.copy(block); 41 | this.position = position; 42 | this.rendererExtension = rendererExtension; 43 | 44 | double speed = randomiser.nextDouble() * maxVelocity; 45 | double angle = randomiser.nextDouble() * Math.PI * 2; 46 | velocity = new DoubleVector(speed, angle, true); 47 | isFlashing = flash; 48 | 49 | maxLifetime = timeToLive; 50 | currentLifetime = 0; 51 | size = 1; 52 | } 53 | 54 | public BlockParticle(Block block, RendererExtension rendererExtension, DoubleVector position, DoubleVector velocity, int timeToLive) { 55 | objectTexture = new Block(); 56 | objectTexture.copy(block); 57 | this.rendererExtension = rendererExtension; 58 | 59 | this.position = position; 60 | this.velocity = velocity; 61 | 62 | maxLifetime = timeToLive; 63 | currentLifetime = 0; 64 | size = 1; 65 | } 66 | 67 | /** 68 | * Update position and lifetime data. 69 | */ 70 | public void update(int animType) { 71 | position = DoubleVector.add(position, velocity); 72 | 73 | switch (animType) { 74 | case BlockParticleCollection.ANIMATION_DTET: 75 | if (currentLifetime < (maxLifetime * 0.75)) { 76 | velocity.setDirection(velocity.getDirection() + (Math.PI / maxLifetime)); 77 | } 78 | break; 79 | case BlockParticleCollection.ANIMATION_TGM: 80 | velocity = DoubleVector.add(velocity, new DoubleVector(0, 0.980665 / 2.25, false)); 81 | size += (1f / 60f); 82 | break; 83 | } 84 | 85 | currentLifetime++; 86 | } 87 | 88 | /** 89 | * Draw the block particle. 90 | * 91 | * @param receiver EventReceiver doing the drawing. 92 | */ 93 | public void draw(GameEngine engine, EventReceiver receiver, int playerID, int animType) { 94 | if (engine.displaysize != -1) { 95 | if (animType == BlockParticleCollection.ANIMATION_TGM) { 96 | rendererExtension.drawScaledBlock(receiver, (int) position.getX() + (int) (((engine.displaysize == 0) ? 2 : 4) * size), (int) position.getY() + ((engine.displaysize == 0) ? 2 : 4), 97 | objectTexture.color, objectTexture.skin, 98 | objectTexture.getAttribute(Block.BLOCK_ATTRIBUTE_BONE), 0.5f, 1f, 99 | ((engine.displaysize == 0) ? 1f : 2f) * size, 0); 100 | } 101 | rendererExtension.drawScaledBlock(receiver, (int) position.getX(), (int) position.getY(), 102 | objectTexture.color, objectTexture.skin, 103 | objectTexture.getAttribute(Block.BLOCK_ATTRIBUTE_BONE), (isFlashing && ((currentLifetime / 2) % 2 == 0)) ? -0.8f : 0f, (animType == BlockParticleCollection.ANIMATION_DTET) ? 0.667f : 1f, 104 | ((engine.displaysize == 0) ? 1f : 2f) * size, 0); 105 | } 106 | } 107 | 108 | public int getMaxLifetime() { 109 | return maxLifetime; 110 | } 111 | 112 | public int getCurrentLifetime() { 113 | return currentLifetime; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/I2.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class I2 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 1, 1 }, 10 | new int[] { 0, 0 } 11 | }, 12 | new int[][] { 13 | new int[] { 1, 0 }, 14 | new int[] { 1, 0 } 15 | } 16 | }; 17 | 18 | private int[] location; 19 | private int state; 20 | private int powerup; 21 | 22 | public I2(int x, int y) { 23 | location = new int[] { x, y }; 24 | state = 0; 25 | powerup = 0; 26 | } 27 | 28 | @Override 29 | public int getPowerup() { 30 | return powerup; 31 | } 32 | 33 | @Override 34 | public void setPowerup(int powerup) { 35 | this.powerup = powerup; 36 | } 37 | 38 | @Override 39 | public int getScore() { 40 | return 50; 41 | } 42 | 43 | @Override 44 | public int getWidth() { 45 | return state == 0 ? 2 : 1; 46 | } 47 | 48 | @Override 49 | public int getHeight() { 50 | return state == 0 ? 1 : 2; 51 | } 52 | 53 | @Override 54 | public int getX() { 55 | return location[0]; 56 | } 57 | 58 | @Override 59 | public int getY() { 60 | return location[1]; 61 | } 62 | 63 | @Override 64 | public int[] getLocation() { 65 | return location; 66 | } 67 | 68 | @Override 69 | public int[][] getContents() { 70 | return contents[state]; 71 | } 72 | 73 | @Override 74 | public int[] getCursorOffset() { 75 | return new int[] { 0, 0 }; 76 | } 77 | 78 | @Override 79 | public double getConveyorYOffset() { 80 | return 0.0; 81 | } 82 | 83 | @Override 84 | public int getState() { 85 | return state; 86 | } 87 | 88 | @Override 89 | public int getColour() { 90 | return Block.BLOCK_COLOR_ORANGE; 91 | } 92 | 93 | @Override 94 | public int[][] getConveyorBoundingBox() { 95 | int minX, minY, maxX, maxY; 96 | 97 | minX = contents[0][0].length - 1; 98 | minY = contents[0].length - 1; 99 | maxX = 0; 100 | maxY = 0; 101 | 102 | for (int y = 0; y < contents[0].length; y++) { 103 | for (int x = 0; x < contents[0][0].length; x++) { 104 | if (contents[state][y][x] != 0) { 105 | if (x < minX) minX = x; 106 | if (y < minY) minY = y; 107 | if (x > maxX) maxX = x; 108 | if (y > maxY) maxY = y; 109 | } 110 | } 111 | } 112 | 113 | maxX++; 114 | maxY++; 115 | 116 | int[] tlc, brc; 117 | tlc = new int[] { 118 | location[0] + (minX * 16), 119 | location[1] + (minY * 16) 120 | }; 121 | brc = new int[] { 122 | location[0] + (maxX * 16), 123 | location[1] + (maxY * 16) 124 | }; 125 | 126 | return new int[][] { tlc, brc }; 127 | } 128 | 129 | @Override 130 | public int[][][] getCursorBoundingBox() { 131 | ArrayList boxes = new ArrayList<>(); 132 | 133 | for (int y = 0; y < contents[state].length; y++) { 134 | for (int x = 0; x < contents[state][0].length; x++) { 135 | if (contents[state][y][x] != 0) { 136 | boxes.add( 137 | new int[][] { 138 | new int[] { 139 | location[0] + (x * 16), 140 | location[1] + (y * 16) 141 | }, 142 | new int[] { 143 | location[0] + ((x + 1) * 16), 144 | location[1] + ((y + 1) * 16) 145 | } 146 | } 147 | ); 148 | } 149 | } 150 | } 151 | 152 | int[][][] arr = new int[boxes.size()][][]; 153 | 154 | int i = 0; 155 | for (int[][] iss : boxes) { 156 | arr[i] = iss.clone(); 157 | i++; 158 | } 159 | 160 | return arr; 161 | } 162 | 163 | @Override 164 | public void rotate() { 165 | state = (state + 1) % 2; 166 | } 167 | 168 | @Override 169 | public void setLocation(int x, int y) { 170 | location = new int[] { x, y }; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/Z5.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class Z5 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 1, 1, 0 }, 10 | new int[] { 0, 1, 0 }, 11 | new int[] { 0, 1, 1 } 12 | }, 13 | new int[][] { 14 | new int[] { 0, 0, 1 }, 15 | new int[] { 1, 1, 1 }, 16 | new int[] { 1, 0, 0 }, 17 | } 18 | }; 19 | 20 | private int[] location; 21 | private int state; 22 | private int powerup; 23 | 24 | public Z5(int x, int y) { 25 | location = new int[] { x, y }; 26 | state = 0; 27 | powerup = 0; 28 | } 29 | 30 | @Override 31 | public int getPowerup() { 32 | return powerup; 33 | } 34 | 35 | @Override 36 | public void setPowerup(int powerup) { 37 | this.powerup = powerup; 38 | } 39 | 40 | @Override 41 | public int getScore() { 42 | return 775; 43 | } 44 | 45 | @Override 46 | public int getWidth() { 47 | return 3; 48 | } 49 | 50 | @Override 51 | public int getHeight() { 52 | return 3; 53 | } 54 | 55 | @Override 56 | public int getX() { 57 | return location[0]; 58 | } 59 | 60 | @Override 61 | public int getY() { 62 | return location[1]; 63 | } 64 | 65 | @Override 66 | public int[] getLocation() { 67 | return location; 68 | } 69 | 70 | @Override 71 | public int[][] getContents() { 72 | return contents[state]; 73 | } 74 | 75 | @Override 76 | public int[] getCursorOffset() { 77 | return new int[] { 1, 1 }; 78 | } 79 | 80 | @Override 81 | public double getConveyorYOffset() { 82 | return 1.0; 83 | } 84 | 85 | @Override 86 | public int getState() { 87 | return state; 88 | } 89 | 90 | @Override 91 | public int getColour() { 92 | return Block.BLOCK_COLOR_RED; 93 | } 94 | 95 | @Override 96 | public int[][] getConveyorBoundingBox() { 97 | int minX, minY, maxX, maxY; 98 | 99 | minX = contents[0][0].length - 1; 100 | minY = contents[0].length - 1; 101 | maxX = 0; 102 | maxY = 0; 103 | 104 | for (int y = 0; y < contents[0].length; y++) { 105 | for (int x = 0; x < contents[0][0].length; x++) { 106 | if (contents[state][y][x] != 0) { 107 | if (x < minX) minX = x; 108 | if (y < minY) minY = y; 109 | if (x > maxX) maxX = x; 110 | if (y > maxY) maxY = y; 111 | } 112 | } 113 | } 114 | 115 | maxX++; 116 | maxY++; 117 | 118 | int[] tlc, brc; 119 | tlc = new int[] { 120 | location[0] + (minX * 16), 121 | location[1] + (minY * 16) 122 | }; 123 | brc = new int[] { 124 | location[0] + (maxX * 16), 125 | location[1] + (maxY * 16) 126 | }; 127 | 128 | return new int[][] { tlc, brc }; 129 | } 130 | 131 | @Override 132 | public int[][][] getCursorBoundingBox() { 133 | ArrayList boxes = new ArrayList<>(); 134 | 135 | for (int y = 0; y < contents[state].length; y++) { 136 | for (int x = 0; x < contents[state][0].length; x++) { 137 | if (contents[state][y][x] != 0) { 138 | boxes.add( 139 | new int[][] { 140 | new int[] { 141 | location[0] + (x * 16), 142 | location[1] + (y * 16) 143 | }, 144 | new int[] { 145 | location[0] + ((x + 1) * 16), 146 | location[1] + ((y + 1) * 16) 147 | } 148 | } 149 | ); 150 | } 151 | } 152 | } 153 | 154 | int[][][] arr = new int[boxes.size()][][]; 155 | 156 | int i = 0; 157 | for (int[][] iss : boxes) { 158 | arr[i] = iss.clone(); 159 | i++; 160 | } 161 | 162 | return arr; 163 | } 164 | 165 | @Override 166 | public void rotate() { 167 | state = (state + 1) % 2; 168 | } 169 | 170 | @Override 171 | public void setLocation(int x, int y) { 172 | location = new int[] { x, y }; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/S5.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class S5 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 0, 1, 1 }, 10 | new int[] { 0, 1, 0 }, 11 | new int[] { 1, 1, 0 } 12 | }, 13 | new int[][] { 14 | new int[] { 1, 0, 0 }, 15 | new int[] { 1, 1, 1 }, 16 | new int[] { 0, 0, 1 }, 17 | } 18 | }; 19 | 20 | private int[] location; 21 | private int state; 22 | private int powerup; 23 | 24 | public S5(int x, int y) { 25 | location = new int[] { x, y }; 26 | state = 0; 27 | powerup = 0; 28 | } 29 | 30 | @Override 31 | public int getPowerup() { 32 | return powerup; 33 | } 34 | 35 | @Override 36 | public void setPowerup(int powerup) { 37 | this.powerup = powerup; 38 | } 39 | 40 | @Override 41 | public int getScore() { 42 | return 775; 43 | } 44 | 45 | @Override 46 | public int getWidth() { 47 | return 3; 48 | } 49 | 50 | @Override 51 | public int getHeight() { 52 | return 3; 53 | } 54 | 55 | @Override 56 | public int getX() { 57 | return location[0]; 58 | } 59 | 60 | @Override 61 | public int getY() { 62 | return location[1]; 63 | } 64 | 65 | @Override 66 | public int[] getLocation() { 67 | return location; 68 | } 69 | 70 | @Override 71 | public int[][] getContents() { 72 | return contents[state]; 73 | } 74 | 75 | @Override 76 | public int[] getCursorOffset() { 77 | return new int[] { 1, 1 }; 78 | } 79 | 80 | @Override 81 | public double getConveyorYOffset() { 82 | return 1.0; 83 | } 84 | 85 | @Override 86 | public int getState() { 87 | return state; 88 | } 89 | 90 | @Override 91 | public int getColour() { 92 | return Block.BLOCK_COLOR_ORANGE; 93 | } 94 | 95 | @Override 96 | public int[][] getConveyorBoundingBox() { 97 | int minX, minY, maxX, maxY; 98 | 99 | minX = contents[0][0].length - 1; 100 | minY = contents[0].length - 1; 101 | maxX = 0; 102 | maxY = 0; 103 | 104 | for (int y = 0; y < contents[0].length; y++) { 105 | for (int x = 0; x < contents[0][0].length; x++) { 106 | if (contents[state][y][x] != 0) { 107 | if (x < minX) minX = x; 108 | if (y < minY) minY = y; 109 | if (x > maxX) maxX = x; 110 | if (y > maxY) maxY = y; 111 | } 112 | } 113 | } 114 | 115 | maxX++; 116 | maxY++; 117 | 118 | int[] tlc, brc; 119 | tlc = new int[] { 120 | location[0] + (minX * 16), 121 | location[1] + (minY * 16) 122 | }; 123 | brc = new int[] { 124 | location[0] + (maxX * 16), 125 | location[1] + (maxY * 16) 126 | }; 127 | 128 | return new int[][] { tlc, brc }; 129 | } 130 | 131 | @Override 132 | public int[][][] getCursorBoundingBox() { 133 | ArrayList boxes = new ArrayList<>(); 134 | 135 | for (int y = 0; y < contents[state].length; y++) { 136 | for (int x = 0; x < contents[state][0].length; x++) { 137 | if (contents[state][y][x] != 0) { 138 | boxes.add( 139 | new int[][] { 140 | new int[] { 141 | location[0] + (x * 16), 142 | location[1] + (y * 16) 143 | }, 144 | new int[] { 145 | location[0] + ((x + 1) * 16), 146 | location[1] + ((y + 1) * 16) 147 | } 148 | } 149 | ); 150 | } 151 | } 152 | } 153 | 154 | int[][][] arr = new int[boxes.size()][][]; 155 | 156 | int i = 0; 157 | for (int[][] iss : boxes) { 158 | arr[i] = iss.clone(); 159 | i++; 160 | } 161 | 162 | return arr; 163 | } 164 | 165 | @Override 166 | public void rotate() { 167 | state = (state + 1) % 2; 168 | } 169 | 170 | @Override 171 | public void setLocation(int x, int y) { 172 | location = new int[] { x, y }; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/I3.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class I3 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 0, 0, 0 }, 10 | new int[] { 1, 1, 1 }, 11 | new int[] { 0, 0, 0 } 12 | }, 13 | new int[][] { 14 | new int[] { 0, 1, 0 }, 15 | new int[] { 0, 1, 0 }, 16 | new int[] { 0, 1, 0 }, 17 | } 18 | }; 19 | 20 | private int[] location; 21 | private int state; 22 | private int powerup; 23 | 24 | public I3(int x, int y) { 25 | location = new int[] { x, y }; 26 | state = 0; 27 | powerup = 0; 28 | } 29 | 30 | @Override 31 | public int getPowerup() { 32 | return powerup; 33 | } 34 | 35 | @Override 36 | public void setPowerup(int powerup) { 37 | this.powerup = powerup; 38 | } 39 | 40 | @Override 41 | public int getScore() { 42 | return 75; 43 | } 44 | 45 | @Override 46 | public int getWidth() { 47 | return state == 0 ? 3 : 1; 48 | } 49 | 50 | @Override 51 | public int getHeight() { 52 | return state == 0 ? 1 : 3; 53 | } 54 | 55 | @Override 56 | public int getX() { 57 | return location[0]; 58 | } 59 | 60 | @Override 61 | public int getY() { 62 | return location[1]; 63 | } 64 | 65 | @Override 66 | public int[] getLocation() { 67 | return location; 68 | } 69 | 70 | @Override 71 | public int[][] getContents() { 72 | return contents[state]; 73 | } 74 | 75 | @Override 76 | public int[] getCursorOffset() { 77 | return new int[] { 1, 1 }; 78 | } 79 | 80 | @Override 81 | public double getConveyorYOffset() { 82 | return 1.0; 83 | } 84 | 85 | @Override 86 | public int getState() { 87 | return state; 88 | } 89 | 90 | @Override 91 | public int getColour() { 92 | return Block.BLOCK_COLOR_RED; 93 | } 94 | 95 | @Override 96 | public int[][] getConveyorBoundingBox() { 97 | int minX, minY, maxX, maxY; 98 | 99 | minX = contents[0][0].length - 1; 100 | minY = contents[0].length - 1; 101 | maxX = 0; 102 | maxY = 0; 103 | 104 | for (int y = 0; y < contents[0].length; y++) { 105 | for (int x = 0; x < contents[0][0].length; x++) { 106 | if (contents[state][y][x] != 0) { 107 | if (x < minX) minX = x; 108 | if (y < minY) minY = y; 109 | if (x > maxX) maxX = x; 110 | if (y > maxY) maxY = y; 111 | } 112 | } 113 | } 114 | 115 | maxX++; 116 | maxY++; 117 | 118 | int[] tlc, brc; 119 | tlc = new int[] { 120 | location[0] + (minX * 16), 121 | location[1] + (minY * 16) 122 | }; 123 | brc = new int[] { 124 | location[0] + (maxX * 16), 125 | location[1] + (maxY * 16) 126 | }; 127 | 128 | return new int[][] { tlc, brc }; 129 | } 130 | 131 | @Override 132 | public int[][][] getCursorBoundingBox() { 133 | ArrayList boxes = new ArrayList<>(); 134 | 135 | for (int y = 0; y < contents[state].length; y++) { 136 | for (int x = 0; x < contents[state][0].length; x++) { 137 | if (contents[state][y][x] != 0) { 138 | boxes.add( 139 | new int[][] { 140 | new int[] { 141 | location[0] + (x * 16), 142 | location[1] + (y * 16) 143 | }, 144 | new int[] { 145 | location[0] + ((x + 1) * 16), 146 | location[1] + ((y + 1) * 16) 147 | } 148 | } 149 | ); 150 | } 151 | } 152 | } 153 | 154 | int[][][] arr = new int[boxes.size()][][]; 155 | 156 | int i = 0; 157 | for (int[][] iss : boxes) { 158 | arr[i] = iss.clone(); 159 | i++; 160 | } 161 | 162 | return arr; 163 | } 164 | 165 | @Override 166 | public void rotate() { 167 | state = (state + 1) % 2; 168 | } 169 | 170 | @Override 171 | public void setLocation(int x, int y) { 172 | location = new int[] { x, y }; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/S4.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class S4 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 0, 0, 0 }, 10 | new int[] { 0, 1, 1 }, 11 | new int[] { 1, 1, 0 } 12 | }, 13 | new int[][] { 14 | new int[] { 1, 0, 0 }, 15 | new int[] { 1, 1, 0 }, 16 | new int[] { 0, 1, 0 }, 17 | } 18 | }; 19 | 20 | private int[] location; 21 | private int state; 22 | private int powerup; 23 | 24 | public S4(int x, int y) { 25 | location = new int[] { x, y }; 26 | state = 0; 27 | powerup = 0; 28 | } 29 | 30 | @Override 31 | public int getPowerup() { 32 | return powerup; 33 | } 34 | 35 | @Override 36 | public void setPowerup(int powerup) { 37 | this.powerup = powerup; 38 | } 39 | 40 | @Override 41 | public int getScore() { 42 | return 275; 43 | } 44 | 45 | @Override 46 | public int getWidth() { 47 | return state == 0 ? 3 : 2; 48 | } 49 | 50 | @Override 51 | public int getHeight() { 52 | return state == 0 ? 2 : 3; 53 | } 54 | 55 | @Override 56 | public int getX() { 57 | return location[0]; 58 | } 59 | 60 | @Override 61 | public int getY() { 62 | return location[1]; 63 | } 64 | 65 | @Override 66 | public int[] getLocation() { 67 | return location; 68 | } 69 | 70 | @Override 71 | public int[][] getContents() { 72 | return contents[state]; 73 | } 74 | 75 | @Override 76 | public int[] getCursorOffset() { 77 | return new int[] { 1, 1 }; 78 | } 79 | 80 | @Override 81 | public double getConveyorYOffset() { 82 | return 1.5; 83 | } 84 | 85 | @Override 86 | public int getState() { 87 | return state; 88 | } 89 | 90 | @Override 91 | public int getColour() { 92 | return Block.BLOCK_COLOR_PURPLE; 93 | } 94 | 95 | @Override 96 | public int[][] getConveyorBoundingBox() { 97 | int minX, minY, maxX, maxY; 98 | 99 | minX = contents[0][0].length - 1; 100 | minY = contents[0].length - 1; 101 | maxX = 0; 102 | maxY = 0; 103 | 104 | for (int y = 0; y < contents[0].length; y++) { 105 | for (int x = 0; x < contents[0][0].length; x++) { 106 | if (contents[state][y][x] != 0) { 107 | if (x < minX) minX = x; 108 | if (y < minY) minY = y; 109 | if (x > maxX) maxX = x; 110 | if (y > maxY) maxY = y; 111 | } 112 | } 113 | } 114 | 115 | maxX++; 116 | maxY++; 117 | 118 | int[] tlc, brc; 119 | tlc = new int[] { 120 | location[0] + (minX * 16), 121 | location[1] + (minY * 16) 122 | }; 123 | brc = new int[] { 124 | location[0] + (maxX * 16), 125 | location[1] + (maxY * 16) 126 | }; 127 | 128 | return new int[][] { tlc, brc }; 129 | } 130 | 131 | @Override 132 | public int[][][] getCursorBoundingBox() { 133 | ArrayList boxes = new ArrayList<>(); 134 | 135 | for (int y = 0; y < contents[state].length; y++) { 136 | for (int x = 0; x < contents[state][0].length; x++) { 137 | if (contents[state][y][x] != 0) { 138 | boxes.add( 139 | new int[][] { 140 | new int[] { 141 | location[0] + (x * 16), 142 | location[1] + (y * 16) 143 | }, 144 | new int[] { 145 | location[0] + ((x + 1) * 16), 146 | location[1] + ((y + 1) * 16) 147 | } 148 | } 149 | ); 150 | } 151 | } 152 | } 153 | 154 | int[][][] arr = new int[boxes.size()][][]; 155 | 156 | int i = 0; 157 | for (int[][] iss : boxes) { 158 | arr[i] = iss.clone(); 159 | i++; 160 | } 161 | 162 | return arr; 163 | } 164 | 165 | @Override 166 | public void rotate() { 167 | state = (state + 1) % 2; 168 | } 169 | 170 | @Override 171 | public void setLocation(int x, int y) { 172 | location = new int[] { x, y }; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/Z4.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class Z4 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 0, 0, 0 }, 10 | new int[] { 1, 1, 0 }, 11 | new int[] { 0, 1, 1 } 12 | }, 13 | new int[][] { 14 | new int[] { 0, 0, 1 }, 15 | new int[] { 0, 1, 1 }, 16 | new int[] { 0, 1, 0 }, 17 | } 18 | }; 19 | 20 | private int[] location; 21 | private int state; 22 | private int powerup; 23 | 24 | public Z4(int x, int y) { 25 | location = new int[] { x, y }; 26 | state = 0; 27 | powerup = 0; 28 | } 29 | 30 | @Override 31 | public int getPowerup() { 32 | return powerup; 33 | } 34 | 35 | @Override 36 | public void setPowerup(int powerup) { 37 | this.powerup = powerup; 38 | } 39 | 40 | @Override 41 | public int getScore() { 42 | return 275; 43 | } 44 | 45 | @Override 46 | public int getWidth() { 47 | return state == 0 ? 3 : 2; 48 | } 49 | 50 | @Override 51 | public int getHeight() { 52 | return state == 0 ? 2 : 3; 53 | } 54 | 55 | @Override 56 | public int getX() { 57 | return location[0]; 58 | } 59 | 60 | @Override 61 | public int getY() { 62 | return location[1]; 63 | } 64 | 65 | @Override 66 | public int[] getLocation() { 67 | return location; 68 | } 69 | 70 | @Override 71 | public int[][] getContents() { 72 | return contents[state]; 73 | } 74 | 75 | @Override 76 | public int[] getCursorOffset() { 77 | return new int[] { 1, 1 }; 78 | } 79 | 80 | @Override 81 | public double getConveyorYOffset() { 82 | return 1.5; 83 | } 84 | 85 | @Override 86 | public int getState() { 87 | return state; 88 | } 89 | 90 | @Override 91 | public int getColour() { 92 | return Block.BLOCK_COLOR_YELLOW; 93 | } 94 | 95 | @Override 96 | public int[][] getConveyorBoundingBox() { 97 | int minX, minY, maxX, maxY; 98 | 99 | minX = contents[0][0].length - 1; 100 | minY = contents[0].length - 1; 101 | maxX = 0; 102 | maxY = 0; 103 | 104 | for (int y = 0; y < contents[0].length; y++) { 105 | for (int x = 0; x < contents[0][0].length; x++) { 106 | if (contents[state][y][x] != 0) { 107 | if (x < minX) minX = x; 108 | if (y < minY) minY = y; 109 | if (x > maxX) maxX = x; 110 | if (y > maxY) maxY = y; 111 | } 112 | } 113 | } 114 | 115 | maxX++; 116 | maxY++; 117 | 118 | int[] tlc, brc; 119 | tlc = new int[] { 120 | location[0] + (minX * 16), 121 | location[1] + (minY * 16) 122 | }; 123 | brc = new int[] { 124 | location[0] + (maxX * 16), 125 | location[1] + (maxY * 16) 126 | }; 127 | 128 | return new int[][] { tlc, brc }; 129 | } 130 | 131 | @Override 132 | public int[][][] getCursorBoundingBox() { 133 | ArrayList boxes = new ArrayList<>(); 134 | 135 | for (int y = 0; y < contents[state].length; y++) { 136 | for (int x = 0; x < contents[state][0].length; x++) { 137 | if (contents[state][y][x] != 0) { 138 | boxes.add( 139 | new int[][] { 140 | new int[] { 141 | location[0] + (x * 16), 142 | location[1] + (y * 16) 143 | }, 144 | new int[] { 145 | location[0] + ((x + 1) * 16), 146 | location[1] + ((y + 1) * 16) 147 | } 148 | } 149 | ); 150 | } 151 | } 152 | } 153 | 154 | int[][][] arr = new int[boxes.size()][][]; 155 | 156 | int i = 0; 157 | for (int[][] iss : boxes) { 158 | arr[i] = iss.clone(); 159 | i++; 160 | } 161 | 162 | return arr; 163 | } 164 | 165 | @Override 166 | public void rotate() { 167 | state = (state + 1) % 2; 168 | } 169 | 170 | @Override 171 | public void setLocation(int x, int y) { 172 | location = new int[] { x, y }; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/particles/BlockParticleCollection.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.particles; 2 | 3 | import java.util.Arrays; 4 | import java.util.Random; 5 | import mu.nu.nullpo.game.component.Block; 6 | import mu.nu.nullpo.game.event.EventReceiver; 7 | import mu.nu.nullpo.game.play.GameEngine; 8 | import zeroxfc.nullpo.custom.libs.DoubleVector; 9 | import zeroxfc.nullpo.custom.libs.RendererExtension; 10 | 11 | public class BlockParticleCollection { 12 | // Animation types: 13 | public static final int ANIMATION_DTET = 0, 14 | ANIMATION_TGM = 1; 15 | // Number of anim types 16 | public static final int ANIMATION_TYPES = 2; 17 | // Block particles in collection 18 | private final BlockParticle[] collectionBlockParticles; 19 | // Animation type 20 | private final int animationType; 21 | 22 | private final RendererExtension rendererExtension; 23 | 24 | /** 25 | * Creates a new collection of particles. 26 | * 27 | * @param length Maximum particle count. 28 | */ 29 | public BlockParticleCollection(RendererExtension rendererExtension, int length, int animType) { 30 | collectionBlockParticles = new BlockParticle[length]; 31 | animationType = animType; 32 | Arrays.fill(collectionBlockParticles, null); 33 | 34 | this.rendererExtension = rendererExtension; 35 | } 36 | 37 | public void update() { 38 | for (int i = 0; i < collectionBlockParticles.length; i++) { 39 | if (collectionBlockParticles[i] != null) { 40 | collectionBlockParticles[i].update(animationType); 41 | 42 | if (collectionBlockParticles[i].getCurrentLifetime() >= collectionBlockParticles[i].getMaxLifetime()) { 43 | collectionBlockParticles[i] = null; 44 | } 45 | } 46 | } 47 | } 48 | 49 | public void drawAll(GameEngine engine, EventReceiver receiver, int playerID) { 50 | for (BlockParticle collectionBlockParticle : collectionBlockParticles) { 51 | if (collectionBlockParticle != null) { 52 | collectionBlockParticle.draw(engine, receiver, playerID, animationType); 53 | } 54 | } 55 | } 56 | 57 | public void addBlock(GameEngine engine, EventReceiver receiver, int playerID, Block block, int x, int y, double maxVelocity, int timeToLive, boolean isFlashing, Random randomiser) { 58 | int i = 0; 59 | try { 60 | while (collectionBlockParticles[i] != null) i++; 61 | } catch (IndexOutOfBoundsException e) { 62 | return; // Do not add block if full. 63 | } 64 | 65 | Block k = new Block(); 66 | k.copy(block); 67 | 68 | int v1 = receiver.getFieldDisplayPositionX(engine, playerID) + (engine.displaysize == 0 ? 4 : 8) + (x * (engine.displaysize == 0 ? 16 : 32)); 69 | int v2 = receiver.getFieldDisplayPositionY(engine, playerID) + (engine.displaysize == 0 ? 52 : 104) + (y * (engine.displaysize == 0 ? 16 : 32)); 70 | DoubleVector position = new DoubleVector(v1, v2, false); 71 | 72 | timeToLive += (randomiser.nextInt(5) - 2); 73 | 74 | collectionBlockParticles[i] = new BlockParticle(k, rendererExtension, position, maxVelocity, timeToLive, isFlashing, randomiser); 75 | } 76 | 77 | public void addBlock(GameEngine engine, EventReceiver receiver, int playerID, Block block, int x, int y, int maxX, int yMod, int maxYMod, int timeToLive) { 78 | int i = 0; 79 | try { 80 | while (collectionBlockParticles[i] != null) i++; 81 | } catch (IndexOutOfBoundsException e) { 82 | return; // Do not add block if full. 83 | } 84 | 85 | Block k = new Block(); 86 | k.copy(block); 87 | 88 | int v1 = receiver.getFieldDisplayPositionX(engine, playerID) + (engine.displaysize == 0 ? 4 : 8) + (x * (engine.displaysize == 0 ? 16 : 32)); 89 | int v2 = receiver.getFieldDisplayPositionY(engine, playerID) + (engine.displaysize == 0 ? 52 : 104) + (y * (engine.displaysize == 0 ? 16 : 32)); 90 | DoubleVector position = new DoubleVector(v1, v2, false); 91 | 92 | double xU = (x - (maxX / 2d)); 93 | if (maxX % 2 == 0) xU += 0.5; 94 | double mod = (1.0 / 3.0) * xU; 95 | DoubleVector velocity = new DoubleVector(mod * 1.1d, -4.8 * (0.5 + (0.5 * ((double) (maxYMod - yMod) / maxYMod))), false); 96 | 97 | collectionBlockParticles[i] = new BlockParticle(k, rendererExtension, position, velocity, timeToLive); 98 | } 99 | 100 | public int getCount() { 101 | int g = 0; 102 | for (BlockParticle collectionBlockParticle : collectionBlockParticles) { 103 | if (collectionBlockParticle != null) g++; 104 | } 105 | return g; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/gemswap/HypercubeGem.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.gemswap; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class HypercubeGem implements Gem { 7 | /** 8 | * Gem ID 9 | */ 10 | private static final int ID = GemField.GEMID_HYPERCUBE; 11 | private final boolean special; 12 | /** 13 | * Class properties. 14 | */ 15 | private int[] location; 16 | private int colour; 17 | private boolean recentSwap; 18 | private boolean recentFall; 19 | private boolean matchedHorizontal; 20 | private boolean matchedVertical; 21 | private boolean actionConducted; 22 | private boolean destroy; 23 | 24 | public HypercubeGem(int x, int y) { 25 | location = new int[] { x, y }; 26 | this.colour = Block.BLOCK_COLOR_GEM_RAINBOW; 27 | 28 | recentSwap = false; 29 | recentFall = false; 30 | matchedHorizontal = false; 31 | matchedVertical = false; 32 | actionConducted = false; 33 | special = true; 34 | destroy = false; 35 | } 36 | 37 | @Override 38 | public int getID() { 39 | return ID; 40 | } 41 | 42 | @Override 43 | public int getColour() { 44 | return colour; 45 | } 46 | 47 | @Override 48 | public void setColour(int colour) { 49 | this.colour = colour; 50 | } 51 | 52 | @Override 53 | public int[] getLocation() { 54 | return location; 55 | } 56 | 57 | @Override 58 | public boolean getRecentSwap() { 59 | return recentSwap; 60 | } 61 | 62 | @Override 63 | public void setRecentSwap(boolean isRecentSwap) { 64 | recentSwap = isRecentSwap; 65 | } 66 | 67 | @Override 68 | public boolean getRecentFall() { 69 | return recentFall; 70 | } 71 | 72 | @Override 73 | public void setRecentFall(boolean isRecentFall) { 74 | recentFall = isRecentFall; 75 | } 76 | 77 | @Override 78 | public void setLocation(int x, int y) { 79 | location = new int[] { x, y }; 80 | } 81 | 82 | @Override 83 | public int conductAction(GemField field, int[] args, ArrayList eventList) { 84 | // THIS METHOD EXPECTS args[0] TO BE THE COLOUR OF THE GEM THAT TRIGGERED IT. 85 | actionConducted = true; 86 | destroy = true; 87 | 88 | int ctr = 0; 89 | int colourSelected = args[0]; 90 | 91 | for (int y = 0; y < field.getHeight(); y++) { 92 | for (int x = 0; x < field.getWidth(); x++) { 93 | if (field.getCell(x, y).getColour() == colourSelected && !field.getCell(x, y).getActionConducted()) { 94 | ctr++; 95 | field.getCell(x, y).conductAction(field, new int[] { colour }, eventList); 96 | field.getCell(x, y).setDestroy(true); 97 | } else if (colourSelected == Block.BLOCK_COLOR_GEM_RAINBOW && !field.getCell(x, y).getActionConducted()) { 98 | ctr++; 99 | field.getCell(x, y).conductAction(field, new int[] { colour }, eventList); 100 | field.getCell(x, y).setDestroy(true); 101 | } 102 | } 103 | } 104 | 105 | eventList.add(new ScoreEvent(ctr, location[0], location[1], ID, colour)); 106 | 107 | return ctr; 108 | } 109 | 110 | @Override 111 | public boolean getSpecial() { 112 | return special; 113 | } 114 | 115 | @Override 116 | public boolean getMatchedHorizontal() { 117 | return matchedHorizontal; 118 | } 119 | 120 | @Override 121 | public void setMatchedHorizontal(boolean isMatched) { 122 | matchedHorizontal = isMatched; 123 | } 124 | 125 | @Override 126 | public boolean getMatchedVertical() { 127 | return matchedVertical; 128 | } 129 | 130 | @Override 131 | public void setMatchedVertical(boolean isMatched) { 132 | matchedVertical = isMatched; 133 | } 134 | 135 | @Override 136 | public boolean getActionConducted() { 137 | return actionConducted; 138 | } 139 | 140 | @Override 141 | public void setActionConducted(boolean isConduted) { 142 | actionConducted = isConduted; 143 | } 144 | 145 | @Override 146 | public Gem getSelf() { 147 | return new HypercubeGem(location[0], location[1]); 148 | } 149 | 150 | @Override 151 | public boolean getDestroy() { 152 | // TODO Auto-generated method stub 153 | return destroy; 154 | } 155 | 156 | @Override 157 | public void setDestroy(boolean shouldDestroy) { 158 | // TODO Auto-generated method stub 159 | destroy = shouldDestroy; 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/ShakingText.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs; 2 | 3 | import java.util.Random; 4 | import mu.nu.nullpo.game.event.EventReceiver; 5 | import mu.nu.nullpo.game.play.GameEngine; 6 | 7 | public class ShakingText { 8 | private final Random textPositionRandomiser; 9 | 10 | /** 11 | * Generates a text shaker object. 12 | * 13 | * @param random Random instance to use. 14 | */ 15 | public ShakingText(Random random) { 16 | textPositionRandomiser = random; 17 | } 18 | 19 | /** 20 | * Generates a text shaker object with an auto-generated randomiser. 21 | */ 22 | public ShakingText() { 23 | this(new Random()); 24 | } 25 | 26 | /** 27 | * Draws some shaken text at some pixel coordinates. 28 | * 29 | * @param engine Current GameEngine instance 30 | * @param x X-coordinate (pixel) of the top-left of the text anchor 31 | * @param y Y-coordinate (pixel) of the top-left of the text anchor 32 | * @param maxDevianceX Maximum x-pixel-coordinate deviance in text 33 | * @param maxDevianceY Maximum y-pixel-coordinate deviance in text 34 | * @param text Text to draw 35 | * @param colour Colour of text. Use colours from EventReceiver 36 | * @param scale Scale of drawn text. 37 | */ 38 | public void drawDirectText(GameEngine engine, int x, int y, int maxDevianceX, int maxDevianceY, String text, int colour, float scale) { 39 | final double offset = 16d * scale; 40 | if (maxDevianceX < 0) maxDevianceX *= -1; 41 | if (maxDevianceY < 0) maxDevianceY *= -1; 42 | 43 | for (int i = 0; i < text.length(); i++) { 44 | int offsetUsed = (int) (offset * i); 45 | int xDiff = 0, yDiff = 0; 46 | if (maxDevianceX > 0) xDiff = textPositionRandomiser.nextInt(maxDevianceX * 2 + 1) - maxDevianceX; 47 | if (maxDevianceY > 0) yDiff = textPositionRandomiser.nextInt(maxDevianceY * 2 + 1) - maxDevianceY; 48 | 49 | GameTextUtilities.drawDirectText(engine, x + offsetUsed + xDiff, y + yDiff, GameTextUtilities.Text.custom(text.substring(i, i + 1), colour, scale)); 50 | } 51 | } 52 | 53 | /** 54 | * Draws some shaken text relative to the score display position. 55 | * 56 | * @param receiver EventReceiver instance to draw on 57 | * @param engine Current GameEngine instance 58 | * @param playerID Current player ID (1P = 0) 59 | * @param x X-coordinate of the top-left of the text anchor 60 | * @param y Y-coordinate of the top-left of the text anchor 61 | * @param maxDevianceX Maximum x-pixel-coordinate deviance in text 62 | * @param maxDevianceY Maximum y-pixel-coordinate deviance in text 63 | * @param text Text to draw 64 | * @param colour Colour of text. Use colours from EventReceiver 65 | * @param scale Scale of drawn text. 66 | */ 67 | public void drawScoreText(EventReceiver receiver, GameEngine engine, int playerID, int x, int y, int maxDevianceX, int maxDevianceY, String text, int colour, float scale) { 68 | int nx, ny; 69 | nx = receiver.getScoreDisplayPositionX(engine, playerID) + (x * ((scale <= 0.5f) ? 8 : 16)); 70 | ny = receiver.getScoreDisplayPositionY(engine, playerID) + (y * ((scale <= 0.5f) ? 8 : 16)); 71 | 72 | drawDirectText(engine, nx, ny, maxDevianceX, maxDevianceY, text, colour, scale); 73 | } 74 | 75 | /** 76 | * Draws some shaken text relative to the field display position. 77 | * 78 | * @param receiver EventReceiver instance to draw on 79 | * @param engine Current GameEngine instance 80 | * @param playerID Current player ID (1P = 0) 81 | * @param x X-coordinate of the top-left of the text anchor 82 | * @param y Y-coordinate of the top-left of the text anchor 83 | * @param maxDevianceX Maximum x-pixel-coordinate deviance in text 84 | * @param maxDevianceY Maximum y-pixel-coordinate deviance in text 85 | * @param text Text to draw 86 | * @param colour Colour of text. Use colours from EventReceiver 87 | * @param scale Scale of drawn text. 88 | */ 89 | public void drawMenuText(EventReceiver receiver, GameEngine engine, int playerID, int x, int y, int maxDevianceX, int maxDevianceY, String text, int colour, float scale) { 90 | int nx, ny; 91 | nx = receiver.getFieldDisplayPositionX(engine, playerID) + (x * ((scale <= 0.5f) ? 8 : 16)) + 4; 92 | ny = receiver.getFieldDisplayPositionY(engine, playerID) + (y * ((scale <= 0.5f) ? 8 : 16)) + 52; 93 | 94 | drawDirectText(engine, nx, ny, maxDevianceX, maxDevianceY, text, colour, scale); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/I4.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class I4 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 0, 0, 0, 0 }, 10 | new int[] { 1, 1, 1, 1 }, 11 | new int[] { 0, 0, 0, 0 }, 12 | new int[] { 0, 0, 0, 0 } 13 | }, 14 | new int[][] { 15 | new int[] { 0, 0, 1, 0 }, 16 | new int[] { 0, 0, 1, 0 }, 17 | new int[] { 0, 0, 1, 0 }, 18 | new int[] { 0, 0, 1, 0 } 19 | } 20 | }; 21 | 22 | private int[] location; 23 | private int state; 24 | private int powerup; 25 | 26 | public I4(int x, int y) { 27 | location = new int[] { x, y }; 28 | state = 0; 29 | powerup = 0; 30 | } 31 | 32 | @Override 33 | public int getPowerup() { 34 | return powerup; 35 | } 36 | 37 | @Override 38 | public void setPowerup(int powerup) { 39 | this.powerup = powerup; 40 | } 41 | 42 | @Override 43 | public int getScore() { 44 | return 125; 45 | } 46 | 47 | @Override 48 | public int getWidth() { 49 | return state == 0 ? 4 : 1; 50 | } 51 | 52 | @Override 53 | public int getHeight() { 54 | return state == 0 ? 1 : 4; 55 | } 56 | 57 | @Override 58 | public int getX() { 59 | return location[0]; 60 | } 61 | 62 | @Override 63 | public int getY() { 64 | return location[1]; 65 | } 66 | 67 | @Override 68 | public int[] getLocation() { 69 | return location; 70 | } 71 | 72 | @Override 73 | public int[][] getContents() { 74 | return contents[state]; 75 | } 76 | 77 | @Override 78 | public int[] getCursorOffset() { 79 | return new int[] { 2, 1 }; 80 | } 81 | 82 | @Override 83 | public double getConveyorYOffset() { 84 | return 1.0; 85 | } 86 | 87 | @Override 88 | public int getState() { 89 | return state; 90 | } 91 | 92 | @Override 93 | public int getColour() { 94 | return Block.BLOCK_COLOR_BLUE; 95 | } 96 | 97 | @Override 98 | public int[][] getConveyorBoundingBox() { 99 | int minX, minY, maxX, maxY; 100 | 101 | minX = contents[0][0].length - 1; 102 | minY = contents[0].length - 1; 103 | maxX = 0; 104 | maxY = 0; 105 | 106 | for (int y = 0; y < contents[0].length; y++) { 107 | for (int x = 0; x < contents[0][0].length; x++) { 108 | if (contents[state][y][x] != 0) { 109 | if (x < minX) minX = x; 110 | if (y < minY) minY = y; 111 | if (x > maxX) maxX = x; 112 | if (y > maxY) maxY = y; 113 | } 114 | } 115 | } 116 | 117 | maxX++; 118 | maxY++; 119 | 120 | int[] tlc, brc; 121 | tlc = new int[] { 122 | location[0] + (minX * 16), 123 | location[1] + (minY * 16) 124 | }; 125 | brc = new int[] { 126 | location[0] + (maxX * 16), 127 | location[1] + (maxY * 16) 128 | }; 129 | 130 | return new int[][] { tlc, brc }; 131 | } 132 | 133 | @Override 134 | public int[][][] getCursorBoundingBox() { 135 | ArrayList boxes = new ArrayList<>(); 136 | 137 | for (int y = 0; y < contents[state].length; y++) { 138 | for (int x = 0; x < contents[state][0].length; x++) { 139 | if (contents[state][y][x] != 0) { 140 | boxes.add( 141 | new int[][] { 142 | new int[] { 143 | location[0] + (x * 16), 144 | location[1] + (y * 16) 145 | }, 146 | new int[] { 147 | location[0] + ((x + 1) * 16), 148 | location[1] + ((y + 1) * 16) 149 | } 150 | } 151 | ); 152 | } 153 | } 154 | } 155 | 156 | int[][][] arr = new int[boxes.size()][][]; 157 | 158 | int i = 0; 159 | for (int[][] iss : boxes) { 160 | arr[i] = iss.clone(); 161 | i++; 162 | } 163 | 164 | return arr; 165 | } 166 | 167 | @Override 168 | public void rotate() { 169 | state = (state + 1) % 2; 170 | } 171 | 172 | @Override 173 | public void setLocation(int x, int y) { 174 | location = new int[] { x, y }; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/L3.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class L3 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 1, 0 }, 10 | new int[] { 1, 1 } 11 | }, 12 | new int[][] { 13 | new int[] { 1, 1 }, 14 | new int[] { 1, 0 } 15 | }, 16 | new int[][] { 17 | new int[] { 1, 1 }, 18 | new int[] { 0, 1 } 19 | }, 20 | new int[][] { 21 | new int[] { 0, 1 }, 22 | new int[] { 1, 1 } 23 | }, 24 | }; 25 | 26 | private int[] location; 27 | private int state; 28 | private int powerup; 29 | 30 | public L3(int x, int y) { 31 | location = new int[] { x, y }; 32 | state = 0; 33 | powerup = 0; 34 | } 35 | 36 | @Override 37 | public int getPowerup() { 38 | return powerup; 39 | } 40 | 41 | @Override 42 | public void setPowerup(int powerup) { 43 | this.powerup = powerup; 44 | } 45 | 46 | @Override 47 | public int getScore() { 48 | return 75; 49 | } 50 | 51 | @Override 52 | public int getWidth() { 53 | return 2; 54 | } 55 | 56 | @Override 57 | public int getHeight() { 58 | return 2; 59 | } 60 | 61 | @Override 62 | public int getX() { 63 | return location[0]; 64 | } 65 | 66 | @Override 67 | public int getY() { 68 | return location[1]; 69 | } 70 | 71 | @Override 72 | public int[] getLocation() { 73 | return location; 74 | } 75 | 76 | @Override 77 | public int[][] getContents() { 78 | return contents[state]; 79 | } 80 | 81 | @Override 82 | public int[] getCursorOffset() { 83 | return new int[] { 0, 0 }; 84 | } 85 | 86 | @Override 87 | public double getConveyorYOffset() { 88 | return 0.5; 89 | } 90 | 91 | @Override 92 | public int getState() { 93 | return state; 94 | } 95 | 96 | @Override 97 | public int getColour() { 98 | return Block.BLOCK_COLOR_GRAY; 99 | } 100 | 101 | @Override 102 | public int[][] getConveyorBoundingBox() { 103 | int minX, minY, maxX, maxY; 104 | 105 | minX = contents[0][0].length - 1; 106 | minY = contents[0].length - 1; 107 | maxX = 0; 108 | maxY = 0; 109 | 110 | for (int y = 0; y < contents[0].length; y++) { 111 | for (int x = 0; x < contents[0][0].length; x++) { 112 | if (contents[state][y][x] != 0) { 113 | if (x < minX) minX = x; 114 | if (y < minY) minY = y; 115 | if (x > maxX) maxX = x; 116 | if (y > maxY) maxY = y; 117 | } 118 | } 119 | } 120 | 121 | maxX++; 122 | maxY++; 123 | 124 | int[] tlc, brc; 125 | tlc = new int[] { 126 | location[0] + (minX * 16), 127 | location[1] + (minY * 16) 128 | }; 129 | brc = new int[] { 130 | location[0] + (maxX * 16), 131 | location[1] + (maxY * 16) 132 | }; 133 | 134 | return new int[][] { tlc, brc }; 135 | } 136 | 137 | @Override 138 | public int[][][] getCursorBoundingBox() { 139 | ArrayList boxes = new ArrayList<>(); 140 | 141 | for (int y = 0; y < contents[state].length; y++) { 142 | for (int x = 0; x < contents[state][0].length; x++) { 143 | if (contents[state][y][x] != 0) { 144 | boxes.add( 145 | new int[][] { 146 | new int[] { 147 | location[0] + (x * 16), 148 | location[1] + (y * 16) 149 | }, 150 | new int[] { 151 | location[0] + ((x + 1) * 16), 152 | location[1] + ((y + 1) * 16) 153 | } 154 | } 155 | ); 156 | } 157 | } 158 | } 159 | 160 | int[][][] arr = new int[boxes.size()][][]; 161 | 162 | int i = 0; 163 | for (int[][] iss : boxes) { 164 | arr[i] = iss.clone(); 165 | i++; 166 | } 167 | 168 | return arr; 169 | } 170 | 171 | @Override 172 | public void rotate() { 173 | state = (state + 1) % 4; 174 | } 175 | 176 | @Override 177 | public void setLocation(int x, int y) { 178 | location = new int[] { x, y }; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/gemswap/StarGem.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.gemswap; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class StarGem implements Gem { 6 | /** 7 | * Gem ID 8 | */ 9 | private static final int ID = GemField.GEMID_STAR; 10 | private final boolean special; 11 | /** 12 | * Class properties. 13 | */ 14 | private int[] location; 15 | private int colour; 16 | private boolean recentSwap; 17 | private boolean recentFall; 18 | private boolean matchedHorizontal; 19 | private boolean matchedVertical; 20 | private boolean actionConducted; 21 | private boolean destroy; 22 | 23 | public StarGem(int x, int y, int colour) { 24 | location = new int[] { x, y }; 25 | this.colour = colour; 26 | 27 | recentSwap = false; 28 | recentFall = false; 29 | matchedHorizontal = false; 30 | matchedVertical = false; 31 | actionConducted = false; 32 | special = true; 33 | destroy = false; 34 | } 35 | 36 | @Override 37 | public int getID() { 38 | return ID; 39 | } 40 | 41 | @Override 42 | public int getColour() { 43 | return colour; 44 | } 45 | 46 | @Override 47 | public void setColour(int colour) { 48 | this.colour = colour; 49 | } 50 | 51 | @Override 52 | public int[] getLocation() { 53 | return location; 54 | } 55 | 56 | @Override 57 | public boolean getRecentSwap() { 58 | return recentSwap; 59 | } 60 | 61 | @Override 62 | public void setRecentSwap(boolean isRecentSwap) { 63 | recentSwap = isRecentSwap; 64 | } 65 | 66 | @Override 67 | public boolean getRecentFall() { 68 | return recentFall; 69 | } 70 | 71 | @Override 72 | public void setRecentFall(boolean isRecentFall) { 73 | recentFall = isRecentFall; 74 | } 75 | 76 | @Override 77 | public void setLocation(int x, int y) { 78 | location = new int[] { x, y }; 79 | } 80 | 81 | @Override 82 | public int conductAction(GemField field, int[] args, ArrayList eventList) { 83 | int ctr = 0; 84 | 85 | for (int x = 0; x < field.getWidth(); x++) { 86 | int tX = location[0] + x; 87 | int tY = location[1]; 88 | 89 | if (field.getCell(tX, tY) != null && tX != location[0]) { 90 | if (field.getCell(tX, tY).getID() != GemField.GEMID_EMPTY && 91 | !field.getCell(tX, tY).getActionConducted()) { 92 | ctr++; 93 | field.getCell(tX, tY).conductAction(field, new int[] { colour }, eventList); 94 | field.getCell(tX, tY).setDestroy(true); 95 | } 96 | } 97 | } 98 | 99 | for (int y = 0; y < field.getHeight(); y++) { 100 | int tX = location[0]; 101 | int tY = location[1] + y; 102 | 103 | if (field.getCell(tX, tY) != null && tY != location[1]) { 104 | if (field.getCell(tX, tY).getID() != GemField.GEMID_EMPTY && 105 | !field.getCell(tX, tY).getActionConducted()) { 106 | ctr++; 107 | field.getCell(tX, tY).conductAction(field, new int[] { colour }, eventList); 108 | field.getCell(tX, tY).setDestroy(true); 109 | } 110 | } 111 | } 112 | 113 | actionConducted = true; 114 | eventList.add(new ScoreEvent(ctr, location[0], location[1], ID, colour)); 115 | 116 | return ctr; 117 | } 118 | 119 | @Override 120 | public boolean getSpecial() { 121 | return special; 122 | } 123 | 124 | @Override 125 | public boolean getMatchedHorizontal() { 126 | return matchedHorizontal; 127 | } 128 | 129 | @Override 130 | public void setMatchedHorizontal(boolean isMatched) { 131 | matchedHorizontal = isMatched; 132 | } 133 | 134 | @Override 135 | public boolean getMatchedVertical() { 136 | return matchedVertical; 137 | } 138 | 139 | @Override 140 | public void setMatchedVertical(boolean isMatched) { 141 | matchedVertical = isMatched; 142 | } 143 | 144 | @Override 145 | public boolean getActionConducted() { 146 | return actionConducted; 147 | } 148 | 149 | @Override 150 | public void setActionConducted(boolean isConduted) { 151 | actionConducted = isConduted; 152 | } 153 | 154 | @Override 155 | public Gem getSelf() { 156 | return new StarGem(location[0], location[1], colour); 157 | } 158 | 159 | @Override 160 | public boolean getDestroy() { 161 | // TODO Auto-generated method stub 162 | return destroy; 163 | } 164 | 165 | @Override 166 | public void setDestroy(boolean shouldDestroy) { 167 | // TODO Auto-generated method stub 168 | destroy = shouldDestroy; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/Stairs6.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class Stairs6 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 1, 0, 0 }, 10 | new int[] { 1, 1, 0 }, 11 | new int[] { 1, 1, 1 } 12 | }, 13 | new int[][] { 14 | new int[] { 1, 1, 1 }, 15 | new int[] { 1, 1, 0 }, 16 | new int[] { 1, 0, 0 }, 17 | }, 18 | new int[][] { 19 | new int[] { 1, 1, 1 }, 20 | new int[] { 0, 1, 1 }, 21 | new int[] { 0, 0, 1 } 22 | }, 23 | new int[][] { 24 | new int[] { 0, 0, 1 }, 25 | new int[] { 0, 1, 1 }, 26 | new int[] { 1, 1, 1 }, 27 | }, 28 | }; 29 | 30 | private int[] location; 31 | private int state; 32 | private int powerup; 33 | 34 | public Stairs6(int x, int y) { 35 | location = new int[] { x, y }; 36 | state = 0; 37 | powerup = 0; 38 | } 39 | 40 | @Override 41 | public int getPowerup() { 42 | return powerup; 43 | } 44 | 45 | @Override 46 | public void setPowerup(int powerup) { 47 | this.powerup = powerup; 48 | } 49 | 50 | @Override 51 | public int getScore() { 52 | return 450; 53 | } 54 | 55 | @Override 56 | public int getWidth() { 57 | return 3; 58 | } 59 | 60 | @Override 61 | public int getHeight() { 62 | return 3; 63 | } 64 | 65 | @Override 66 | public int getX() { 67 | return location[0]; 68 | } 69 | 70 | @Override 71 | public int getY() { 72 | return location[1]; 73 | } 74 | 75 | @Override 76 | public int[] getLocation() { 77 | return location; 78 | } 79 | 80 | @Override 81 | public int[][] getContents() { 82 | return contents[state]; 83 | } 84 | 85 | @Override 86 | public int[] getCursorOffset() { 87 | return new int[] { 1, 1 }; 88 | } 89 | 90 | @Override 91 | public double getConveyorYOffset() { 92 | return 1.0; 93 | } 94 | 95 | @Override 96 | public int getState() { 97 | return state; 98 | } 99 | 100 | @Override 101 | public int getColour() { 102 | return Block.BLOCK_COLOR_CYAN; 103 | } 104 | 105 | @Override 106 | public int[][] getConveyorBoundingBox() { 107 | int minX, minY, maxX, maxY; 108 | 109 | minX = contents[0][0].length - 1; 110 | minY = contents[0].length - 1; 111 | maxX = 0; 112 | maxY = 0; 113 | 114 | for (int y = 0; y < contents[0].length; y++) { 115 | for (int x = 0; x < contents[0][0].length; x++) { 116 | if (contents[state][y][x] != 0) { 117 | if (x < minX) minX = x; 118 | if (y < minY) minY = y; 119 | if (x > maxX) maxX = x; 120 | if (y > maxY) maxY = y; 121 | } 122 | } 123 | } 124 | 125 | maxX++; 126 | maxY++; 127 | 128 | int[] tlc, brc; 129 | tlc = new int[] { 130 | location[0] + (minX * 16), 131 | location[1] + (minY * 16) 132 | }; 133 | brc = new int[] { 134 | location[0] + (maxX * 16), 135 | location[1] + (maxY * 16) 136 | }; 137 | 138 | return new int[][] { tlc, brc }; 139 | } 140 | 141 | @Override 142 | public int[][][] getCursorBoundingBox() { 143 | ArrayList boxes = new ArrayList<>(); 144 | 145 | for (int y = 0; y < contents[state].length; y++) { 146 | for (int x = 0; x < contents[state][0].length; x++) { 147 | if (contents[state][y][x] != 0) { 148 | boxes.add( 149 | new int[][] { 150 | new int[] { 151 | location[0] + (x * 16), 152 | location[1] + (y * 16) 153 | }, 154 | new int[] { 155 | location[0] + ((x + 1) * 16), 156 | location[1] + ((y + 1) * 16) 157 | } 158 | } 159 | ); 160 | } 161 | } 162 | } 163 | 164 | int[][][] arr = new int[boxes.size()][][]; 165 | 166 | int i = 0; 167 | for (int[][] iss : boxes) { 168 | arr[i] = iss.clone(); 169 | i++; 170 | } 171 | 172 | return arr; 173 | } 174 | 175 | @Override 176 | public void rotate() { 177 | state = (state + 1) % 4; 178 | } 179 | 180 | @Override 181 | public void setLocation(int x, int y) { 182 | location = new int[] { x, y }; 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/libs/types/ImageChunk.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.libs.types; 2 | 3 | /** Represents a chunk of an image to draw. */ 4 | public class ImageChunk { 5 | private ObjectAlignment alignment; 6 | 7 | // New Members 8 | private int anchorX, anchorY; 9 | private int sourceX, sourceY; 10 | private int sourceDimensionsX, sourceDimensionsY; 11 | private float scaleX, scaleY; 12 | 13 | private int drawLocationX, drawLocationY; 14 | 15 | public ImageChunk() { 16 | this( 17 | ObjectAlignment.TOP_LEFT, 18 | 0, 0, 19 | 0, 0, 20 | 1, 1, 21 | 1f, 1f 22 | ); 23 | } 24 | 25 | public ImageChunk(ObjectAlignment alignment, int anchorX, int anchorY, int sourceX, int sourceY, int sourceDimensionsX, int sourceDimensionsY, float scaleX, float scaleY) { 26 | this.alignment = alignment; 27 | 28 | this.anchorX = anchorX; 29 | this.anchorY = anchorY; 30 | this.sourceX = sourceX; 31 | this.sourceY = sourceY; 32 | this.sourceDimensionsX = sourceDimensionsX; 33 | this.sourceDimensionsY = sourceDimensionsY; 34 | this.scaleX = scaleX; 35 | this.scaleY = scaleY; 36 | 37 | calibrateDrawLocation(); 38 | } 39 | 40 | private void calibrateDrawLocation() { 41 | final int ddimX = getDrawDimensionsX(); 42 | final int ddimY = getDrawDimensionsY(); 43 | 44 | switch (alignment) { 45 | case TOP_MIDDLE: 46 | drawLocationX = anchorX - (ddimX / 2); 47 | drawLocationY = anchorY; 48 | break; 49 | case TOP_RIGHT: 50 | drawLocationX = anchorX - ddimX; 51 | drawLocationY = anchorY; 52 | break; 53 | case MIDDLE_LEFT: 54 | drawLocationX = anchorX; 55 | drawLocationY = anchorY - (ddimY / 2); 56 | break; 57 | case MIDDLE_MIDDLE: 58 | drawLocationX = anchorX - (ddimX / 2); 59 | drawLocationY = anchorY - (ddimY / 2); 60 | break; 61 | case MIDDLE_RIGHT: 62 | drawLocationX = anchorX - ddimX; 63 | drawLocationY = anchorY - (ddimY / 2); 64 | break; 65 | case BOTTOM_LEFT: 66 | drawLocationX = anchorX; 67 | drawLocationY = anchorY - ddimY; 68 | break; 69 | case BOTTOM_MIDDLE: 70 | drawLocationX = anchorX - (ddimX / 2); 71 | drawLocationY = anchorY - ddimY; 72 | break; 73 | case BOTTOM_RIGHT: 74 | drawLocationX = anchorX - ddimX; 75 | drawLocationY = anchorY - ddimY; 76 | break; 77 | default: 78 | drawLocationX = anchorX; 79 | drawLocationY = anchorY; 80 | break; 81 | } 82 | } 83 | 84 | public ObjectAlignment getAlignment() { 85 | return alignment; 86 | } 87 | 88 | public void setAlignment(ObjectAlignment alignment) { 89 | this.alignment = alignment; 90 | 91 | calibrateDrawLocation(); 92 | } 93 | 94 | public int getAnchorX() { 95 | return anchorX; 96 | } 97 | 98 | public int getAnchorY() { 99 | return anchorY; 100 | } 101 | 102 | public void setAnchor(int x, int y) { 103 | this.anchorX = x; 104 | this.anchorY = y; 105 | 106 | calibrateDrawLocation(); 107 | } 108 | 109 | public float getScaleX() { 110 | return scaleX; 111 | } 112 | 113 | public float getScaleY() { 114 | return scaleY; 115 | } 116 | 117 | public void setScale(float scaleX, float scaleY) { 118 | this.scaleX = scaleX; 119 | this.scaleY = scaleY; 120 | 121 | calibrateDrawLocation(); 122 | } 123 | 124 | public int getSourceX() { 125 | return sourceX; 126 | } 127 | 128 | public int getSourceY() { 129 | return sourceY; 130 | } 131 | 132 | private void setSourceLocation(int x, int y) { 133 | this.sourceX = x; 134 | this.sourceY = y; 135 | } 136 | 137 | public int getSourceDimensionsX() { 138 | return sourceDimensionsX; 139 | } 140 | 141 | public int getSourceDimensionsY() { 142 | return sourceDimensionsY; 143 | } 144 | 145 | public void setSourceDimensions(int sizeX, int sizeY) { 146 | this.sourceDimensionsX = sizeX; 147 | this.sourceDimensionsY = sizeY; 148 | 149 | calibrateDrawLocation(); 150 | } 151 | 152 | public int getDrawDimensionsX() { 153 | return (int) (sourceDimensionsX * scaleX); 154 | } 155 | 156 | public int getDrawDimensionsY() { 157 | return (int) (sourceDimensionsY * scaleY); 158 | } 159 | 160 | public int getDrawLocationX() { 161 | return drawLocationX; 162 | } 163 | 164 | public int getDrawLocationY() { 165 | return drawLocationY; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/J4.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class J4 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 0, 1, 0 }, 10 | new int[] { 0, 1, 0 }, 11 | new int[] { 1, 1, 0 } 12 | }, 13 | new int[][] { 14 | new int[] { 1, 0, 0 }, 15 | new int[] { 1, 1, 1 }, 16 | new int[] { 0, 0, 0 }, 17 | }, 18 | new int[][] { 19 | new int[] { 0, 1, 1 }, 20 | new int[] { 0, 1, 0 }, 21 | new int[] { 0, 1, 0 } 22 | }, 23 | new int[][] { 24 | new int[] { 0, 0, 0 }, 25 | new int[] { 1, 1, 1 }, 26 | new int[] { 0, 0, 1 }, 27 | }, 28 | }; 29 | 30 | private int[] location; 31 | private int state; 32 | private int powerup; 33 | 34 | public J4(int x, int y) { 35 | location = new int[] { x, y }; 36 | state = 0; 37 | powerup = 0; 38 | } 39 | 40 | @Override 41 | public int getPowerup() { 42 | return powerup; 43 | } 44 | 45 | @Override 46 | public void setPowerup(int powerup) { 47 | this.powerup = powerup; 48 | } 49 | 50 | @Override 51 | public int getScore() { 52 | return 250; 53 | } 54 | 55 | @Override 56 | public int getWidth() { 57 | return (state == 0 || state == 2) ? 2 : 3; 58 | } 59 | 60 | @Override 61 | public int getHeight() { 62 | return (state == 0 || state == 2) ? 3 : 2; 63 | } 64 | 65 | @Override 66 | public int getX() { 67 | return location[0]; 68 | } 69 | 70 | @Override 71 | public int getY() { 72 | return location[1]; 73 | } 74 | 75 | @Override 76 | public int[] getLocation() { 77 | return location; 78 | } 79 | 80 | @Override 81 | public int[][] getContents() { 82 | return contents[state]; 83 | } 84 | 85 | @Override 86 | public int[] getCursorOffset() { 87 | return new int[] { 1, 1 }; 88 | } 89 | 90 | @Override 91 | public double getConveyorYOffset() { 92 | return 1.0; 93 | } 94 | 95 | @Override 96 | public int getState() { 97 | return state; 98 | } 99 | 100 | @Override 101 | public int getColour() { 102 | return Block.BLOCK_COLOR_ORANGE; 103 | } 104 | 105 | @Override 106 | public int[][] getConveyorBoundingBox() { 107 | int minX, minY, maxX, maxY; 108 | 109 | minX = contents[0][0].length - 1; 110 | minY = contents[0].length - 1; 111 | maxX = 0; 112 | maxY = 0; 113 | 114 | for (int y = 0; y < contents[0].length; y++) { 115 | for (int x = 0; x < contents[0][0].length; x++) { 116 | if (contents[state][y][x] != 0) { 117 | if (x < minX) minX = x; 118 | if (y < minY) minY = y; 119 | if (x > maxX) maxX = x; 120 | if (y > maxY) maxY = y; 121 | } 122 | } 123 | } 124 | 125 | maxX++; 126 | maxY++; 127 | 128 | int[] tlc, brc; 129 | tlc = new int[] { 130 | location[0] + (minX * 16), 131 | location[1] + (minY * 16) 132 | }; 133 | brc = new int[] { 134 | location[0] + (maxX * 16), 135 | location[1] + (maxY * 16) 136 | }; 137 | 138 | return new int[][] { tlc, brc }; 139 | } 140 | 141 | @Override 142 | public int[][][] getCursorBoundingBox() { 143 | ArrayList boxes = new ArrayList<>(); 144 | 145 | for (int y = 0; y < contents[state].length; y++) { 146 | for (int x = 0; x < contents[state][0].length; x++) { 147 | if (contents[state][y][x] != 0) { 148 | boxes.add( 149 | new int[][] { 150 | new int[] { 151 | location[0] + (x * 16), 152 | location[1] + (y * 16) 153 | }, 154 | new int[] { 155 | location[0] + ((x + 1) * 16), 156 | location[1] + ((y + 1) * 16) 157 | } 158 | } 159 | ); 160 | } 161 | } 162 | } 163 | 164 | int[][][] arr = new int[boxes.size()][][]; 165 | 166 | int i = 0; 167 | for (int[][] iss : boxes) { 168 | arr[i] = iss.clone(); 169 | i++; 170 | } 171 | 172 | return arr; 173 | } 174 | 175 | @Override 176 | public void rotate() { 177 | state = (state + 1) % 4; 178 | } 179 | 180 | @Override 181 | public void setLocation(int x, int y) { 182 | location = new int[] { x, y }; 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/L4.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class L4 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 0, 1, 0 }, 10 | new int[] { 0, 1, 0 }, 11 | new int[] { 0, 1, 1 } 12 | }, 13 | new int[][] { 14 | new int[] { 0, 0, 0 }, 15 | new int[] { 1, 1, 1 }, 16 | new int[] { 1, 0, 0 }, 17 | }, 18 | new int[][] { 19 | new int[] { 1, 1, 0 }, 20 | new int[] { 0, 1, 0 }, 21 | new int[] { 0, 1, 0 } 22 | }, 23 | new int[][] { 24 | new int[] { 0, 0, 1 }, 25 | new int[] { 1, 1, 1 }, 26 | new int[] { 0, 0, 0 }, 27 | }, 28 | }; 29 | 30 | private int[] location; 31 | private int state; 32 | private int powerup; 33 | 34 | public L4(int x, int y) { 35 | location = new int[] { x, y }; 36 | state = 0; 37 | powerup = 0; 38 | } 39 | 40 | @Override 41 | public int getPowerup() { 42 | return powerup; 43 | } 44 | 45 | @Override 46 | public void setPowerup(int powerup) { 47 | this.powerup = powerup; 48 | } 49 | 50 | @Override 51 | public int getScore() { 52 | return 250; 53 | } 54 | 55 | @Override 56 | public int getWidth() { 57 | return (state == 0 || state == 2) ? 2 : 3; 58 | } 59 | 60 | @Override 61 | public int getHeight() { 62 | return (state == 0 || state == 2) ? 3 : 2; 63 | } 64 | 65 | @Override 66 | public int getX() { 67 | return location[0]; 68 | } 69 | 70 | @Override 71 | public int getY() { 72 | return location[1]; 73 | } 74 | 75 | @Override 76 | public int[] getLocation() { 77 | return location; 78 | } 79 | 80 | @Override 81 | public int[][] getContents() { 82 | return contents[state]; 83 | } 84 | 85 | @Override 86 | public int[] getCursorOffset() { 87 | return new int[] { 1, 1 }; 88 | } 89 | 90 | @Override 91 | public double getConveyorYOffset() { 92 | return 1.0; 93 | } 94 | 95 | @Override 96 | public int getState() { 97 | return state; 98 | } 99 | 100 | @Override 101 | public int getColour() { 102 | return Block.BLOCK_COLOR_PURPLE; 103 | } 104 | 105 | @Override 106 | public int[][] getConveyorBoundingBox() { 107 | int minX, minY, maxX, maxY; 108 | 109 | minX = contents[0][0].length - 1; 110 | minY = contents[0].length - 1; 111 | maxX = 0; 112 | maxY = 0; 113 | 114 | for (int y = 0; y < contents[0].length; y++) { 115 | for (int x = 0; x < contents[0][0].length; x++) { 116 | if (contents[state][y][x] != 0) { 117 | if (x < minX) minX = x; 118 | if (y < minY) minY = y; 119 | if (x > maxX) maxX = x; 120 | if (y > maxY) maxY = y; 121 | } 122 | } 123 | } 124 | 125 | maxX++; 126 | maxY++; 127 | 128 | int[] tlc, brc; 129 | tlc = new int[] { 130 | location[0] + (minX * 16), 131 | location[1] + (minY * 16) 132 | }; 133 | brc = new int[] { 134 | location[0] + (maxX * 16), 135 | location[1] + (maxY * 16) 136 | }; 137 | 138 | return new int[][] { tlc, brc }; 139 | } 140 | 141 | @Override 142 | public int[][][] getCursorBoundingBox() { 143 | ArrayList boxes = new ArrayList<>(); 144 | 145 | for (int y = 0; y < contents[state].length; y++) { 146 | for (int x = 0; x < contents[state][0].length; x++) { 147 | if (contents[state][y][x] != 0) { 148 | boxes.add( 149 | new int[][] { 150 | new int[] { 151 | location[0] + (x * 16), 152 | location[1] + (y * 16) 153 | }, 154 | new int[] { 155 | location[0] + ((x + 1) * 16), 156 | location[1] + ((y + 1) * 16) 157 | } 158 | } 159 | ); 160 | } 161 | } 162 | } 163 | 164 | int[][][] arr = new int[boxes.size()][][]; 165 | 166 | int i = 0; 167 | for (int[][] iss : boxes) { 168 | arr[i] = iss.clone(); 169 | i++; 170 | } 171 | 172 | return arr; 173 | } 174 | 175 | @Override 176 | public void rotate() { 177 | state = (state + 1) % 4; 178 | } 179 | 180 | @Override 181 | public void setLocation(int x, int y) { 182 | location = new int[] { x, y }; 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/zeroxfc/nullpo/custom/modes/objects/expressshipping/P5.java: -------------------------------------------------------------------------------- 1 | package zeroxfc.nullpo.custom.modes.objects.expressshipping; 2 | 3 | import java.util.ArrayList; 4 | import mu.nu.nullpo.game.component.Block; 5 | 6 | public class P5 implements GamePiece { 7 | private static final int[][][] contents = { 8 | new int[][] { 9 | new int[] { 0, 1, 1 }, 10 | new int[] { 0, 1, 1 }, 11 | new int[] { 0, 1, 0 } 12 | }, 13 | new int[][] { 14 | new int[] { 0, 0, 0 }, 15 | new int[] { 1, 1, 1 }, 16 | new int[] { 0, 1, 1 }, 17 | }, 18 | new int[][] { 19 | new int[] { 0, 1, 0 }, 20 | new int[] { 1, 1, 0 }, 21 | new int[] { 1, 1, 0 } 22 | }, 23 | new int[][] { 24 | new int[] { 1, 1, 0 }, 25 | new int[] { 1, 1, 1 }, 26 | new int[] { 0, 0, 0 }, 27 | }, 28 | }; 29 | 30 | private int[] location; 31 | private int state; 32 | private int powerup; 33 | 34 | public P5(int x, int y) { 35 | location = new int[] { x, y }; 36 | state = 0; 37 | powerup = 0; 38 | } 39 | 40 | @Override 41 | public int getPowerup() { 42 | return powerup; 43 | } 44 | 45 | @Override 46 | public void setPowerup(int powerup) { 47 | this.powerup = powerup; 48 | } 49 | 50 | @Override 51 | public int getScore() { 52 | return 350; 53 | } 54 | 55 | @Override 56 | public int getWidth() { 57 | return (state == 0 || state == 2) ? 2 : 3; 58 | } 59 | 60 | @Override 61 | public int getHeight() { 62 | return (state == 0 || state == 2) ? 3 : 2; 63 | } 64 | 65 | @Override 66 | public int getX() { 67 | return location[0]; 68 | } 69 | 70 | @Override 71 | public int getY() { 72 | return location[1]; 73 | } 74 | 75 | @Override 76 | public int[] getLocation() { 77 | return location; 78 | } 79 | 80 | @Override 81 | public int[][] getContents() { 82 | return contents[state]; 83 | } 84 | 85 | @Override 86 | public int[] getCursorOffset() { 87 | return new int[] { 1, 1 }; 88 | } 89 | 90 | @Override 91 | public double getConveyorYOffset() { 92 | return 1.0; 93 | } 94 | 95 | @Override 96 | public int getState() { 97 | return state; 98 | } 99 | 100 | @Override 101 | public int getColour() { 102 | return Block.BLOCK_COLOR_PURPLE; 103 | } 104 | 105 | @Override 106 | public int[][] getConveyorBoundingBox() { 107 | int minX, minY, maxX, maxY; 108 | 109 | minX = contents[0][0].length - 1; 110 | minY = contents[0].length - 1; 111 | maxX = 0; 112 | maxY = 0; 113 | 114 | for (int y = 0; y < contents[0].length; y++) { 115 | for (int x = 0; x < contents[0][0].length; x++) { 116 | if (contents[state][y][x] != 0) { 117 | if (x < minX) minX = x; 118 | if (y < minY) minY = y; 119 | if (x > maxX) maxX = x; 120 | if (y > maxY) maxY = y; 121 | } 122 | } 123 | } 124 | 125 | maxX++; 126 | maxY++; 127 | 128 | int[] tlc, brc; 129 | tlc = new int[] { 130 | location[0] + (minX * 16), 131 | location[1] + (minY * 16) 132 | }; 133 | brc = new int[] { 134 | location[0] + (maxX * 16), 135 | location[1] + (maxY * 16) 136 | }; 137 | 138 | return new int[][] { tlc, brc }; 139 | } 140 | 141 | @Override 142 | public int[][][] getCursorBoundingBox() { 143 | ArrayList boxes = new ArrayList<>(); 144 | 145 | for (int y = 0; y < contents[state].length; y++) { 146 | for (int x = 0; x < contents[state][0].length; x++) { 147 | if (contents[state][y][x] != 0) { 148 | boxes.add( 149 | new int[][] { 150 | new int[] { 151 | location[0] + (x * 16), 152 | location[1] + (y * 16) 153 | }, 154 | new int[] { 155 | location[0] + ((x + 1) * 16), 156 | location[1] + ((y + 1) * 16) 157 | } 158 | } 159 | ); 160 | } 161 | } 162 | } 163 | 164 | int[][][] arr = new int[boxes.size()][][]; 165 | 166 | int i = 0; 167 | for (int[][] iss : boxes) { 168 | arr[i] = iss.clone(); 169 | i++; 170 | } 171 | 172 | return arr; 173 | } 174 | 175 | @Override 176 | public void rotate() { 177 | state = (state + 1) % 4; 178 | } 179 | 180 | @Override 181 | public void setLocation(int x, int y) { 182 | location = new int[] { x, y }; 183 | } 184 | } 185 | --------------------------------------------------------------------------------