/* Copyright 2012 Jan Ove Saltvedt This file is part of KBot. KBot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. KBot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with KBot. If not, see <http://www.gnu.org/licenses/>. */ package com.kbotpro.scriptsystem.wrappers; import com.kbotpro.bot.BotEnvironment; import com.kbotpro.hooks.*; import com.kbotpro.scriptsystem.interfaces.Targetable; import com.kbotpro.scriptsystem.interfaces.MouseTarget; import com.kbotpro.scriptsystem.input.jobs.MouseHoverJob; import com.kbotpro.scriptsystem.input.jobs.MouseJob; import com.kbotpro.scriptsystem.input.callbacks.MouseMoveListener; import com.kbotpro.scriptsystem.various.KTimer; import com.kbotpro.scriptsystem.various.Point3D; import java.awt.*; import java.util.*; import java.util.List; /** * Wrapper for in game character like Players and NPCs */ public abstract class Character extends GameObject implements Targetable { private com.kbotpro.hooks.Character rChar; protected Character(BotEnvironment botEnv, com.kbotpro.hooks.Character rChar) { super(botEnv, rChar); this.rChar = rChar; } /** * Be aware that this does not contain accurate data. * The data does not get deleted after walking is done, but overwritten when you walk again. * * @return Returns an array of the walking queue of the character. */ public Tile[] getWalkingArray() { int[] xPoints = rChar.getWalkingX(); int[] yPoints = rChar.getWalkingY(); Client client = getClient(); int baseX = client.getBaseX(); int baseY = getClient().getBaseY(); int maxIndex = getMotion(); Tile[] out = new Tile[maxIndex]; for (int i = 0; i < maxIndex; i++) { out[i] = new Tile(xPoints[i] + baseX, yPoints[i] + baseY); } return out; } public Point getScreenPos() { Model model = getModel(); if(model != null){ Point3D point3D = model.createSeed(); return getCalculations().worldToScreen(getRegionalX() + point3D.x, getRegionalY()+point3D.z, -point3D.y); } int posX = getRegionalX(); int posY = getRegionalY(); int height = (getHeight() >> 1); // Divide by two and negate return getCalculations().worldToScreen(posX, posY, height); } public Point getCenter() { Model model = getModel(); if(model != null){ Point3D point3D = model.getCenter(); return getCalculations().worldToScreen(getRegionalX() + point3D.x, getRegionalY()+point3D.z, -point3D.y); } int posX = getRegionalX(); int posY = getRegionalY(); int height = (getHeight() >> 1); // Divide by two and negate return getCalculations().worldToScreen(posX, posY, height); } /** * Gets the height in RS units of the character * * @return integer containing height */ public int getHeight() { return -rChar.getHeight(); } /** * Gets the animation ID of the character * * @return return an integer containing animation or -1 if no animation. */ public int getAnimation() { return rChar.getAnimation(); } /** * Gets the motion length in the client. * This is 0 if still and also represents how many the length of the walking queue array * * @return integer; 0 if standing still or otherwise 1-3 */ public int getMotion() { return rChar.getMotion(); } /** * Checks if the character is currently in motion * * @return boolean true if mooving. */ public boolean isMoving() { return getMotion() != 0; } /** * Gets the model of the character * * @return */ public Model getModel() { com.kbotpro.hooks.Model model = rChar.getModel(); if (model == null) { return null; } return new TransformableGameModel(botEnv, model, this); } /** * Gets the character models. (Normally just one) * * @return * @deprecated DOES NOT WORK as of #574. */ public Model[] getModels() { List<Model> out = new ArrayList<Model>(); com.kbotpro.hooks.Model[] models = rChar.getModels(); for (int i = 0; i < models.length; i++) { if (models[i] == null) { continue; } out.add(new GameModel(botEnv, models[i], this)); } return out.toArray(new Model[out.size()]); } /** * Get the orientation around the Y axis. This is runescapes unit system. * 0 is south. * 4095 is west * 8191 is north * 12287 is east * 16383 is max and is also south * * * @return */ public int getOrientationYAxis() { return rChar.getOrientation(); } /** * Gets the orientation of the character * 0 is south * 90 is west * 180 is north * 270 is east * * @return */ public double getOrientation() { long con = getOrientationYAxis() * 360; return (double) con / 0x3FFF; } /** * Get target * * @return */ public MouseTarget getTarget() { if (getModel() != null) { return new MouseTarget() { public Point get() { return getCenter(); } public boolean isOver(int posX, int posY) { return getModel().isPointOver(posX, posY /*,true*/); } }; } else { return new MouseTarget() { public Point get() { return getCenter(); } public boolean isOver(int posX, int posY) { Point p = getScreenPos(); return new Rectangle(p.x - 2, p.y - 2, 4, 4).contains(posX, posY); } }; } } /** * Moves the mouse to the object and clicks at the given action * NOTE: Do not use this method while you have a mouse job active! * * @param actionContains A string that the action contains. Case ignored * @return Boolean, true if succeeded, false if not. */ public boolean doAction(final String actionContains) { if (!onScreen()) { return false; } final boolean[] ret = new boolean[]{false}; MouseHoverJob mouseHoverJob = botEnv.mouse.createMouseHoverJob(new MouseMoveListener() { private int count = 0; public void onMouseOverTarget(MouseJob mouseJob) { MouseHoverJob mouseHoverJob = (MouseHoverJob) mouseJob; count++; if (count > random(5, 100)) { mouseHoverJob.stop(); ret[0] = botEnv.menu.atMenu(actionContains); } } public void onFinished(MouseJob mouseJob) { } }, this, new KTimer(5000)); mouseHoverJob.start(); mouseHoverJob.join(); return ret[0]; } public boolean doClick() { if (!onScreen()) { return false; } final boolean[] ret = new boolean[]{false}; MouseHoverJob mouseHoverJob = botEnv.mouse.createMouseHoverJob(new MouseMoveListener() { private int count = 0; public void onMouseOverTarget(MouseJob mouseJob) { MouseHoverJob mouseHoverJob = (MouseHoverJob) mouseJob; count++; if (count > random(5, 100)) { mouseHoverJob.doMouseClick(true); ret[0] = true; mouseHoverJob.stop(); } } public void onFinished(MouseJob mouseJob) { } }, this, new KTimer(5000)); mouseHoverJob.start(); mouseHoverJob.join(); return ret[0]; } /** * Hovers over the PhysicalObject. * @param ms Time in milliseconds to hover. */ public void hover(int ms) { if (!onScreen()) { return; } final KTimer timeout = new KTimer(ms); MouseHoverJob mouseHoverJob = botEnv.mouse.createMouseHoverJob(new MouseMoveListener() { public void onMouseOverTarget(MouseJob mouseJob) { MouseHoverJob mouseHoverJob = (MouseHoverJob) mouseJob; if (timeout.isDone()) { mouseHoverJob.stop(); } } public void onFinished(MouseJob mouseJob) { } }, this, timeout); mouseHoverJob.start(); mouseHoverJob.join(); } public boolean onScreen() { return botEnv.calculations.isInGameArea(getScreenPos()); } /** * Gets the current frames index. Can be used for timing stuff like high alching ;) * * @return */ public int getCurrentAnimationFrameIndex() { return rChar.getCurrentAnimationFrame(); } /** * Gets the character the player is interacting with or null if none. * Cast this to Player OR NPC if you need more specific * * @return */ public Character getInteracting() { int index = rChar.getInteractingCharacterIndex(); if (index == -1) return null; if (index < 32768) { return botEnv.npcs.getNPCAtIndex(index); } else { index -= 32768; return new Player(botEnv, botEnv.client.getPlayers()[index]); } } /** * Checks if the character is interacting with another character! * DOES NOT SUPPORT interaction with objects * * @return */ public boolean isInteracting() { return getInteracting() != null; } /** * Checks if the character is currently in combat. * * @return */ public boolean isInCombat() { int loopCycleStatus = botEnv.client.getLoopCycle()-130; for(int loopCycle: rChar.getHitLoopCycleArray()){ if(loopCycle > loopCycleStatus){ return true; } } return false; } /** * This method gets the character current hp percentage by reading the length of the hp bar. * Therefor this only works if the character is in combat. If the character is not in combat it will retun 100% even if its low on HP. * @return the percentage of hp the character has left */ public int getHPPercent() { return isInCombat() ? rChar.getHPRatio() * 100 / 255 : 100; } /** * Gets the message currently hovering over the character. * @return */ public String getMessage(){ return rChar.getMessage(); } }