L2JMobius

Public Development => Shares/Contributions => Topic started by: BazookaRpm on June 02, 2025, 08:05:58 PM

Title: Polymorph for Admin
Post by: BazookaRpm on June 02, 2025, 08:05:58 PM
Hi friends, I'm sharing this code that the administrator can use to change the appearance of a mob based on its ID.

Motivated to continue collaborating with free tier users.

The admin command can change your appearance to show it to other players.
For example: you use the following admin command //polymorph 29022
where the ID: 29022 corresponds to Zaken, then all other players will see you as Zaken, the same if you apply the ID: 25286 everyone will see you as the raid boss Anakim

First we are going to create two new methods in Java in the following path.
Route : dist\game\data\scripts\handlers\admincommandhandlers\AdminPolymorph.java
below is the code we will create.

Code: [Select]
/*
 * This file is part of the L2J Mobius project.
 *
 * This program 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.
 *
 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 * Este comando debe ser registrado en masterhandlers.
 */
package handlers.admincommandhandlers;

import org.l2jmobius.gameserver.handler.IAdminCommandHandler;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.util.BuilderUtil;

public class AdminPolymorph implements IAdminCommandHandler
{
private static final String[] ADMIN_COMMANDS =
{
"admin_polymorph",   // Comando para poder usar el poliformismo de apariencia
"admin_unpolymorph"  // Comando para poder remover el poliformismo de apariencia
};

[member=79]override[/member]
public boolean useAdminCommand(String command, Player activeChar)
{
String[] tokens = command.split(" ");
String cmd = tokens[0];

WorldObject target = activeChar.getTarget();
if (target == null)
{
BuilderUtil.sendSysMessage(activeChar, "You must select a target.");
return false;
}

if (!target.isPlayer())
{
BuilderUtil.sendSysMessage(activeChar, "Only players can be polymorphed.");
return false;
}

Player player = target.asPlayer();

if (cmd.equalsIgnoreCase("admin_polymorph"))
{
if (tokens.length < 2)
{
BuilderUtil.sendSysMessage(activeChar, "Usage: //polymorph <npcId>");
return false;
}

int polyId;
try
{
polyId = Integer.parseInt(tokens[1]);
}
catch (NumberFormatException e)
{
BuilderUtil.sendSysMessage(activeChar, "Invalid NPC ID.");
return false;
}

player.getPoly().setPolyInfo("npc", String.valueOf(polyId));
player.decayMe();
player.spawnMe(player.getX(), player.getY(), player.getZ());
player.broadcastUserInfo();

BuilderUtil.sendSysMessage(activeChar, "Polymorph applied successfully.");
}
else if (cmd.equalsIgnoreCase("admin_unpolymorph"))
{
player.getPoly().resetPolyInfo();
player.decayMe();
player.spawnMe(player.getX(), player.getY(), player.getZ());
player.broadcastUserInfo();

BuilderUtil.sendSysMessage(activeChar, "Polymorph removed successfully.");
}

return true;
}

[member=79]override[/member]
public String[] getAdminCommandList()
{
return ADMIN_COMMANDS;
}
}

Next we will add the following codes.We will update charInfo to show us the polymorph
Route: java\org\l2jmobius\gameserver\network\serverpackets\CharInfo.java
Code: [Select]
/*
 * Copyright (c) 2013 L2jMobius
 */
package org.l2jmobius.gameserver.network.serverpackets;

import org.l2jmobius.Config;
import org.l2jmobius.commons.network.WritableBuffer;
import org.l2jmobius.gameserver.instancemanager.CursedWeaponsManager;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.actor.appearance.PlayerAppearance;
import org.l2jmobius.gameserver.model.actor.instance.Decoy;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.skill.AbnormalVisualEffect;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.ServerPackets;

public class CharInfo extends ServerPacket
{
private final Player _player;
private int _objId;
private int _x;
private int _y;
private int _z;
private int _heading;
private final int _mAtkSpd;
private final int _pAtkSpd;
private final int _runSpd;
private final int _walkSpd;
private final int _swimRunSpd;
private final int _swimWalkSpd;
private final int _flyRunSpd;
private final int _flyWalkSpd;
private final double _moveMultiplier;
private int _vehicleId = 0;
private final boolean _gmSeeInvis;

public CharInfo(Player player, boolean gmSeeInvis)
{
_player = player;
_objId = player.getObjectId();
if ((_player.getVehicle() != null) && (_player.getInVehiclePosition() != null))
{
_x = _player.getInVehiclePosition().getX();
_y = _player.getInVehiclePosition().getY();
_z = _player.getInVehiclePosition().getZ();
_vehicleId = _player.getVehicle().getObjectId();
}
else
{
_x = _player.getX();
_y = _player.getY();
_z = _player.getZ();
}
_heading = _player.getHeading();
_mAtkSpd = _player.getMAtkSpd();
_pAtkSpd = (int) _player.getPAtkSpd();
_moveMultiplier = player.getMovementSpeedMultiplier();
_runSpd = (int) Math.round(player.getRunSpeed() / _moveMultiplier);
_walkSpd = (int) Math.round(player.getWalkSpeed() / _moveMultiplier);
_swimRunSpd = (int) Math.round(player.getSwimRunSpeed() / _moveMultiplier);
_swimWalkSpd = (int) Math.round(player.getSwimWalkSpeed() / _moveMultiplier);
_flyRunSpd = player.isFlying() ? _runSpd : 0;
_flyWalkSpd = player.isFlying() ? _walkSpd : 0;
_gmSeeInvis = gmSeeInvis;
}

public CharInfo(Decoy decoy, boolean gmSeeInvis)
{
this(decoy.asPlayer(), gmSeeInvis);
_objId = decoy.getObjectId();
_x = decoy.getX();
_y = decoy.getY();
_z = decoy.getZ();
_heading = decoy.getHeading();
}

[member=79]override[/member]
public void writeImpl(GameClient client, WritableBuffer buffer)
{
if (_player.getPoly().isMorphed())
{
new NpcInfoPoly(_player).writeImpl(client, buffer);
return;
}

ServerPackets.CHAR_INFO.writeId(this, buffer);
buffer.writeInt(_x);
buffer.writeInt(_y);
buffer.writeInt(_z);
buffer.writeInt(_vehicleId);
buffer.writeInt(_objId);
final PlayerAppearance appearance = _player.getAppearance();
buffer.writeString(appearance.getVisibleName());
buffer.writeInt(_player.getRace().ordinal());
buffer.writeInt(appearance.isFemale());
buffer.writeInt(_player.getBaseClass());

buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_UNDER));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_HEAD));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_RHAND));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LHAND));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_GLOVES));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CHEST));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_LEGS));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_FEET));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_CLOAK));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_RHAND));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_HAIR));
buffer.writeInt(_player.getInventory().getPaperdollItemDisplayId(Inventory.PAPERDOLL_HAIR2));
// c6 new h's
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeInt(_player.getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_RHAND));
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeInt(_player.getInventory().getPaperdollAugmentationId(Inventory.PAPERDOLL_RHAND));
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeShort(0);
buffer.writeInt(_player.getPvpFlag());
buffer.writeInt(_player.getKarma());
buffer.writeInt(_mAtkSpd);
buffer.writeInt(_pAtkSpd);
buffer.writeInt(_player.getPvpFlag());
buffer.writeInt(_player.getKarma());
buffer.writeInt(_runSpd);
buffer.writeInt(_walkSpd);
buffer.writeInt(_swimRunSpd);
buffer.writeInt(_swimWalkSpd);
buffer.writeInt(_flyRunSpd);
buffer.writeInt(_flyWalkSpd);
buffer.writeInt(_flyRunSpd);
buffer.writeInt(_flyWalkSpd);
buffer.writeDouble(_moveMultiplier);
buffer.writeDouble(_player.getAttackSpeedMultiplier());
buffer.writeDouble(_player.getCollisionRadius());
buffer.writeDouble(_player.getCollisionHeight());
buffer.writeInt(appearance.getHairStyle());
buffer.writeInt(appearance.getHairColor());
buffer.writeInt(appearance.getFace());
buffer.writeString(_gmSeeInvis ? "Invisible" : appearance.getVisibleTitle());
if (!_player.isCursedWeaponEquipped())
{
buffer.writeInt(_player.getClanId());
buffer.writeInt(_player.getClanCrestId());
buffer.writeInt(_player.getAllyId());
buffer.writeInt(_player.getAllyCrestId());
}
else
{
buffer.writeInt(0);
buffer.writeInt(0);
buffer.writeInt(0);
buffer.writeInt(0);
}
// In UserInfo leader rights and siege flags, but here found nothing??
// Therefore RelationChanged packet with that info is required
buffer.writeInt(0);
buffer.writeByte(!_player.isSitting()); // standing = 1 sitting = 0
buffer.writeByte(_player.isRunning()); // running = 1 walking = 0
buffer.writeByte(_player.isInCombat());
buffer.writeByte(!_player.isInOlympiadMode() && _player.isAlikeDead());
buffer.writeByte(!_gmSeeInvis && _player.isInvisible()); // invisible = 1 visible =0
buffer.writeByte(_player.getMountType().ordinal()); // 1-on Strider, 2-on Wyvern, 3-on Great Wolf, 0-no mount
buffer.writeByte(_player.getPrivateStoreType().getId());

buffer.writeShort(_player.getCubics().size());
for (int cubicId : _player.getCubics().keySet())
{
buffer.writeShort(cubicId);
}

buffer.writeByte(_player.isInPartyMatchRoom());
buffer.writeInt(_gmSeeInvis ? (_player.getAbnormalVisualEffects() | AbnormalVisualEffect.STEALTH.getMask()) : _player.getAbnormalVisualEffects());
buffer.writeByte(_player.getRecomLeft());
buffer.writeShort(_player.getRecomHave()); // Blue value for name (0 = white, 255 = pure blue)
buffer.writeInt(_player.getClassId().getId());
buffer.writeInt(_player.getMaxCp());
buffer.writeInt((int) _player.getCurrentCp());
buffer.writeByte(_player.isMounted() ? 0 : _player.getEnchantEffect());
buffer.writeByte(_player.getTeam().getId());
buffer.writeInt(_player.getClanCrestLargeId());
buffer.writeByte(_player.isNoble()); // Symbol on char menu ctrl+I
buffer.writeByte(_player.isHero() || (_player.isGM() && Config.GM_HERO_AURA)); // Hero Aura

buffer.writeByte(_player.isFishing()); // 1: Fishing Mode (Cannot be undone by setting back to 0)
buffer.writeInt(_player.getFishX());
buffer.writeInt(_player.getFishY());
buffer.writeInt(_player.getFishZ());

buffer.writeInt(appearance.getNameColor());
buffer.writeInt(_heading);
buffer.writeInt(_player.getPledgeClass());
buffer.writeInt(_player.getPledgeType());
buffer.writeInt(appearance.getTitleColor());
buffer.writeInt(_player.isCursedWeaponEquipped() ? CursedWeaponsManager.getInstance().getLevel(_player.getCursedWeaponEquippedId()) : 0);
}
}


We are going to create this new file in the following path.
Route : java\org\l2jmobius\gameserver\network\serverpackets\NpcInfoPoly.java
Code: [Select]
/*
 * Copyright (c) 2013 L2jMobius
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package org.l2jmobius.gameserver.network.serverpackets;

import org.l2jmobius.gameserver.data.xml.NpcData;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.actor.templates.NpcTemplate;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.ServerPackets;
import org.l2jmobius.commons.network.WritableBuffer;

/**
 * Packet for sending a Player polymorphed as an NPC
 */
public class NpcInfoPoly extends AbstractNpcInfo
{
private final Player _player;
private final int _objectId;
private final int _displayId;

public NpcInfoPoly(Player player)
{
super(player, false);
_player = player;
_objectId = player.getObjectId();
_displayId = player.getPolyId();

NpcTemplate template = NpcData.getInstance().getTemplate(_displayId);
if (template != null)
{
_collisionHeight = template.getFCollisionHeight();
_collisionRadius = template.getFCollisionRadius();
}
else
{
_collisionHeight = 25; // fallback safe values
_collisionRadius = 5;
}

_rhand = 0;
_lhand = 0;
_chest = 0;
_enchantEffect = 0;
_isAttackable = false;
_name = player.getName();
_title = player.getTitle();
}

[member=79]override[/member]
public void writeImpl(GameClient client, WritableBuffer buffer)
{
ServerPackets.NPC_INFO.writeId(this, buffer);
buffer.writeInt(_objectId);
buffer.writeInt(_displayId + 1000000); // npc polymorph type id
buffer.writeInt(0); // attackable 0
buffer.writeInt(_x);
buffer.writeInt(_y);
buffer.writeInt(_z);
buffer.writeInt(_heading);
buffer.writeInt(0);
buffer.writeInt(_mAtkSpd);
buffer.writeInt(_pAtkSpd);
buffer.writeInt(_runSpd);
buffer.writeInt(_walkSpd);
buffer.writeInt(_swimRunSpd);
buffer.writeInt(_swimWalkSpd);
buffer.writeInt(_flyRunSpd);
buffer.writeInt(_flyWalkSpd);
buffer.writeInt(_flyRunSpd);
buffer.writeInt(_flyWalkSpd);
buffer.writeDouble(_moveMultiplier);
buffer.writeDouble(_player.getAttackSpeedMultiplier());
buffer.writeDouble(_collisionRadius);
buffer.writeDouble(_collisionHeight);
buffer.writeInt(_rhand);
buffer.writeInt(_chest);
buffer.writeInt(_lhand);
buffer.writeByte(1); // name above char
buffer.writeByte(_player.isRunning() ? 1 : 0);
buffer.writeByte(_player.isInCombat() ? 1 : 0);
buffer.writeByte(_player.isAlikeDead() ? 1 : 0);
buffer.writeByte(0); // summoned invisible 2, normal 0
buffer.writeString(_name);
buffer.writeString(_title);
buffer.writeInt(0); // Title color
buffer.writeInt(_player.getPvpFlag());
buffer.writeInt(_player.getKarma());
buffer.writeInt(_player.getAbnormalVisualEffects());
buffer.writeInt(0); // clan id
buffer.writeInt(0); // clan crest id
buffer.writeInt(0); // ally id
buffer.writeInt(0); // ally crest id
buffer.writeByte(_player.isInsideZone(ZoneId.WATER) ? 1 : _player.isFlying() ? 2 : 0);
buffer.writeByte(_player.getTeam().getId());
buffer.writeDouble(_collisionRadius);
buffer.writeDouble(_collisionHeight);
buffer.writeInt(_enchantEffect);
buffer.writeInt(_player.isFlying());
}
}

We continue with the creation of the following file.We must create a new folder called poly and inside it will be located ObjetPoly
java\org\l2jmobius\gameserver\model\actor\poly\ObjectPoly.java
Code: [Select]
/*
 * This file is part of the l2jmobius project.
 *
 * This program 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.
 *
 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.l2jmobius.gameserver.model.actor.poly;

import org.l2jmobius.gameserver.model.WorldObject;

public class ObjectPoly
{
private final WorldObject _activeObject;
private int _polyId;
private String _polyType;

public ObjectPoly(WorldObject activeObject)
{
_activeObject = activeObject;
}

public void setPolyInfo(String polyType, String polyId)
{
setPolyId(Integer.parseInt(polyId));
setPolyType(polyType);
}

public WorldObject getActiveObject()
{
return _activeObject;
}

public boolean isMorphed()
{
return _polyType != null;
}

public boolean isPolymorphed()
{
    return isMorphed();
}

public int getPolyId()
{
return _polyId;
}

public void setPolyId(int value)
{
_polyId = value;
}

public String getPolyType()
{
return _polyType;
}

public void setPolyType(String value)
{
_polyType = value;
}

public void resetPolyInfo()
{
    _polyType = null;
    _polyId = 0;
}
}

Now we need to update our Player.Java by adding the following.
Code: [Select]
// client radar
// TODO: This needs to be better integrated and saved/loaded
private final Radar _radar;

// polymorph
private final ObjectPoly _poly = new ObjectPoly(this);
also add in the same player.java
Code: [Select]
public ContactList getContactList()
{
return _contactList;
}

public ObjectPoly getPoly()  // polymorph test
{
    return _poly;
}

public boolean isPolymorphed()  // polymorph test
{
    return _poly.isPolymorphed();
}

public String getPolyType()   // polymorph test
{
    return _poly.getPolyType();
}

public int getPolyId()
{
    return _poly.getPolyId(); // polymorph test
}

finally in WorldObjet.java
add.
Code: [Select]
import org.l2jmobius.gameserver.network.serverpackets.ServerPacket;
import org.l2jmobius.gameserver.model.actor.poly.ObjectPoly;
Code: [Select]
private Map<String, Object> _scripts;
private final ObjectPoly _poly = new ObjectPoly(this);
Code: [Select]
[member=79]override[/member]
public String getName()
{
return _name;
}

public ObjectPoly getPoly()
{
return _poly;
}

Here I leave the code in a mediafire link : https://www.mediafire.com/file/uw9v6zt11uunxie/22._Polymorph.rar/file