package admincommands;
import com.aionemu.gameserver.controllers.attack.AggroInfo;
import com.aionemu.gameserver.dataholders.DataManager;
import com.aionemu.gameserver.model.Race;
import com.aionemu.gameserver.model.SkillElement;
import com.aionemu.gameserver.model.gameobjects.Creature;
import com.aionemu.gameserver.model.gameobjects.Npc;
import com.aionemu.gameserver.model.gameobjects.Pet;
import com.aionemu.gameserver.model.gameobjects.VisibleObject;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.player.npcFaction.ENpcFactionQuestState;
import com.aionemu.gameserver.model.gameobjects.player.npcFaction.NpcFaction;
import com.aionemu.gameserver.model.gameobjects.siege.SiegeNpc;
import com.aionemu.gameserver.model.siege.FortressLocation;
import com.aionemu.gameserver.model.stats.container.PlayerGameStats;
import com.aionemu.gameserver.model.stats.container.StatEnum;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.restrictions.PlayerRestrictions;
import com.aionemu.gameserver.services.SiegeService;
import com.aionemu.gameserver.services.TownService;
import com.aionemu.gameserver.spawnengine.ClusteredNpc;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.PositionUtil;
import com.aionemu.gameserver.utils.chathandlers.AdminCommand;
import com.aionemu.gameserver.utils.stats.CalculationType;
import com.aionemu.gameserver.utils.stats.StatFunctions;
/**
* @author Nemiroff, Neon
*/
public class Info extends AdminCommand {
public Info() {
super("info", "Shows information about your target.");
}
@Override
public void execute(Player admin, String... params) {
VisibleObject target = admin.getTarget();
if (target == null) {
PacketSendUtility.sendPacket(admin, SM_SYSTEM_MESSAGE.STR_INVALID_TARGET());
return;
}
sendInfo(admin, "[Info about " + target.getClass().getSimpleName() + "]\n\tName: " + target.getName() + ", ObjectId: " + target.getObjectId()
+ "\n\tTemplateId: " + target.getObjectTemplate().getTemplateId());
if (target instanceof Creature creature) {
if (creature instanceof Player player) {
Pet pet = player.getPet();
sendInfo(admin, (pet != null ? "Pet Id: " + pet.getObjectTemplate().getTemplateId() + ", ObjectId: " + pet.getObjectId() + "\n\t" : "")
+ "Town ID: " + TownService.getInstance().getTownResidence(player));
sendInfo(admin, "Current Panesterra Faction: %s".formatted(player.getPanesterraFaction()));
PlayerGameStats pgs = player.getGameStats();
sendInfo(admin,
"[Stats]"
+ "\n\tHP: " + player.getLifeStats().getCurrentHp() + "/" + pgs.getMaxHp().getCurrent()
+ ", MP: " + player.getLifeStats().getCurrentMp() + "/" + pgs.getMaxMp().getCurrent()
+ ", FP: " + player.getLifeStats().getCurrentFp() + "/" + pgs.getFlyTime().getCurrent()
+ ", DP: " + player.getCommonData().getDp() + "/" + pgs.getMaxDp().getCurrent()
+ "\n\tPower: " + pgs.getPower().getCurrent()
+ ", Health: " + pgs.getHealth().getCurrent()
+ ", Agility: " + pgs.getAgility().getCurrent()
+ ", Accuracy: " + pgs.getAccuracy().getCurrent()
+ ", Knowledge: " + pgs.getKnowledge().getCurrent()
+ ", Will: " + pgs.getWill().getCurrent()
+ "\n\tCast Time Boost: " + (pgs.getStat(StatEnum.BOOST_CASTING_TIME, 1000).getCurrent() * 0.1f - 100) + "%"
+ "\n\tBase Attack Speed " + pgs.getAttackSpeed().getBase() * 0.001f
+ "\n\tCurrent Attack Speed: " + pgs.getAttackSpeed().getCurrent() * 0.001f
+ "\n\tMovement Speed: " + pgs.getMovementSpeedFloat()
+ "\n\t-------------Offence-------------"
+ "\n\tMagic Boost: " + pgs.getMBoost().getCurrent()
+ "\n\tM. Accuracy: " + pgs.getMAccuracy().getCurrent()
+ "\n\tM. Critical: " + pgs.getMCritical().getCurrent()
+ "\n\t\t---------Main Hand-----------"
+ "\n\t\tM. Attack: " + (pgs.getMainHandMAttack(CalculationType.DISPLAY).getCurrent())
+ "\n\t\tP. Attack: " + pgs.getMainHandPAttack(CalculationType.DISPLAY).getCurrent()
+ "\n\t\tP. Accuracy: " + pgs.getMainHandPAccuracy().getCurrent()
+ "\n\t\tP. Critical: " + pgs.getMainHandPCritical().getCurrent()
+ "\n\t\t-----------Off Hand-----------"
+ "\n\t\tM. Attack displayed: " + (pgs.getOffHandMAttack(CalculationType.DISPLAY).getCurrent())
+ ", min: " + (int) (pgs.getOffHandMAttack().getCurrent() * pgs.getMinDamageRatio())
+ ", max: " + pgs.getOffHandMAttack().getCurrent()
+ "\n\t\tP. Attack displayed: " + (pgs.getOffHandPAttack(CalculationType.DISPLAY).getCurrent())
+ ", min: " + (int) (pgs.getOffHandPAttack().getCurrent() * pgs.getMinDamageRatio())
+ ", max: " + pgs.getOffHandPAttack().getCurrent()
+ "\n\t\tP. Accuracy: " + pgs.getOffHandPAccuracy().getCurrent()
+ "\n\t\tP. Critical: " + pgs.getOffHandPCritical().getCurrent()
+ "\n\t-------------Defence--------------"
+ "\n\t\tM. Defence: " + pgs.getMDef().getCurrent()
+ "\n\t\tMagic Resist: " + pgs.getMResist().getCurrent()
+ "\n\t\tCrit. Spell Resist: " + pgs.getMCR()
+ "\n\t\tCrit. Spell Fortitude: " + pgs.getStat(StatEnum.MAGICAL_CRITICAL_DAMAGE_REDUCE, 0).getCurrent()
+ "\n\t\tP. Defence: " + pgs.getPDef().getCurrent()
+ "\n\t\tBlock: " + pgs.getBlock().getCurrent()
+ "\n\t\tParry: " + pgs.getParry().getCurrent()
+ "\n\t\tEvasion: " + pgs.getEvasion().getCurrent()
+ "\n\t\tCrit. Strike Resist: " + pgs.getPCR().getCurrent()
+ "\n\t\tCrit. Strike Fortitude: " + pgs.getStat(StatEnum.PHYSICAL_CRITICAL_DAMAGE_REDUCE, 0).getCurrent()
+ "\n\t\tWind Resist: " + pgs.getMagicalDefenseFor(SkillElement.WIND)
+ "\n\t\tWater Resist: " + pgs.getMagicalDefenseFor(SkillElement.WATER)
+ "\n\t\tEarth Resist: " + pgs.getMagicalDefenseFor(SkillElement.EARTH)
+ "\n\t\tFire Resist: " + pgs.getMagicalDefenseFor(SkillElement.FIRE)
+ "\n\t\tDark Resist: " + pgs.getMagicalDefenseFor(SkillElement.DARK)
+ "\n\t\tLight Resist: " + pgs.getMagicalDefenseFor(SkillElement.LIGHT)
+ "\n\t-------------PvP Stats-------------"
+ "\n\tPvP attack: " + pgs.getStat(StatEnum.PVP_ATTACK_RATIO, 0).getCurrent() * 0.1f + "%"
+ "\n\tPvP p. attack: " + pgs.getStat(StatEnum.PVP_ATTACK_RATIO_PHYSICAL, 0).getCurrent() * 0.1f + "%"
+ "\n\tPvP m. attack: " + pgs.getStat(StatEnum.PVP_ATTACK_RATIO_MAGICAL, 0).getCurrent() * 0.1f + "%"
+ "\n\tPvP defend: " + pgs.getStat(StatEnum.PVP_DEFEND_RATIO, 0).getCurrent() * 0.1f + "%"
+ "\n\tPvP p. defend: " + pgs.getStat(StatEnum.PVP_DEFEND_RATIO_PHYSICAL, 0).getCurrent() * 0.1f + "%"
+ "\n\tPvP m. defend: " + pgs.getStat(StatEnum.PVP_DEFEND_RATIO_MAGICAL, 0).getCurrent() * 0.1f + "%");
for (int i = 0; i < 2; i++) {
NpcFaction faction = player.getNpcFactions().getActiveNpcFaction(i == 0);
if (faction != null) {
sendInfo(admin,
player.getName() + " have join to " + (i == 0 ? "mentor" : "daily") + " faction: " + DataManager.NPC_FACTIONS_DATA.getNpcFactionById(faction.getId()).getName()
+ "\n\tCurrent quest state: " + faction.getState().name()
+ (faction.getState().equals(ENpcFactionQuestState.COMPLETE) ? ("\n\tNext after: " + ((faction.getTime() - System.currentTimeMillis() / 1000) / 3600f) + " h.") : ""));
}
}
} else if (creature instanceof Npc npc) {
sendInfo(admin, "[Template info]\n\tRating: " + npc.getRating() + ", Rank: " + npc.getRank()
+ "\n\tTemplateType: " + npc.getNpcTemplateType() + ", AbyssType: " + npc.getAbyssNpcType()
+ "\n\tRelative XP reward: " + StatFunctions.calculateExperienceReward(admin.getLevel(), npc));
if (npc instanceof SiegeNpc)
sendInfo(admin, "[Siege info]\n\tSiegeId: " + ((SiegeNpc) npc).getSiegeId() + ", SiegeRace: " + ((SiegeNpc) npc).getSiegeRace());
sendInfo(admin,
"[AI info]\n\tAI: " + npc.getAi().getName()
+ "\n\tState: " + npc.getAi().getState() + ", SubState: " + npc.getAi().getSubState());
sendInfo(admin,
"[Sense range]\n\tRadius: " + npc.getAggroRange()
+ "\n\tShort-Radius: " + npc.getShortAggroRange()
+ "\n\tAngle: " + npc.getAggroAngle()
+ "\n\tSide: " + npc.getObjectTemplate().getBoundRadius().getSide() + ", Front: " + npc.getObjectTemplate().getBoundRadius().getFront() + ", Upper: " + npc.getObjectTemplate().getBoundRadius().getUpper()
+ "\n\tDirectional bound: " + PositionUtil.getDirectionalBound(npc, admin, true)
+ "\n\tDistance: " + (npc.getAggroRange() + PositionUtil.getDirectionalBound(npc, admin, true)));
sendInfo(admin, "[Spawn info]\n\tStaticId: " + npc.getSpawn().getStaticId() + ", DistToSpawn: " + npc.getDistanceToSpawnLocation() + "m");
if (npc.isPathWalker()) {
sendInfo(admin, "\tRouteId: " + npc.getSpawn().getWalkerId());
if (npc.getWalkerGroup() != null) {
ClusteredNpc snpc = npc.getWalkerGroup().getClusterData(npc);
sendInfo(admin, "\tWalkerGroupType: " + npc.getWalkerGroup().getWalkType() + ", XDelta: " + snpc.getXDelta() + ", YDelta: "
+ snpc.getYDelta() + ", Index: " + snpc.getWalkerIndex());
}
} else if (npc.isRandomWalker()) {
sendInfo(admin, "\tRandomWalkRange: " + npc.getSpawn().getRandomWalkRange() + "m");
}
}
sendInfo(admin, createZoneInfo(creature));
sendInfo(admin, "[Tribe]\n\tRace: " + creature.getRace() + ", Tribe: " + creature.getTribe() + ", TribeBase: " + creature.getBaseTribe());
sendInfo(admin, "[Your relation]\n\tisEnemy: " + admin.isEnemy(creature) + ", canAttack: " + PlayerRestrictions.canAttack(admin, target));
sendInfo(admin, "[Targets relation]\n\tisEnemy: " + creature.isEnemy(admin)
+ (creature instanceof Npc ? ", Hostility: " + ((Npc) creature).getType(admin) : ""));
sendInfo(admin, "[Life stats]\n\tHP: " + creature.getLifeStats().getCurrentHp() + " / " + creature.getLifeStats().getMaxHp()
+ "\n\tMP: " + creature.getLifeStats().getCurrentMp() + " / " + creature.getLifeStats().getMaxMp());
sendInfo(admin, createAggroInfo(creature));
} else if (target.getSpawn() != null && target.getSpawn().getStaticId() != 0) {
sendInfo(admin, "\tStaticId: " + target.getSpawn().getStaticId());
}
}
private String createZoneInfo(Creature creature) {
FortressLocation fortress = SiegeService.getInstance().findFortress(creature.getWorldId(), creature.getX(), creature.getY(), creature.getZ());
int townId = TownService.getInstance().getTownIdByPosition(creature);
StringBuilder sb = new StringBuilder("[Current zone]");
sb.append("\n\t" + creature.getPosition().toCoordString());
sb.append("\n\tFortress Location ID: " + (fortress == null ? "-" : fortress.getLocationId()));
sb.append("\n\tTown ID: " + (townId == 0 ? "-" : townId));
sb.append("\n\tPvP: " + creature.isInsidePvPZone());
return sb.toString();
}
private String createAggroInfo(Creature creature) {
StringBuilder sb = new StringBuilder("[AggroList]");
int aDmg = 0, eDmg = 0, tDmg = creature.getAggroList().getTotalDamage();
for (AggroInfo ai : creature.getAggroList().getList()) {
String name = ai.getAttacker().getName();
if (ai.getAttacker() instanceof Creature attacker) {
Creature master = attacker.getMaster();
if (master.getRace() == Race.ASMODIANS)
aDmg += ai.getDamage();
else if (master.getRace() == Race.ELYOS)
eDmg += ai.getDamage();
if (!master.equals(ai.getAttacker()))
name = master.getName() + "'s " + attacker.getObjectTemplate().getL10n();
}
sb.append("\n\tName: " + name + ", Dmg: " + ai.getDamage() + ", Hate: " + ai.getHate());
}
if (tDmg > 0) {
sb.append("\n\tTotal Dmg: ").append(tDmg);
sb.append("\n\t\t(A) Dmg: ").append(aDmg);
sb.append("\n\t\t(E) Dmg: ").append(eDmg);
sb.append("\n\t\t(N) Dmg: ").append(tDmg - aDmg - eDmg);
}
return sb.toString();
}
}