Have fun, report all errors.
In all files you edit add:
In MapleCharacter change:Code:import net.sf.odinms.server.maps.FakeCharacter;
toCode:private MapleCharacter() {
and add:Code:public MapleCharacter() {
andCode:private List<FakeCharacter> fakes = new ArrayList<FakeCharacter>(); public boolean isfake = false;
In net.sf.odinms.server.maps add FakeCharacter.javaCode:public void setID(int id){ this.id = id; } public void setJob(int job){ this.job = MapleJob.getById(job); } public void setInventory(MapleInventoryType type, MapleInventory inv) { inventory[type.ordinal()] = inv; } public boolean hasFakeChar() { for (FakeCharacter ch : fakes) { if(ch != null) return true; } return false; } public List<FakeCharacter> getFakeChars() { return fakes; } public void addFakeChar(FakeCharacter f) { fakes.add(f); }
In MapleMap.java add:Code:package net.sf.odinms.server.maps; import net.sf.odinms.client.IItem; import net.sf.odinms.client.MapleCharacter; import net.sf.odinms.client.MapleInventoryType; /** * * @author Patrick/PurpleMadness */ public class FakeCharacter { private MapleCharacter ch; public FakeCharacter(MapleCharacter player, int id) { MapleCharacter fakechr = new MapleCharacter(); fakechr.setHair(player.getHair()); fakechr.setFace(player.getFace()); fakechr.setSkinColor(player.getSkinColor()); fakechr.setName(player.getName()); fakechr.setID(id + 100000); fakechr.setLevel(player.getLevel()); fakechr.setJob(player.getJob().getId()); fakechr.setMap(player.getMap()); fakechr.setPosition(player.getPosition()); fakechr.silentGiveBuffs(player.getAllBuffs()); for(IItem equip : player.getInventory(MapleInventoryType.EQUIPPED)){ fakechr.getInventory(MapleInventoryType.EQUIPPED).addFromDB(equip); } fakechr.isfake = true; player.getMap().addBotPlayer(fakechr); ch = fakechr; } public MapleCharacter getFakeChar() { return ch; } }
In MapleMap.java change:Code:/** * Adds a player to this map and sends nescessary data * * @param chr */ public void addBotPlayer(MapleCharacter chr) { //log.warn("[dc] [level2] Player {} enters map {}", new Object[] { chr.getName(), mapid }); synchronized (characters) { this.characters.add(chr); } synchronized (this.mapobjects) { if (!chr.isHidden()) { broadcastMessage(chr, (MaplePacketCreator.spawnPlayerMapobject(chr)), false); /*MaplePet[] pets = chr.getPets(); for (int i = 0; i < 3; i++) { if (pets[i] != null) { broadcastMessage(chr, MaplePacketCreator.showPet(chr, pets[i], false, false), false); } }*/ } this.mapobjects.put(Integer.valueOf(chr.getObjectId()), chr); } }
toCode:if (chr.getPosition().distanceSq(mapobject.getPosition()) <= MapleCharacter.MAX_VIEW_RANGE_SQ) {
andCode:if (chr.getPosition().distanceSq(mapobject.getPosition()) <= MapleCharacter.MAX_VIEW_RANGE_SQ && !chr.isfake) {
toCode:private void broadcastMessage(MapleCharacter source, MaplePacket packet, double rangeSq, Point rangedFrom) { synchronized (characters) { for (MapleCharacter chr : characters) { if (chr != source) {
andCode:private void broadcastMessage(MapleCharacter source, MaplePacket packet, double rangeSq, Point rangedFrom) { synchronized (characters) { for (MapleCharacter chr : characters) { if (chr != source && !chr.isfake) {
toCode:private void updateMapObjectVisibility(MapleCharacter chr, MapleMapObject mo) {
andCode:private void updateMapObjectVisibility(MapleCharacter chr, MapleMapObject mo) { if(chr.isfake) return;
toCode:public void movePlayer(MapleCharacter player, Point newPosition) { player.setPosition(newPosition);
In MovePlayerHandler.java addCode:public void movePlayer(MapleCharacter player, Point newPosition) { player.setPosition(newPosition); if(player.isfake) return;
afterCode:if(c.getPlayer().hasFakeChar()) { int i = 1; for (final FakeCharacter ch : c.getPlayer().getFakeChars()) { ScheduledFuture<?> scheduleRemove = TimerManager.getInstance().schedule(new Runnable() { @Override public void run() { MaplePacket packet = MaplePacketCreator.movePlayer(ch.getFakeChar().getId(), res); ch.getFakeChar().getMap().broadcastMessage(ch.getFakeChar(), packet, false); updatePosition (res, ch.getFakeChar(), 0); ch.getFakeChar().getMap().movePlayer(ch.getFakeChar(), ch.getFakeChar().getPosition()); } }, i * 300); i++; } }
AddCode:c.getPlayer().getMap().movePlayer(c.getPlayer(), c.getPlayer().getPosition());
and change:Code:import net.sf.odinms.server.TimerManager; import java.util.concurrent.ScheduledFuture;
toCode:List<LifeMovementFragment> res = parseMovement(slea);
In MapleClient.java addCode:final List<LifeMovementFragment> res = parseMovement(slea);
afterCode:if(chr.hasFakeChar()) { for (FakeCharacter ch : chr.getFakeChars()) { ch.getFakeChar().getMap().removePlayer(ch.getFakeChar()); } }
In CloseRangeDamageHandler addCode:public void disconnect() { // pingTask.cancel(true); MapleCharacter chr = this.getPlayer(); if (chr != null && isLoggedIn()) {
afterCode:if(c.getPlayer().hasFakeChar()) { for (FakeCharacter ch : c.getPlayer().getFakeChars()) { MaplePacket packett = MaplePacketCreator.closeRangeAttack(ch.getFakeChar().getId(), attack.skill, attack.stance, attack.numAttackedAndDamage, attack.allDamage, attack.speed); player.getMap().broadcastMessage(ch.getFakeChar(), packett, false, true); applyAttack(attack, ch.getFakeChar(), maxdamage, attackCount); } }
In FacialExpressionHandler.java addCode:applyAttack(attack, player, maxdamage, attackCount);
afterCode:for (FakeCharacter ch : c.getPlayer().getFakeChars()) { c.getPlayer().getMap().broadcastMessage(ch.getFakeChar(), MaplePacketCreator.facialExpression(ch.getFakeChar(), emote), false); }
In MapleMonster.java change:Code:c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.facialExpression(c.getPlayer(), emote), false);
toCode:@Override public void sendSpawnData(MapleClient client) { if (!isAlive()) { return; }
in maplecharacter.javaCode:@Override public void sendSpawnData(MapleClient client) { if (!isAlive() || client.getPlayer().isfake) { return; }
add:
beforeCode:if(hasFakeChar()) { for (FakeCharacter ch : getFakeChars()) { ch.getFakeChar().getMap().removePlayer(ch.getFakeChar()); } }
Here's the command:Code:getClient().getSession().write(warpPacket);
and that should give you a basic clone.Code:else if (splitted[0].equals("!fakechar")) { for(int i = 0; i < getOptionalIntArg(splitted, 1, 1); i++) { FakeCharacter fc = new FakeCharacter(c.getPlayer(), c.getPlayer().getId() + c.getPlayer().getFakeChars().size() + 1); c.getPlayer().addFakeChar(fc); } mc.dropMessage("Please move around for it to take effect."); }
if there's an error, just reply and I should be able to help.
edit:
forgot to say, lol flam at wil!
edit:
Forgot to add, thanks to PurpleMadness for his FakeCharacter.java that I edited.


![[Release] Clone system](http://ragezone.com/hyper728.png)

