package com.weem.epicinventor.actor; import com.weem.epicinventor.*; import com.weem.epicinventor.network.*; import com.weem.epicinventor.utility.*; import com.weem.epicinventor.weapon.*; import java.awt.*; import java.awt.image.*; import java.awt.geom.AffineTransform; import java.io.*; import java.util.*; import java.awt.geom.Arc2D; public abstract class Actor implements Serializable { private static final long serialVersionUID = -5771308574194949873L; public enum VertMoveMode { NOT_JUMPING, JUMPING, FALLING, FLYING }; public enum Facing { RIGHT, LEFT }; public enum ActionMode { NONE, GATHERING, ATTACKING }; public enum AttackType { TOUCH, MELEE, RANGE } protected String id = ""; transient protected Manager manager; transient protected Registry registry; transient protected Arc2D.Double attackArc; transient protected int attackArcOffsetX, attackArcOffsetY; transient protected boolean shouldRender = true; protected int mapX, lastMapY, mapY; transient protected int lastMapX; transient protected int[] yx, ycm; protected int width, height; protected int xMoveSize; protected boolean stateChanged; protected String image = ""; transient protected String lastImage = ""; protected int numAnimationFrames; protected int currentAnimationFrame; protected int animationFrameDuration; protected long animationFrameUpdateTime = 0; protected final static double DEFAULT_ANIMATION_DURATION = 0.20; protected boolean isAnimating; protected boolean isActive; protected ActionMode actionMode; protected VertMoveMode vertMoveMode; protected Facing facing; protected AttackType currentAttackType; protected int topOffset; protected int jumpSize; protected int ascendOriginalSize; protected int ascendSize; protected int ascendCount; protected int ascendMax; protected int fallSize; protected int baseOffset; protected int baseWidth; protected boolean isStill; protected boolean isTryingToMove; protected boolean isStomping; protected int startJumpSize; protected int maxFallSize; protected int gravity; protected int totalFall = 0; protected int completeFall = 0; protected int totalHitPoints, hitPoints; protected int totalArmorPoints, armorPoints; protected int baseHitPoints = 100; protected int baseArmorPoints = 0; transient protected Rectangle spriteRect; transient protected Rectangle attackRect; protected int spriteRectOffestX, spriteRectOffestY; protected boolean showRect; protected boolean showGoals; protected int knockBackX = 0; protected boolean isDead; protected boolean isFeared; protected boolean isSlowed; protected boolean isPoisoned; protected Point fearedSource; protected long fearedDuration; protected long fearedTotalTime; protected long slowedDuration; protected long slowedTotalTime; protected long poisonedDuration; protected long poisonedTotalTime; protected int attackRange = 30; protected long attackRefreshTimerStart = 0; protected long attackRefreshTimerEnd = 0; protected int maxFollowDistance; protected boolean statusAttackBonus; protected boolean statusFear; protected boolean statusHeal; protected boolean statusPoison; protected boolean statusStun; protected boolean statusRezSickness; protected boolean statusSlowed; protected final static int STATUS_WIDTH = 17; protected final static int STATUS_SPACING = 1; protected boolean canFly; protected SoundClip loopingSound; transient protected HashMap<Actor, Integer> attackers = new HashMap<Actor, Integer>(); transient protected Actor lastAttacker; protected boolean disregardKnockBack = false; protected long stunEnded = 0; protected String debugInfo = ""; protected long chatEnd = 0; protected boolean isChatting; protected boolean projectileOut = false; public Actor(Manager m, Registry rg, String im, int x, int y) { manager = m; registry = rg; mapX = x; lastMapY = mapY = y; yx = new int[2]; ycm = new int[2]; isAnimating = false; isActive = true; ascendOriginalSize = 2; ascendSize = 2; ascendMax = 16; startJumpSize = 20; maxFallSize = 40; gravity = 2; spriteRect = new Rectangle(); spriteRectOffestX = 0; spriteRectOffestY = 0; attackRect = null; attackArcOffsetX = 0; attackArcOffsetY = 0; attackArc = null; currentAttackType = AttackType.TOUCH; setImage(im); id = UUID.randomUUID().toString(); } public void setTransient(Registry rg, Manager m) { registry = rg; manager = m; spriteRect = new Rectangle(); yx = new int[2]; ycm = new int[2]; } public String getId() { return id; } public void projectileReturned() { projectileOut = false; } public boolean isProjectileOut() { return projectileOut; } public void hide() { } public boolean getIsHiding() { return false; } public boolean getIsStomping() { return isStomping; } public void setIsStomping(boolean s) { isStomping = s; } public void moveLeft() { isStill = false; isTryingToMove = true; facing = Facing.LEFT; } public void moveRight() { isStill = false; isTryingToMove = true; facing = Facing.RIGHT; } public void moveTowardsPoint(Point p) { if (p != null && knockBackX == 0) { actionMode = ActionMode.NONE; int actorX = getMapX(); int actorCenterX = actorX + (getWidth() / 2); int actorCenterY = getMapY() + (getHeight() / 2); int targetX = p.x; int targetY = p.y; int distance = (int) Math.sqrt(Math.pow(Math.abs(targetX - actorCenterX), 2.0f) + Math.pow(Math.abs(targetY - actorCenterY), 2.0f)); if (distance <= maxFollowDistance) { if (targetX > actorCenterX) { if (facing != Facing.RIGHT) { moveRight(); stopMove(); } } else { if (facing != Facing.LEFT) { moveLeft(); stopMove(); } } checkCollide(0); } else { if (getIsTryingToMove()) { if (targetX > actorCenterX) { if (getFacing() != Actor.Facing.RIGHT) { moveRight(); } } else { if (getFacing() != Actor.Facing.LEFT) { moveLeft(); } } } else { if (targetX > actorCenterX) { moveRight(); } else { moveLeft(); } } //try and move int oldMapX = actorX; if (Math.abs(actorCenterX - targetX) > maxFollowDistance) { if (getIsTryingToMove()) { if (getFacing() == Actor.Facing.RIGHT) { actorX += checkCollideRight(); } else { actorX -= checkCollideLeft(); } } if (getCanFly()) { if (mapY < (targetY + 30) || mapY < (manager.findNextFloor(mapX, mapY, height) + Rand.getRange(5, 15))) { flap(); } } else { //we didn't move anywhere - try jumping? if (actorX == oldMapX) { jump(); if (getFacing() == Actor.Facing.RIGHT) { checkCollideRight(); } else { checkCollideLeft(); } } } } else if (getCanFly()) { if (mapY < (targetY + 30) || mapY < (manager.findNextFloor(mapX, mapY, height) + Rand.getRange(5, 15))) { flap(); } if (getFacing() == Actor.Facing.RIGHT) { actorX += checkCollideRight(); } else { actorX -= checkCollideLeft(); } } setMapX(actorX); } } } public void updatePosition() { if (!statusStun) { if (knockBackX > 0) { mapX += checkCollide(knockBackX); } else if (knockBackX < 0) { mapX -= checkCollide(knockBackX); } else { if (isTryingToMove) { if (facing == Facing.RIGHT) { mapX += checkCollideRight(); } else { mapX -= checkCollideLeft(); } checkCollide(0); } else if (vertMoveMode != VertMoveMode.NOT_JUMPING) { checkCollide(0); } } } } public void moveAwayFromPoint(Point p) { if (p != null) { actionMode = ActionMode.NONE; int actorX = getMapX(); int actorCenter = actorX + (getWidth() / 2); int targetX = p.x; int targetY = p.y; int distance = Math.abs(targetX - actorCenter); if (distance <= maxFollowDistance) { if (targetX > actorCenter) { if (facing != Facing.RIGHT) { moveLeft(); stopMove(); } } else { if (facing != Facing.LEFT) { moveRight(); stopMove(); } } } else { if (getIsTryingToMove()) { if (targetX > actorCenter) { if (getFacing() != Actor.Facing.LEFT) { moveLeft(); } } else { if (getFacing() != Actor.Facing.RIGHT) { moveRight(); } } } else { if (targetX > actorCenter) { moveLeft(); } else { moveRight(); } } //try and move int oldMapX = actorX; if (getIsTryingToMove()) { if (getFacing() == Actor.Facing.RIGHT) { actorX += checkCollideRight(); } else { actorX -= checkCollideLeft(); } } if (getCanFly()) { if (mapY < (targetY + 30) || mapY < (manager.findFloor(mapX) + Rand.getRange(25, 60))) { flap(); } } else { //we didn't move anywhere - try jumping? if (actorX == oldMapX) { jump(); } } setMapX(actorX); } } } public void jump() { jump(startJumpSize); } public void jump(int initialVelocity) { if (!statusStun) { if (vertMoveMode == VertMoveMode.NOT_JUMPING || vertMoveMode == VertMoveMode.FLYING) { setVertMoveMode(VertMoveMode.JUMPING); jumpSize = initialVelocity; } } } public void flap() { if (!statusStun) { if (vertMoveMode != VertMoveMode.FLYING) { setVertMoveMode(VertMoveMode.FLYING); } } } public void fear(Point p, long d) { isFeared = true; fearedSource = p; fearedDuration = d; fearedTotalTime = 0; } public void unfear() { isFeared = false; fearedSource = null; fearedDuration = 0; fearedTotalTime = 0; } public void slow(long d) { isSlowed = true; slowedDuration = d; slowedTotalTime = 0; } public void unslow() { isSlowed = false; slowedDuration = 0; slowedTotalTime = 0; } public void poison(long d) { isPoisoned = true; poisonedDuration = d; poisonedTotalTime = 0; } public void unpoison() { isPoisoned = false; poisonedDuration = 0; poisonedTotalTime = 0; } public void setFearedSource(Point p) { fearedSource = p; } public void stopMove() { isTryingToMove = false; isStill = true; } public int getArmorPoints() { return armorPoints; } public int getHitPoints() { return hitPoints; } public int getBaseHitPoints() { return baseHitPoints; } public int getTotalHitPoints() { return totalHitPoints; } public Point getFearedSource() { return fearedSource; } public boolean getStatusStun() { return statusStun; } public String getDebugInfo() { if (debugInfo == null) { return ""; } else { return debugInfo; } } public void setStatusStun(boolean s, long time) { statusStun = s; stunEnded = registry.currentTime + time; if (statusStun) { //stopMove(); updateImage(); actionMode = Actor.ActionMode.NONE; } } protected void updateImage() { //to be overridden } protected void setImage(String name) { if (!name.equals(lastImage)) { BufferedImage im = registry.getImageLoader().getImage(name); if (im != null) { image = name; width = im.getWidth(); height = im.getHeight(); isAnimating = false; } } lastImage = name; } public int attackDamageAndKnockBack(Actor source, Arc2D.Double arc, Point mapPoint, int damage, int kbX, int kbY, String weaponType) { int damageTaken = 0; if (registry.getGameController().multiplayerMode != registry.getGameController().multiplayerMode.CLIENT) { //System.out.println(spriteRect.intersects(r) + ":" + hitPoints); if (arc.intersects(spriteRect) && hitPoints > 0) { int range = 3 * Math.abs(kbX) / 4; if (range < 1) { range = 1; } int randX = Rand.getRange(1, range); int baseX = Math.abs(kbX) / 4; if (kbX < 0) { kbX = baseX + randX; kbX = -1 * kbX; } else { kbX = baseX + randX; } damageTaken = applyDamage(damage, source); if (!disregardKnockBack) { applyKnockBack(kbX, kbY); } } //System.out.println(spriteRect.x+","+spriteRect.y+" "+spriteRect.width+","+spriteRect.height+" "+r.x+","+r.y+" "+r.width+","+r.height); } return damageTaken; } public void applyKnockBack(int x, int y) { knockBackX = x; jump(y); if (registry.getGameController().multiplayerMode == registry.getGameController().multiplayerMode.SERVER && registry.getNetworkThread() != null) { if (registry.getNetworkThread().readyForUpdates()) { UpdateMonster um = new UpdateMonster(this.getId()); um.mapX = this.getMapX(); um.mapY = this.getMapY(); um.action = "ApplyKnockBack"; um.dataInt = x; um.dataInt2 = y; registry.getNetworkThread().sendData(um); } } } public int getKnockBackX() { return knockBackX; } public int applyDamage(int damage, Actor a) { if (damage <= 0) { return 0; } damage -= Math.floor(getArmorPoints() / 5); registerAttacker(a, damage); if (damage <= 0) { damage = 1; } hitPoints -= damage; registry.getIndicatorManager().createIndicator(mapX + (width / 2), mapY + 50, "-" + Integer.toString(damage)); SoundClip cl = new SoundClip(registry, "Weapon/Hit", getCenterPoint()); return damage; } protected void registerAttacker(Actor a, int d) { if (a != null && d > 0) { lastAttacker = a; if (attackers == null) { attackers = new HashMap<Actor, Integer>(); } if (attackers.containsKey(a)) { attackers.put(a, attackers.get(a) + d); } else { attackers.put(a, d); } } } public Actor getLastAttacker() { return lastAttacker; } public Arc2D.Double getAttackArc() { return getAttackArc(attackRange); } public Arc2D.Double getAttackArc(int range) { Arc2D.Double arc = null; if (spriteRect != null) { arc = new Arc2D.Double( (double) spriteRect.x - range + spriteRect.width / 2 + attackArcOffsetX, (double) spriteRect.y - range + spriteRect.height / 2 + attackArcOffsetY, 2 * range, 2 * range, -90, 180, Arc2D.PIE); if (facing == Facing.LEFT) { arc = new Arc2D.Double( (double) spriteRect.x - range + spriteRect.width / 2 + attackArcOffsetX, (double) spriteRect.y - range + spriteRect.height / 2 + attackArcOffsetY, 2 * range, 2 * range, 90, 180, Arc2D.PIE); } } return arc; } public void doChat(long duration) { chatEnd = registry.currentTime + duration; isChatting = true; } public void stopChat() { chatEnd = 0; isChatting = false; } public boolean getIsDead() { return isDead; } public Rectangle getSpriteRect() { return spriteRect; } public boolean getStateChanged() { return stateChanged; } public boolean getCanFly() { return canFly; } protected void setStatuses() { statusFear = false; if (isFeared) { statusFear = true; } statusSlowed = false; if (isSlowed) { statusSlowed = true; } statusPoison = false; if (isPoisoned) { statusPoison = true; } } public void attack() { //to be overridden } public void meleeAttack(WeaponType newWeaponType, int level) { //to be overridden } protected void loopImage(String name, double fDuration) { if (!name.equals(lastImage)) { if (registry.getImageLoader().numImages(name) > 1) { image = name; BufferedImage im = registry.getImageLoader().getImage(name); numAnimationFrames = registry.getImageLoader().numImages(name); width = im.getWidth(); height = im.getHeight(); currentAnimationFrame = 0; animationFrameDuration = (int) (1000 * fDuration); animationFrameUpdateTime = (long) (registry.currentTime + animationFrameDuration); isAnimating = true; } else { setImage(name); } } lastImage = name; } protected void loopImage(String name) { loopImage(name, DEFAULT_ANIMATION_DURATION); } public int checkCollide(int xMove) { //EIError.debugMsg("checkCollide "+xMove+" "+(mapX+baseOffset)+" "+mapX+" "+baseWidth+" "+(height-topOffset)); int xCanMove = 0; boolean hit = false; int blockWidth = manager.getBlockWidth(); int blockHeight = manager.getBlockHeight(); int[] y = ycm; y[0] = y[1] = 0; int xMoveABS = Math.abs(xMove); for (xCanMove = 0; xCanMove < xMoveABS && !hit; xCanMove += blockWidth - 1) { y = getYByVertMoveMode(xCanMove, xMoveABS); hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset); //EIError.debugMsg("Find first hit X "+xCanMove+" Y "+y[0]+" Hit "+hit); } hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset); if (!hit && xCanMove > xMoveABS) { xCanMove = xMoveABS; y = getYByVertMoveMode(xCanMove, xMoveABS); hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset); //EIError.debugMsg("Back off from last loop X "+xCanMove+" Y "+y[0]+" Hit "+hit); } if (hit && xCanMove > 0) { xCanMove = getCollideXBackoffToBlock((xMove > 0 ? xCanMove : -xCanMove), blockWidth); if (xCanMove > 0) { xCanMove--; } //EIError.debugMsg("Back off from hit X "+xCanMove+" Y "+y[0]+" Hit "+hit); } if (vertMoveMode == VertMoveMode.NOT_JUMPING) { if (xCanMove > xMoveABS) { xCanMove = xMoveABS; hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset); } if (hit) { y = stepUp(xMove, xCanMove, blockWidth, blockHeight); xCanMove = y[1]; //EIError.debugMsg("Step up X "+xCanMove+" Y "+y[0]+" Hit "+hit); } } else { y = fixCollideY(y, xCanMove, xMove, blockHeight); if (y[0] == 0 && xCanMove == 0 && vertMoveMode == VertMoveMode.FLYING) { //try ceiling slide xCanMove++; hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY, baseWidth, height - topOffset); if (hit) { xCanMove = 0; } //EIError.debugMsg("Ceiling slide X "+xCanMove+" Y "+y[0]+" Hit "+hit); } } if (manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset)) { y[0] = 0; xCanMove = 0; } mapY += y[0]; return xCanMove; } public int[] stepUp(int xMove, int xCanMove, int blockWidth, int blockHeight) { yx[0] = 0; yx[1] = xCanMove; boolean hit = false; hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? (xCanMove + blockWidth / 8) : -(xCanMove + blockWidth / 8)), mapY + blockHeight, baseWidth, height - topOffset); if (!hit) { yx[0] = blockHeight; yx[1] = xCanMove + blockWidth / 8; } //registry.getIndicatorManager().createIndicator(mapX + (width / 2), mapY + 50, Integer.toString(yx[1])); return yx; } public int[] fixCollideY(int[] y, int xCanMove, int xMove, int blockHeight) { boolean hit = false; int xMoveABS = Math.abs(xMove); y = getYByVertMoveMode(xCanMove, xMoveABS); hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset); if (hit) { y = backOffY(y, (xMove > 0 ? xCanMove : -xCanMove), blockHeight); y[1] = y[0]; //EIError.debugMsg("Back off y X "+xCanMove+" Y "+y[0]+" Hit "+hit); } if (y[0] > y[1]) { //falling hit = false; for (; y[0] > y[1] && !hit; y[0] -= blockHeight) { hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset); } if (y[0] < y[1]) { y[0] = y[1]; } //EIError.debugMsg("Falling backoff y X "+xCanMove+" Y "+y[0]+" Hit "+hit); hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset); if (hit) { y = backOffY(y, (xMove > 0 ? xCanMove : -xCanMove), blockHeight); //EIError.debugMsg("Falling backoff y X "+xCanMove+" Y "+y[0]+" Hit "+hit); } } else if (y[0] < y[1]) { //jumping hit = false; for (; y[0] < y[1] && !hit; y[0] += blockHeight) { hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset); } if (y[0] > y[1]) { y[0] = y[1]; } //EIError.debugMsg("Jumping backoff y X "+xCanMove+" Y "+y[0]+" Hit "+hit); hit = manager.doesRectContainBlocks(mapX + baseOffset + (xMove > 0 ? xCanMove : -xCanMove), mapY + y[0], baseWidth, height - topOffset); if (hit && y[0] != 0) { y = backOffY(y, (xMove > 0 ? xCanMove : -xCanMove), blockHeight); y[0]--; //EIError.debugMsg("Jumping backoff y X "+xCanMove+" Y "+y[0]+" Hit "+hit); } } return y; } public int[] backOffY(int[] y, int x, int blockHeight) { boolean hit = true; if (y[0] < 0) { y[0] = getCollideYBackoffToBlock(y[0], blockHeight); for (; y[0] < 0 && hit;) { hit = manager.doesRectContainBlocks(mapX + baseOffset + x, mapY + y[0], baseWidth, height - topOffset); if (hit) { y[0] = getCollideYBackoffToBlock(y[0] + 1, blockHeight); } } } else if (y[0] > 0) { y[0] = getCollideYBackoffToBlock(y[0], blockHeight) - 1; for (; y[0] > 0 && hit;) { hit = manager.doesRectContainBlocks(mapX + baseOffset + x, mapY + y[0], baseWidth, height - topOffset); if (hit) { y[0] = getCollideYBackoffToBlock(y[0] - 1, blockHeight) - 1; } } } return y; } protected BufferedImage flipHorizontal(BufferedImage bi) { AffineTransform tx; AffineTransformOp op; tx = AffineTransform.getScaleInstance(1, -1); tx = AffineTransform.getScaleInstance(-1, 1); tx.translate(-bi.getWidth(), 0); op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); bi = op.filter(bi, null); return bi; } private int getCollideXBackoffToBlock(int xPosChange, int blockWidth) { int xPosNew = mapX + baseOffset + xPosChange; if (xPosChange > 0) { xPosNew += baseWidth; } xPosNew = (xPosNew / blockWidth) * blockWidth; if (xPosChange < 0) { xPosNew += blockWidth; } xPosNew -= mapX + baseOffset; if (xPosChange > 0) { xPosNew -= baseWidth; } //EIError.debugMsg("getCollideXBackoffToBlock "+xPosNew); return Math.abs(xPosNew); } private int getCollideYBackoffToBlock(int yPosChange, int blockHeight) { int yPosNew = mapY + yPosChange; if (yPosChange > 0) { yPosNew += height - topOffset; } yPosNew = (yPosNew / blockHeight) * blockHeight; if (yPosChange < 0) { yPosNew += blockHeight; } yPosNew -= mapY; if (yPosChange > 0) { yPosNew -= height - topOffset; } return yPosNew; } private int[] getYByVertMoveMode(int i, int xMove) { int[] y = new int[2]; y[0] = y[1] = 0; if (vertMoveMode == VertMoveMode.FALLING) { y[1] = -fallSize; if (i != 0) { y[0] = -1 * (int) ((float) (fallSize * i) / (float) xMove); } if (y[0] < y[1]) { y[0] = y[1]; } } else if (vertMoveMode == VertMoveMode.JUMPING) { y[1] = jumpSize; if (i != 0) { y[0] = (int) ((float) (jumpSize * i) / (float) xMove); } if (y[0] > y[1]) { y[0] = y[1]; } } else if (vertMoveMode == VertMoveMode.FLYING) { y[1] = ascendSize; if (i != 0) { y[0] = (int) ((float) (ascendSize * i) / (float) xMove); } if (y[0] > y[1]) { y[0] = y[1]; } } return y; } public int checkCollideRight() { return checkCollide(xMoveSize); } public int checkCollideLeft() { return checkCollide(-1 * xMoveSize); } public void stopLooping() { isAnimating = false; } public int getWidth() { return width; } public int getHeight() { return height; } public Point getCenterPoint() { if (spriteRect == null) { int offsetX = -1 * spriteRectOffestX; if (facing == Facing.RIGHT) { offsetX = spriteRectOffestX; } spriteRect = new Rectangle(mapX + baseOffset + offsetX, mapY - topOffset + spriteRectOffestY, baseWidth, height - topOffset); } Point p = new Point(spriteRect.x + spriteRect.width / 2, spriteRect.y + spriteRect.height / 2); return p; } public boolean isActive() { return isActive; } public boolean isFeared() { return isFeared; } public boolean isSlowed() { return isSlowed; } public boolean isPoisoned() { return isPoisoned; } public boolean isWithinAttackRange(Point p) { if (getCenterPoint().distance(p) <= attackRange) { return true; } else { return false; } } public AttackType getCurrentAttackType() { return currentAttackType; } public int getAttackRange() { return attackRange; } public Rectangle getAttackRect(int range) { Rectangle rect = new Rectangle(mapX + baseOffset + baseWidth / 2, mapY - topOffset - range, baseWidth / 2 + range, height + range * 2); if (facing == Facing.LEFT) { rect = new Rectangle(mapX + baseOffset - range, mapY - topOffset - range, baseWidth / 2 + range, height + range * 2); } return rect; } public void setActive(boolean a) { isActive = a; } public void setMapX(int x) { mapX = x; } public void setPosition(int x, int y) { mapX = x; mapY = y; } public void setFacing(Facing f) { facing = f; } public void setActionMode(ActionMode a) { actionMode = a; } public void setFallSize(int fs) { fallSize = fs; } public int getMapX() { return mapX; } public int getMapY() { return mapY; } public Facing getFacing() { return facing; } public ActionMode getActionMode() { return actionMode; } public boolean getIsTryingToMove() { return isTryingToMove; } public boolean getIsFollowing() { //meant to be overridden - specially for the robot return false; } public Boolean getShowRect() { return showRect; } public Rectangle getPerimeter() { return new Rectangle(mapX, mapY, width, height); } protected void checkIfFalling() { if (vertMoveMode != VertMoveMode.JUMPING && vertMoveMode != VertMoveMode.FLYING) { Point p = null; boolean falling = true; if (manager.doesRectContainBlocks(mapX + baseOffset, mapY - 1, baseWidth, height - topOffset)) { falling = false; knockBackX = 0; } if (falling == true) { totalFall = 0; setVertMoveMode(VertMoveMode.FALLING, false); } else if (falling != true && vertMoveMode != VertMoveMode.NOT_JUMPING) { setVertMoveMode(VertMoveMode.NOT_JUMPING, true); } } } public void updateJumping() { //check if we can keep jumping or not if (jumpSize < 0) { //player reached the top of the jump jumpSize = startJumpSize; setFallSize(0); setVertMoveMode(VertMoveMode.FALLING); } else { if (mapY - lastMapY < jumpSize && (mapY - lastMapY) > 0) { setVertMoveMode(VertMoveMode.FALLING, false); } jumpSize -= gravity; } } public void updateAscending() { //check if we can keep ascending or not if (ascendSize < 0) { //player reached the top of the ascend ascendSize = ascendOriginalSize; ascendCount = 0; fallSize = 0; setVertMoveMode(VertMoveMode.FALLING, false); } else { if (ascendCount >= ascendMax) { ascendSize -= gravity; } ascendCount++; } } public void updateFalling() { if (this.getTotalHitPoints() == 6000) { //System.out.println(lastMapY + ":" + mapY + ":" + fallSize); } if (lastMapY - mapY < fallSize && fallSize > 0) { finishJumping(); } else { totalFall += fallSize; } fallSize += gravity; completeFall += gravity; if (fallSize > maxFallSize) { fallSize = maxFallSize; } } protected void finishJumping() { //EIError.debugMsg("finishJumping"); setVertMoveMode(VertMoveMode.NOT_JUMPING); totalFall = 0; fallSize = 0; knockBackX = 0; if (!isTryingToMove) { stopMove(); } else { if (facing == Facing.RIGHT) { moveRight(); } else { moveLeft(); } } } public void setShowRect(boolean r) { showRect = r; } public void setShowGoals(boolean g) { showGoals = g; } public void setStateChanged(boolean s) { if (s) { stateChanged = s; } } public void setDebugInfo(String d) { debugInfo = d; } public void setVertMoveMode(VertMoveMode v) { //System.out.println("VertMoveMode "+v); setVertMoveMode(v, true); } public Actor.VertMoveMode getVertMoveMode() { return vertMoveMode; } public int getXMoveSize() { return xMoveSize; } public void setXMoveSize(int x) { xMoveSize = x; } public void setVertMoveMode(VertMoveMode v, boolean sc) { if (sc) { stateChanged = sc; } vertMoveMode = v; if (vertMoveMode == VertMoveMode.NOT_JUMPING) { completeFall = 0; } } public void setIsTryingToMove(boolean m) { isTryingToMove = m; } public void update() { lastMapY = mapY; spriteRect = null; int offsetX = -1 * spriteRectOffestX; if (facing == Facing.RIGHT) { offsetX = spriteRectOffestX; } spriteRect = new Rectangle(mapX + baseOffset + offsetX, mapY - topOffset + spriteRectOffestY, baseWidth, height - topOffset); if (isChatting && registry.currentTime >= chatEnd) { isChatting = false; } if (statusStun && registry.currentTime >= stunEnded) { this.setStatusStun(false, 0); } if (isActive && isFeared) { long p = registry.getImageLoader().getPeriod(); fearedTotalTime += (registry.getImageLoader().getPeriod()) % (long) (1000 * fearedDuration); // calculate current displayable image position if (fearedTotalTime >= (fearedDuration * 1000)) { unfear(); } } if (isActive && isSlowed) { long p = registry.getImageLoader().getPeriod(); slowedTotalTime += (registry.getImageLoader().getPeriod()) % (long) (1000 * slowedDuration); // calculate current displayable image position if (slowedTotalTime >= (slowedDuration * 1000)) { unslow(); } } if (isActive && isPoisoned) { long p = registry.getImageLoader().getPeriod(); poisonedTotalTime += (registry.getImageLoader().getPeriod()) % (long) (1000 * poisonedDuration); // calculate current displayable image position if (poisonedTotalTime >= (poisonedDuration * 1000)) { unpoison(); } } setStatuses(); if (spriteRect.intersects(manager.getPanelRect())) { shouldRender = true; } else { shouldRender = false; } } public void render(Graphics g) { if (shouldRender) { int xPos = 0, yPos = 0; BufferedImage im; BufferedImage imLeft; AffineTransform tx; AffineTransformOp op; if (isChatting) { im = registry.getImageLoader().getImage("Misc/ChatBubble"); if (facing == Facing.LEFT) { xPos = manager.mapToPanelX(mapX - width + 25); yPos = manager.mapToPanelY(mapY + 10); } else { xPos = manager.mapToPanelX(mapX + width - 25); yPos = manager.mapToPanelY(mapY + 10); } //flip the yPos since drawing happens top down versus bottom up yPos = manager.getPHeight() - yPos; //subtract the height since points are bottom left and drawing starts from top left yPos -= height; if (im != null) { if (facing == Facing.LEFT) { tx = AffineTransform.getScaleInstance(1, -1); tx = AffineTransform.getScaleInstance(-1, 1); tx.translate(-width, 0); op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); imLeft = op.filter(im, null); if (imLeft != null) { g.drawImage(imLeft, xPos, yPos, null); } } else { g.drawImage(im, xPos, yPos, null); } } } if (showRect && spriteRect != null) { xPos = manager.mapToPanelX(spriteRect.x); yPos = manager.mapToPanelY(spriteRect.y); //flip the yPos since drawing happens top down versus bottom up yPos = manager.getPHeight() - yPos; //subtract the height since points are bottom left and drawing starts from top left yPos -= height; g.setColor(Color.red); g.drawRect(xPos, yPos, spriteRect.width, spriteRect.height); } if (showGoals && debugInfo != null) { xPos = manager.mapToPanelX(mapX); yPos = manager.mapToPanelY(mapY + height + 20); //flip the yPos since drawing happens top down versus bottom up yPos = manager.getPHeight() - yPos; //subtract the height since points are bottom left and drawing starts from top left yPos -= height; String[] parts = debugInfo.split("\\|"); for (int i = 0; i < parts.length; i++) { g.setColor(Color.RED); g.setFont(new Font("SansSerif", Font.BOLD, 18)); g.drawString(parts[i], xPos, yPos + (i * 15)); } } if (showRect && attackRect != null) { xPos = manager.mapToPanelX(attackRect.x); yPos = manager.mapToPanelY(attackRect.y); //flip the yPos since drawing happens top down versus bottom up yPos = manager.getPHeight() - yPos; //subtract the height since points are bottom left and drawing starts from top left yPos -= attackRect.height + topOffset; g.setColor(Color.red); g.drawRect(xPos, yPos, attackRect.width, attackRect.height); } } } private void readObject(ObjectInputStream aInputStream) throws Exception { aInputStream.defaultReadObject(); } private void writeObject(ObjectOutputStream aOutputStream) throws Exception { aOutputStream.defaultWriteObject(); } }