• SiteAnalyzer, технический и SEO-анализ сайтов

yGuard

  • Автор темы Автор темы Dev4ik
  • Дата начала Дата начала
need make update knownlist.
resource_icon.png

AionServer-4.7.5.X (Aion Core rev.7420; By GiGatR00n
I use this
I can't send an update list
 
PvpService és a Player Controller

Sorry, I can't find the error:

PvpService.java

package com.aionemu.gameserver.services;

import java.util.ArrayList;
import java.util.List;

import javolution.util.FastMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aionemu.commons.utils.Rnd;
import com.aionemu.gameserver.configs.main.CustomConfig;
import com.aionemu.gameserver.configs.main.EventSystem;
import com.aionemu.gameserver.configs.main.GroupConfig;
import com.aionemu.gameserver.configs.main.LoggingConfig;
import com.aionemu.gameserver.configs.main.PunishmentConfig;
import com.aionemu.gameserver.controllers.attack.AggroInfo;
import com.aionemu.gameserver.controllers.attack.KillList;
import com.aionemu.gameserver.eventEngine.crazy_daeva.CrazyDaevaService;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.player.RewardType;
import com.aionemu.gameserver.model.ingameshop.InGameShopEn;
import com.aionemu.gameserver.model.team2.alliance.PlayerAlliance;
import com.aionemu.gameserver.model.team2.group.PlayerGroup;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.questEngine.QuestEngine;
import com.aionemu.gameserver.questEngine.model.QuestEnv;
import com.aionemu.gameserver.services.abyss.AbyssPointsService;
import com.aionemu.gameserver.services.item.ItemService;
import com.aionemu.gameserver.utils.MathUtil;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.audit.AuditLogger;
import com.aionemu.gameserver.utils.stats.AbyssRankEnum;
import com.aionemu.gameserver.utils.stats.StatFunctions;

/**
* @author Sarynth
*/
public class PvpService {

private static Logger log = LoggerFactory.getLogger("KILL_LOG");

public static final PvpService getInstance() {
return SingletonHolder.instance;
}

private FastMap<Integer, KillList> pvpKillLists;

private PvpService() {
pvpKillLists = new FastMap<Integer, KillList>();
}

/**
* @param winnerId
* @param victimId
* @return
*/
private int getKillsFor(int winnerId, int victimId) {
KillList winnerKillList = pvpKillLists.get(winnerId);

if (winnerKillList == null) {
return 0;
}
return winnerKillList.getKillsFor(victimId);
}

/**
* @param winnerId
* @param victimId
*/
private void addKillFor(int winnerId, int victimId) {
KillList winnerKillList = pvpKillLists.get(winnerId);
if (winnerKillList == null) {
winnerKillList = new KillList();
pvpKillLists.put(winnerId, winnerKillList);
}
winnerKillList.addKillFor(victimId);
}

/**
* @param victim
*/
public void doReward(Player victim) {
// winner is the player that receives the kill count
final Player winner = victim.getAggroList().getMostPlayerDamage();

int totalDamage = victim.getAggroList().getTotalDamage();

if (totalDamage == 0 || winner == null || winner.getRace() == victim.getRace()) {
return;
}

if (victim.getBattleGround() != null) {
return;
}

// Add Player Kill to record.
if (this.getKillsFor(winner.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
winner.getAbyssRank().setAllKill();
int kills = winner.getAbyssRank().getAllKill();
// Pvp Kill Reward.
if (CustomConfig.ENABLE_KILL_REWARD) {
if (kills % CustomConfig.KILLS_NEEDED1 == 1) {
ItemService.addItem(winner, CustomConfig.REWARD1, 1);
PacketSendUtility.sendMessage(winner, "Congratulations, you have won " + "[item: " + CustomConfig.REWARD1
+ "] for having killed " + CustomConfig.KILLS_NEEDED1 + " players !");
log.info("[REWARD] Player [" + winner.getName() + "] win 2 [" + CustomConfig.REWARD1 + "]");
}
if (kills % CustomConfig.KILLS_NEEDED2 == 3) {
ItemService.addItem(winner, CustomConfig.REWARD2, 1);
PacketSendUtility.sendMessage(winner, "Congratulations, you have won " + "[item: " + CustomConfig.REWARD2
+ "] for having killed " + CustomConfig.KILLS_NEEDED2 + " players !");
log.info("[REWARD] Player [" + winner.getName() + "] win 4 [" + CustomConfig.REWARD2 + "]");
}
if (kills % CustomConfig.KILLS_NEEDED3 == 5) {
ItemService.addItem(winner, CustomConfig.REWARD3, 1);
PacketSendUtility.sendMessage(winner, "Congratulations, you have won " + "[item: " + CustomConfig.REWARD3
+ "] for having killed " + CustomConfig.KILLS_NEEDED3 + " players !");
log.info("[REWARD] Player [" + winner.getName() + "] win 6 [" + CustomConfig.REWARD3 + "]");
}
}
// PvP Toll Reward
if (CustomConfig.ENABLE_TOLL_REWARD) {
if (Rnd.get(0, 100) > CustomConfig.TOLL_CHANCE){
InGameShopEn.getInstance().addToll(winner, CustomConfig.TOLL_QUANTITY);
PacketSendUtility.sendMessage(winner, "You've recived " + CustomConfig.TOLL_QUANTITY + " tolls from PvP!");
}
}
}

//Crazy kill
if (EventSystem.ENABLE_CRAZY) {
if (winner.getRndCrazy() >= EventSystem.CRAZY_LOWEST_RND) {
AbyssPointsService.addAp(winner, 500);
AbyssPointsService.addGp(winner, 20);
}
}

// Announce that player has died.
PacketSendUtility.broadcastPacketAndReceive(victim, SM_SYSTEM_MESSAGE.STR_MSG_COMBAT_FRIENDLY_DEATH_TO_B(victim.getName(), winner.getName()));

// Pvp Kill Reward.
int reduceap = PunishmentConfig.PUNISHMENT_REDUCEAP;
if (reduceap < 0) {
reduceap *= -1;
}
if (reduceap > 100) {
reduceap = 100;
}

//Kill-log
if (LoggingConfig.LOG_KILL) {
log.info("[KILL] Player [" + winner.getName() + "] killed [" + victim.getName() + "]");
}

if ((LoggingConfig.LOG_PL) || (reduceap > 0)) {
String ip1 = winner.getClientConnection().getIP();
String mac1 = winner.getClientConnection().getMacAddress();
String ip2 = victim.getClientConnection().getIP();
String mac2 = victim.getClientConnection().getMacAddress();
if ((mac1 != null) && (mac2 != null)) {
if ((ip1.equalsIgnoreCase(ip2)) && (mac1.equalsIgnoreCase(mac2))) {
AuditLogger.info(winner, "Power Leveling : " + winner.getName() + " with " + victim.getName() + ", They have the sames ip=" + ip1 + " and mac=" + mac1 + ".");
if (reduceap > 0) {
int win_ap = winner.getAbyssRank().getAp() * reduceap / 100;
int vic_ap = victim.getAbyssRank().getAp() * reduceap / 100;
AbyssPointsService.addAp(winner, -win_ap);
AbyssPointsService.addAp(victim, -vic_ap);
PacketSendUtility.sendMessage(winner, "[PL-AP] You lost " + reduceap + "% of your total ap");
PacketSendUtility.sendMessage(victim, "[PL-AP] You lost " + reduceap + "% of your total ap");
}
return;
}
if (ip1.equalsIgnoreCase(ip2)) {
AuditLogger.info(winner, "Possible Power Leveling : " + winner.getName() + " with " + victim.getName() + ", They have the sames ip=" + ip1 + ".");
AuditLogger.info(winner, "Check if " + winner.getName() + " and " + victim.getName() + " are Brothers-Sisters-Lovers-dogs-cats...");
}
}
}

// Keep track of how much damage was dealt by players
// so we can remove AP based on player damage...
int playerDamage = 0;
boolean success;

// Distribute AP to groups and players that had damage.
for (AggroInfo aggro : victim.getAggroList().getFinalDamageList(true)) {
success = false;
if (aggro.getAttacker() instanceof Player) {
success = rewardPlayer(victim, totalDamage, aggro);
} else if (aggro.getAttacker() instanceof PlayerGroup) {
success = rewardPlayerGroup(victim, totalDamage, aggro);
} else if (aggro.getAttacker() instanceof PlayerAlliance) {
success = rewardPlayerAlliance(victim, totalDamage, aggro);
}

// Add damage last, so we don't include damage from same race. (Duels, Arena)
if (success) {
playerDamage += aggro.getDamage();
}
}

SerialKillerService.getInstance().updateRank(winner, victim);

//notify Quest engine for winner + his group
notifyKillQuests(winner, victim);

// Apply lost AP to defeated player
final int apLost = StatFunctions.calculatePvPApLost(victim, winner);
final int apActuallyLost = (int) (apLost * playerDamage / totalDamage);

if (apActuallyLost > 0) {
AbyssPointsService.addAp(victim, -apActuallyLost);
}
}

/**
* @param victim
* @param totalDamage
* @param aggro
* @return true if group is not same race
*/
private boolean rewardPlayerGroup(Player victim, int totalDamage, AggroInfo aggro) {
// Reward Group
PlayerGroup group = ((PlayerGroup) aggro.getAttacker());

// Don't Reward Player of Same Faction.
if (group.getRace() == victim.getRace()) {
return false;
}

// Find group members in range
List<Player> players = new ArrayList<Player>();

// Find highest rank and level in local group
int maxRank = AbyssRankEnum.GRADE9_SOLDIER.getId();
int maxLevel = 0;

for (Player member : group.getMembers()) {
if (MathUtil.isIn3dRange(member, victim, GroupConfig.GROUP_MAX_DISTANCE)) {
// Don't distribute AP to a dead player!
if (!member.getLifeStats().isAlreadyDead()) {
players.add(member);
if (member.getLevel() > maxLevel) {
maxLevel = member.getLevel();
}
if (member.getAbyssRank().getRank().getId() > maxRank) {
maxRank = member.getAbyssRank().getRank().getId();
}
}
}
}

// They are all dead or out of range.
if (players.isEmpty()) {
return false;
}

int baseApReward = StatFunctions.calculatePvpApGained(victim, maxRank, maxLevel);
int baseXpReward = StatFunctions.calculatePvpXpGained(victim, maxRank, maxLevel);
int baseDpReward = StatFunctions.calculatePvpDpGained(victim, maxRank, maxLevel);
float groupPercentage = (float) aggro.getDamage() / totalDamage;
int apRewardPerMember = Math.round(baseApReward * groupPercentage / players.size());
int xpRewardPerMember = Math.round(baseXpReward * groupPercentage / players.size());
int dpRewardPerMember = Math.round(baseDpReward * groupPercentage / players.size());

for (Player member : players) {
int memberApGain = 1;
int memberXpGain = 1;
int memberDpGain = 1;
if (this.getKillsFor(member.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
if (apRewardPerMember > 0) {
memberApGain = Math.round(RewardType.AP_PLAYER.calcReward(member, apRewardPerMember));
}
if (xpRewardPerMember > 0) {
memberXpGain = Math.round(xpRewardPerMember * member.getRates().getXpPlayerGainRate());
}
if (dpRewardPerMember > 0) {
memberDpGain = Math.round(StatFunctions.adjustPvpDpGained(dpRewardPerMember, victim.getLevel(), member.getLevel()) * member.getRates().getDpPlayerRate());
}

}
Player partner = member.findPartner();
if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
AbyssPointsService.addAp(member, victim, memberApGain + (memberApGain * 20 / 100)); //20% more AP for weddings
} else {
AbyssPointsService.addAp(member, victim, memberApGain);
}
member.getCommonData().addExp(memberXpGain, RewardType.PVP_KILL, victim.getName());
member.getCommonData().addEventExp(memberXpGain);
member.getCommonData().addDp(memberDpGain);
this.addKillFor(member.getObjectId(), victim.getObjectId());
}

return true;
}

/**
* @param victim
* @param totalDamage
* @param aggro
* @return true if group is not same race
*/
private boolean rewardPlayerAlliance(Player victim, int totalDamage, AggroInfo aggro) {
// Reward Alliance
PlayerAlliance alliance = ((PlayerAlliance) aggro.getAttacker());

// Don't Reward Player of Same Faction.
if (alliance.getLeaderObject().getRace() == victim.getRace()) {
return false;
}

// Find group members in range
List<Player> players = new ArrayList<Player>();

// Find highest rank and level in local group
int maxRank = AbyssRankEnum.GRADE9_SOLDIER.getId();
int maxLevel = 0;

for (Player member : alliance.getMembers()) {
if (!member.isOnline()) {
continue;
}
if (MathUtil.isIn3dRange(member, victim, GroupConfig.GROUP_MAX_DISTANCE)) {
// Don't distribute AP to a dead player!
if (!member.getLifeStats().isAlreadyDead()) {
players.add(member);
if (member.getLevel() > maxLevel) {
maxLevel = member.getLevel();
}
if (member.getAbyssRank().getRank().getId() > maxRank) {
maxRank = member.getAbyssRank().getRank().getId();
}
}
}
}

// They are all dead or out of range.
if (players.isEmpty()) {
return false;
}

int baseApReward = StatFunctions.calculatePvpApGained(victim, maxRank, maxLevel);
int baseXpReward = StatFunctions.calculatePvpXpGained(victim, maxRank, maxLevel);
int baseDpReward = StatFunctions.calculatePvpDpGained(victim, maxRank, maxLevel);
float groupPercentage = (float) aggro.getDamage() / totalDamage;
int apRewardPerMember = Math.round(baseApReward * groupPercentage / players.size());
int xpRewardPerMember = Math.round(baseXpReward * groupPercentage / players.size());
int dpRewardPerMember = Math.round(baseDpReward * groupPercentage / players.size());

for (Player member : players) {
int memberApGain = 1;
int memberXpGain = 1;
int memberDpGain = 1;
if (this.getKillsFor(member.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
if (apRewardPerMember > 0) {
memberApGain = Math.round(RewardType.AP_PLAYER.calcReward(member, apRewardPerMember));
}
if (xpRewardPerMember > 0) {
memberXpGain = Math.round(xpRewardPerMember * member.getRates().getXpPlayerGainRate());
}
if (dpRewardPerMember > 0) {
memberDpGain = Math.round(StatFunctions.adjustPvpDpGained(dpRewardPerMember, victim.getLevel(), member.getLevel()) * member.getRates().getDpPlayerRate());
}
}
AbyssPointsService.addAp(member, victim, memberApGain);
member.getCommonData().addExp(memberXpGain, RewardType.PVP_KILL, victim.getName());
member.getCommonData().addEventExp(memberXpGain);
member.getCommonData().addDp(memberDpGain);

this.addKillFor(member.getObjectId(), victim.getObjectId());
}

return true;
}

/**
* @param victim
* @param totalDamage
* @param aggro
* @return true if player is not same race
*/
private boolean rewardPlayer(Player victim, int totalDamage, AggroInfo aggro) {
// Reward Player
Player winner = ((Player) aggro.getAttacker());

// Don't Reward Player out of range/dead/same faction
if (winner.getRace() == victim.getRace() || !MathUtil.isIn3dRange(winner, victim, GroupConfig.GROUP_MAX_DISTANCE) || winner.getLifeStats().isAlreadyDead()) {
return false;
}

int baseApReward = 1;
int baseXpReward = 1;
int baseDpReward = 1;

if (this.getKillsFor(winner.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
baseApReward = StatFunctions.calculatePvpApGained(victim, winner.getAbyssRank().getRank().getId(), winner.getLevel());
baseXpReward = StatFunctions.calculatePvpXpGained(victim, winner.getAbyssRank().getRank().getId(), winner.getLevel());
baseDpReward = StatFunctions.calculatePvpDpGained(victim, winner.getAbyssRank().getRank().getId(), winner.getLevel());
if (EventSystem.ENABLE_CRAZY) {
if (winner.getRace() != victim.getRace()) {
CrazyDaevaService.getInstance().increaseRawKillCount(winner);
}
}
}

int apPlayerReward = Math.round(baseApReward * aggro.getDamage() / totalDamage);
apPlayerReward = (int) RewardType.AP_PLAYER.calcReward(winner, apPlayerReward);
int xpPlayerReward = Math.round(baseXpReward * winner.getRates().getXpPlayerGainRate() * aggro.getDamage() / totalDamage);
int dpPlayerReward = Math.round(baseDpReward * winner.getRates().getDpPlayerRate() * aggro.getDamage() / totalDamage);

AbyssPointsService.addAp(winner, victim, apPlayerReward);
winner.getCommonData().addExp(xpPlayerReward, RewardType.PVP_KILL, victim.getName());
winner.getCommonData().addEventExp(xpPlayerReward);
winner.getCommonData().addDp(dpPlayerReward);
this.addKillFor(winner.getObjectId(), victim.getObjectId());
return true;
}

private void notifyKillQuests(Player winner, Player victim) {
if (winner.getRace() == victim.getRace()) {
return;
}

List<Player> rewarded = new ArrayList<Player>();
int worldId = victim.getWorldId();

if (winner.isInGroup2()) {
rewarded.addAll(winner.getPlayerGroup2().getOnlineMembers());
} else if (winner.isInAlliance2()) {
rewarded.addAll(winner.getPlayerAllianceGroup2().getOnlineMembers());
} else {
rewarded.add(winner);
}

for (Player p : rewarded) {
if (!MathUtil.isIn3dRange(p, victim, GroupConfig.GROUP_MAX_DISTANCE) || p.getLifeStats().isAlreadyDead()) {
continue;
}

QuestEngine.getInstance().onKillInWorld(new QuestEnv(victim, p, 0, 0), worldId);
QuestEngine.getInstance().onKillRanked(new QuestEnv(victim, p, 0, 0), victim.getAbyssRank().getRank());
}
rewarded.clear();
}

@SuppressWarnings("synthetic-access")
private static class SingletonHolder {

protected static final PvpService instance = new PvpService();
}
}

-------------------------------------------------------
PlayerController.java

package com.aionemu.gameserver.controllers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.Future;

import com.aionemu.gameserver.ai2.manager.LookManager;
import com.aionemu.gameserver.configs.main.EventSystem;
import com.aionemu.gameserver.configs.main.HTMLConfig;
import com.aionemu.gameserver.configs.main.MembershipConfig;
import com.aionemu.gameserver.configs.main.SecurityConfig;
import com.aionemu.gameserver.controllers.attack.AttackUtil;
import com.aionemu.gameserver.dataholders.DataManager;
import com.aionemu.gameserver.dataholders.PlayerInitialData;
import com.aionemu.gameserver.eventEngine.battleground.model.templates.BattleGroundTemplate;
import com.aionemu.gameserver.eventEngine.battleground.services.battleground.AssaultBattleGround;
import com.aionemu.gameserver.eventEngine.battleground.services.battleground.BattleGroundManager;
import com.aionemu.gameserver.eventEngine.battleground.services.battleground.CTFBattleGround;
import com.aionemu.gameserver.eventEngine.crazy_daeva.CrazyDaevaService;
import com.aionemu.gameserver.model.DescriptionId;
import com.aionemu.gameserver.model.EmotionType;
import com.aionemu.gameserver.model.Race;
import com.aionemu.gameserver.model.TaskId;
import com.aionemu.gameserver.model.actions.PlayerMode;
import com.aionemu.gameserver.model.gameobjects.Kisk;
import com.aionemu.gameserver.model.gameobjects.Npc;
import com.aionemu.gameserver.model.gameobjects.Summon;
import com.aionemu.gameserver.model.gameobjects.VisibleObject;
import com.aionemu.gameserver.model.gameobjects.Item;
import com.aionemu.gameserver.model.gameobjects.Creature;
import com.aionemu.gameserver.model.gameobjects.Pet;
import com.aionemu.gameserver.model.gameobjects.Gatherable;
import com.aionemu.gameserver.model.gameobjects.StaticObject;
import com.aionemu.gameserver.model.gameobjects.player.AbyssRank;
import com.aionemu.gameserver.model.gameobjects.player.BindPointPosition;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.state.CreatureState;
import com.aionemu.gameserver.model.gameobjects.state.CreatureVisualState;
import com.aionemu.gameserver.model.house.House;
import com.aionemu.gameserver.model.skill.PlayerSkillEntry;
import com.aionemu.gameserver.model.stats.container.PlayerGameStats;
import com.aionemu.gameserver.model.summons.SummonMode;
import com.aionemu.gameserver.model.summons.UnsummonType;
import com.aionemu.gameserver.model.team2.group.PlayerFilters.ExcludePlayerFilter;
import com.aionemu.gameserver.model.templates.flypath.FlyPathEntry;
import com.aionemu.gameserver.model.templates.panels.SkillPanel;
import com.aionemu.gameserver.model.templates.quest.QuestItems;
import com.aionemu.gameserver.model.templates.stats.PlayerStatsTemplate;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EMOTION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PET;
import com.aionemu.gameserver.network.aion.serverpackets.SM_MOTION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_NPC_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_KISK_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EMOTION_SWITCH;
import com.aionemu.gameserver.network.aion.serverpackets.SM_HEADING_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_GATHERABLE_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_DELETE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_NEARBY_QUESTS;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_DIE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ATTACK_STATUS;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SKILL_CANCEL;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ITEM_USAGE_ANIMATION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PRIVATE_STORE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEVEL_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PACKAGE_INFO_NOTIFY;
import com.aionemu.gameserver.network.aion.serverpackets.SM_STATS_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_STATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_STANCE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ATTACK_STATUS.LOG;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ATTACK_STATUS.TYPE;
import com.aionemu.gameserver.questEngine.QuestEngine;
import com.aionemu.gameserver.questEngine.model.QuestEnv;
import com.aionemu.gameserver.restrictions.RestrictionsManager;
import com.aionemu.gameserver.services.QuestService;
import com.aionemu.gameserver.services.SerialKillerService;
import com.aionemu.gameserver.services.SiegeService;
import com.aionemu.gameserver.services.DuelService;
import com.aionemu.gameserver.services.PvpService;
import com.aionemu.gameserver.services.HTMLService;
import com.aionemu.gameserver.services.ClassChangeService;
import com.aionemu.gameserver.services.SkillLearnService;
import com.aionemu.gameserver.services.LegionService;
import com.aionemu.gameserver.services.abyss.AbyssService;
import com.aionemu.gameserver.services.craft.CraftSkillUpdateService;
import com.aionemu.gameserver.services.ecfunctions.oneVsone.ArenaMasterService;
import com.aionemu.gameserver.services.ecfunctions.oneVsone.OneVsOneStruct;
import com.aionemu.gameserver.services.instance.InstanceService;
import com.aionemu.gameserver.services.item.ItemService;
import com.aionemu.gameserver.services.summons.SummonsService;
import com.aionemu.gameserver.skillengine.SkillEngine;
import com.aionemu.gameserver.skillengine.model.Effect;
import com.aionemu.gameserver.skillengine.model.DispelCategoryType;
import com.aionemu.gameserver.skillengine.model.SkillTargetSlot;
import com.aionemu.gameserver.skillengine.model.Skill;
import com.aionemu.gameserver.skillengine.model.SkillTemplate;
import com.aionemu.gameserver.skillengine.model.HealType;
import com.aionemu.gameserver.skillengine.model.Skill.SkillMethod;
import com.aionemu.gameserver.taskmanager.tasks.PlayerMoveTaskManager;
import com.aionemu.gameserver.taskmanager.tasks.TeamEffectUpdater;
import com.aionemu.gameserver.utils.MathUtil;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.ThreadPoolManager;
import com.aionemu.gameserver.utils.audit.AuditLogger;
import com.aionemu.gameserver.world.MapRegion;
import com.aionemu.gameserver.world.World;
import com.aionemu.gameserver.world.WorldType;
import com.aionemu.gameserver.world.geo.GeoService;
import com.aionemu.gameserver.world.zone.ZoneInstance;
import com.aionemu.gameserver.world.zone.ZoneName;

/**
* This class is for controlling players.
*
* @author -Nemesiss-, ATracer, xavier, Sarynth, RotO, xTz, KID, Sippolo
*/
public class PlayerController extends CreatureController<Player> {

private Logger log = LoggerFactory.getLogger(PlayerController.class);
private boolean isInShutdownProgress;
private long lastAttackMilis = 0;
private long lastAttackedMilis = 0;
private int stance = 0;
@SuppressWarnings("unused")
private Listener mListener;
protected BattleGroundTemplate template;

@Override
public void see(VisibleObject object) {
super.see(object);
if (object instanceof Player) {
Player player = (Player) object;
PacketSendUtility.sendPacket(getOwner(), new SM_PLAYER_INFO(player, getOwner().isAggroIconTo(player)));
PacketSendUtility.sendPacket(getOwner(), new SM_MOTION(player.getObjectId(), player.getMotions().getActiveMotions()));
if (player.isInPlayerMode(PlayerMode.RIDE)) {
PacketSendUtility.sendPacket(getOwner(), new SM_EMOTION(player, EmotionType.RIDE, 0, player.ride.getNpcId()));
}
if (player.getPet() != null) {
LoggerFactory.getLogger(PlayerController.class).debug("Player " + getOwner().getName() + " sees " + object.getName() + " that has toypet");
PacketSendUtility.sendPacket(getOwner(), new SM_PET(3, player.getPet()));
}
player.getEffectController().sendEffectIconsTo(getOwner());
} else if (object instanceof Kisk) {
Kisk kisk = ((Kisk) object);
PacketSendUtility.sendPacket(getOwner(), new SM_NPC_INFO(kisk, getOwner()));
if (getOwner().getRace() == kisk.getOwnerRace()) {
PacketSendUtility.sendPacket(getOwner(), new SM_KISK_UPDATE(kisk));
}
} else if (object instanceof Npc) {
Npc npc = ((Npc) object);
LookManager.corrigateHeading(npc, this.getOwner());
PacketSendUtility.sendPacket(getOwner(), new SM_NPC_INFO(npc, getOwner()));
PacketSendUtility.sendPacket(getOwner(), new SM_EMOTION_SWITCH(npc, npc.getState(), EmotionType.SELECT_TARGET));
PacketSendUtility.sendPacket(getOwner(), new SM_HEADING_UPDATE(object.getObjectId(), (byte) object.getHeading()));
if (!npc.getEffectController().isEmpty()) {
npc.getEffectController().sendEffectIconsTo(getOwner());
}
QuestEngine.getInstance().onAtDistance(new QuestEnv(object, getOwner(), 0, 0));
} else if (object instanceof Summon) {
Summon npc = ((Summon) object);
PacketSendUtility.sendPacket(getOwner(), new SM_NPC_INFO(npc, getOwner()));
if (!npc.getEffectController().isEmpty()) {
npc.getEffectController().sendEffectIconsTo(getOwner());
}
} else if (object instanceof Gatherable || object instanceof StaticObject) {
PacketSendUtility.sendPacket(getOwner(), new SM_GATHERABLE_INFO(object));
} else if (object instanceof Pet) {
PacketSendUtility.sendPacket(getOwner(), new SM_PET(3, (Pet) object));
}
}

@Override
public void notSee(VisibleObject object, boolean isOutOfRange) {
super.notSee(object, isOutOfRange);
if (object instanceof Pet) {
PacketSendUtility.sendPacket(getOwner(), new SM_PET(4, (Pet) object));
} else {
PacketSendUtility.sendPacket(getOwner(), new SM_DELETE(object, isOutOfRange ? 0 : 15));
}
}

public void updateNearbyQuests() {
HashMap<Integer, Integer> nearbyQuestList = new HashMap<>();
for (int questId : getOwner().getPosition().getMapRegion().getParent().getQuestIds()) {
int diff = 0;
if (questId <= 0xFFFF) {
diff = QuestService.getLevelRequirementDiff(questId, getOwner().getCommonData().getLevel());
}
if (diff <= 2 && QuestService.checkStartConditions(new QuestEnv(null, getOwner(), questId, 0), false)) {
nearbyQuestList.put(questId, diff);
}
}
PacketSendUtility.sendPacket(getOwner(), new SM_NEARBY_QUESTS(nearbyQuestList));
}

@Override
public void onEnterZone(ZoneInstance zone) {
Player player = getOwner();
if (!zone.canRide() && player.isInPlayerMode(PlayerMode.RIDE)) {
player.unsetPlayerMode(PlayerMode.RIDE);
}
InstanceService.onEnterZone(player, zone);
if (zone.getAreaTemplate().getZoneName() == null) {
log.error("No name found for a Zone in the map " + zone.getAreaTemplate().getWorldId());
} else {
QuestEngine.getInstance().onEnterZone(new QuestEnv(null, player, 0, 0), zone.getAreaTemplate().getZoneName());
}
}

@Override
public void onLeaveZone(ZoneInstance zone) {
Player player = getOwner();
InstanceService.onLeaveZone(player, zone);
ZoneName zoneName = zone.getAreaTemplate().getZoneName();
if (zoneName == null) {
log.warn("No name for zone template in " + zone.getAreaTemplate().getWorldId());
return;
}
QuestEngine.getInstance().onLeaveZone(new QuestEnv(null, player, 0, 0), zoneName);
}

/**
* {@inheritDoc} Should only be triggered from one place (life stats)
*/
// TODO [AT] move
public void onEnterWorld() {

InstanceService.onEnterInstance(getOwner());
if (getOwner().getPosition().getWorldMapInstance().getParent().isExceptBuff()) {
getOwner().getEffectController().removeAllEffects();
}

if (getOwner().getBattleGround() != null && getOwner().getWorldId() != getOwner().getBattleGround().getWorldId()) {
BattleGroundManager.unregisterPlayer(getOwner());
getOwner().battlegroundWaiting = false;
getOwner().setBattleGround(null);
}

for (Effect ef : getOwner().getEffectController().getAbnormalEffects()) {
if (ef.isDeityAvatar()) {
// remove abyss transformation if worldtype != abyss && worldtype != balaurea
if (getOwner().getWorldType() != WorldType.ABYSS && getOwner().getWorldType() != WorldType.BALAUREA || getOwner().isInInstance() || getOwner().getWorldId() == 600040000) {
ef.endEffect();
getOwner().getEffectController().clearEffect(ef);
}
} else if (ef.getSkillTemplate().getDispelCategory() == DispelCategoryType.NPC_BUFF) {
ef.endEffect();
getOwner().getEffectController().clearEffect(ef);
}
}
}

// TODO [AT] move
public void onLeaveWorld() {
SerialKillerService.getInstance().onLeaveMap(getOwner());
ArenaMasterService.getInstance().onLeaveInstance(getOwner());
InstanceService.onLeaveInstance(getOwner());
}

public void validateLoginZone() {
int mapId;
float x, y, z;
byte h;
boolean moveToBind = false;

BindPointPosition bind = getOwner().getBindPoint();

if (bind != null) {
mapId = bind.getMapId();
x = bind.getX();
y = bind.getY();
z = bind.getZ();
h = bind.getHeading();
} else {
PlayerInitialData.LocationData start = DataManager.PLAYER_INITIAL_DATA.getSpawnLocation(getOwner().getRace());

mapId = start.getMapId();
x = start.getX();
y = start.getY();
z = start.getZ();
h = start.getHeading();
}
if (!SiegeService.getInstance().validateLoginZone(getOwner())) {
moveToBind = true;
} else {
long lastOnline = getOwner().getCommonData().getLastOnline().getTime();
long secondsOffline = (System.currentTimeMillis() / 1000) - lastOnline / 1000;
if (secondsOffline > 10 * 60) { //Logout in no-recall zone sends you to bindpoint after 10 (??) minutes
for (ZoneInstance zone : getOwner().getPosition().getMapRegion().getZones(getOwner())) {
if (!zone.canRecall()) {
moveToBind = true;
break;
}
}
}
}

if (moveToBind) {
World.getInstance().setPosition(getOwner(), mapId, x, y, z, h);
}
}

public void onDie(@Nonnull Creature lastAttacker, boolean showPacket) {
Player player = this.getOwner();
player.getController().cancelCurrentSkill();
player.setRebirthRevive(getOwner().haveSelfRezEffect());
showPacket = player.hasResurrectBase() ? false : showPacket;
Creature master = lastAttacker.getMaster();

// crazy Daeva
if (EventSystem.ENABLE_CRAZY) {
if (((master instanceof Player)) && (master.getRace() != player.getRace())) {
CrazyDaevaService.getInstance().crazyOnDie(player, (Player) master, true);
}
}

// Battelground
if (master instanceof Player) {
if (((Player) master).getBattleGround() != null && ((Player) master).getBattleGround() instanceof AssaultBattleGround) {
((AssaultBattleGround) (((Player) master).getBattleGround())).onKillPlayer(player, (Player) master);
}
}
// 1 vs 1 Event
if (EventSystem.ENABLE_ONEVONE){
if (((master instanceof Player)) && ((Player) master).isInPkMode()){
for(int worldId : OneVsOneStruct.worldid){
if(master.getWorldId() == worldId){
ArenaMasterService.getInstance().onDie((Player) master, player);
}
}
}
}

// High ranked kill announce
AbyssRank ar = player.getAbyssRank();
if (AbyssService.isOnPvpMap(player) && ar != null) {
if (ar.getRank().getId() >= 10) {
AbyssService.rankedKillAnnounce(player);
}
}

if (DuelService.getInstance().isDueling(player.getObjectId())) {
if (master != null && DuelService.getInstance().isDueling(player.getObjectId(), master.getObjectId())) {
DuelService.getInstance().loseDuel(player);
player.getEffectController().removeAbnormalEffectsByTargetSlot(SkillTargetSlot.DEBUFF);
player.getLifeStats().setCurrentHpPercent(33);
player.getLifeStats().setCurrentMpPercent(33);
return;
}
DuelService.getInstance().loseDuel(player);
}

/**
* Release summon
*/
Summon summon = player.getSummon();
if (summon != null) {
SummonsService.doMode(SummonMode.RELEASE, summon, UnsummonType.UNSPECIFIED);
}

// setIsFlyingBeforeDead for PlayerReviveService
if (player.isInState(CreatureState.FLYING)) {
player.setIsFlyingBeforeDeath(true);
}

// ride
player.setPlayerMode(PlayerMode.RIDE, null);
player.unsetState(CreatureState.RESTING);
player.unsetState(CreatureState.FLOATING_CORPSE);

// unsetflying
player.unsetState(CreatureState.FLYING);
player.unsetState(CreatureState.GLIDING);
player.setFlyState(0);

if (player.isInInstance()) {
if (player.getPosition().getWorldMapInstance().getInstanceHandler().onDie(player, lastAttacker)) {
super.onDie(lastAttacker);
return;
}
}

MapRegion mapRegion = player.getPosition().getMapRegion();
if (mapRegion != null && mapRegion.onDie(lastAttacker, getOwner())) {
return;
}

this.doReward();

if (master instanceof Npc || master == player) {
if (player.getLevel() > 4 && !isNoDeathPenaltyInEffect())
player.getCommonData().calculateExpLoss();
}
// Effects removed with super.onDie()
super.onDie(lastAttacker);

//test it if bug (maybe not needed)
if (player.getBattleGround() != null && player.getBattleGround() instanceof CTFBattleGround && master instanceof Player) {
int tplId = player.getBattleGround().getTplId();
template = DataManager.BATTLEGROUND_DATA.getBattleGroundTemplate(tplId);
player.getBattleGround().increasePoints((Player) master, template.getRules().getKillPlayer());
}
if (player.battlegroundFlag != null) {
player.getBattleGround().broadcastToBattleGround(player.getCommonData().getName() + (player.getLegion() != null ? " de " + player.getLegion().getLegionName() : "") + " got the " + (player.battlegroundFlag.getRace() == Race.ELYOS ? "Elyséen" : "Asmodien") + " !", null);
if (master instanceof Player) {
player.getBattleGround().increasePoints((Player) master, template.getRules().getFlagBase());
}

player.battlegroundFlag.getController().dropped = true;
player.battlegroundFlag.setFlagHolder(null);
player.battlegroundFlag = null;
if (player.getController().getTask(TaskId.BATTLEGROUND_CARRY_FLAG) != null) {
player.getController().getTask(TaskId.BATTLEGROUND_CARRY_FLAG).cancel(true);
player.getController().addTask(TaskId.BATTLEGROUND_CARRY_FLAG, null);
}
}
player.getActionList().clearAll();

// send sm_emotion with DIE
// have to be send after state is updated!
sendDieFromCreature(lastAttacker, showPacket);

QuestEngine.getInstance().onDie(new QuestEnv(null, player, 0, 0));

if (player.isInGroup2()) {
player.getPlayerGroup2().sendPacket(SM_SYSTEM_MESSAGE.STR_MSG_COMBAT_FRIENDLY_DEATH(player.getName()), new ExcludePlayerFilter(player));
}
}

@Override
public void onDie(@Nonnull Creature lastAttacker) {
this.onDie(lastAttacker, true);
}

public void sendDie() {
sendDieFromCreature(getOwner(), true);
}

private void sendDieFromCreature(@Nonnull Creature lastAttacker, boolean showPacket) {
Player player = this.getOwner();

PacketSendUtility.broadcastPacket(player, new SM_EMOTION(player, EmotionType.DIE, 0, player.equals(lastAttacker) ? 0 : lastAttacker.getObjectId()), true);

if (showPacket) {
int kiskTimeRemaining = (player.getKisk() != null ? player.getKisk().getRemainingLifetime() : 0);
PacketSendUtility.sendPacket(player, new SM_DIE(player.canUseRebirthRevive(), player.haveSelfRezItem(), kiskTimeRemaining, 0, isInvader(player)));
}

PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_COMBAT_MY_DEATH);
}

private boolean isInvader(Player player) {
if (player.getRace().equals(Race.ASMODIANS)) {
return player.getWorldId() == 210060000;
} else {
return player.getWorldId() == 220050000;
}
}

@Override
public void doReward() {
PvpService.getInstance().doReward(getOwner());
}

@Override
public void onBeforeSpawn() {
this.onBeforeSpawn(true);
/*
super.onBeforeSpawn();
startProtectionActiveTask();
if (getOwner().getIsFlyingBeforeDeath()) {
getOwner().unsetState(CreatureState.FLOATING_CORPSE);
} else {
getOwner().unsetState(CreatureState.DEAD);
}
getOwner().setState(CreatureState.ACTIVE);
*/
}

public void onBeforeSpawn(boolean blink) {
super.onBeforeSpawn();
if (blink) {
startProtectionActiveTask();
}
if (getOwner().getIsFlyingBeforeDeath()) {
getOwner().unsetState(CreatureState.FLOATING_CORPSE);
} else {
getOwner().unsetState(CreatureState.DEAD);
}
getOwner().setState(CreatureState.ACTIVE);
}

@Override
public void attackTarget(Creature target, int time) {

PlayerGameStats gameStats = getOwner().getGameStats();

if (!RestrictionsManager.canAttack(getOwner(), target)) {
return;
}

// Normal attack is already limited client side (ex. Press C and attacker approaches target)
// but need a check server side too also for Z axis issue
if (!MathUtil.isInAttackRange(getOwner(), target, (float) (getOwner().getGameStats().getAttackRange().getCurrent() / 1000f) + 1)) {
return;
}

if (!GeoService.getInstance().canSee(getOwner(), target)) {
PacketSendUtility.sendPacket(getOwner(), SM_SYSTEM_MESSAGE.STR_ATTACK_OBSTACLE_EXIST);
return;
}

if (target instanceof Npc) {
QuestEngine.getInstance().onAttack(new QuestEnv(target, getOwner(), 0, 0));
}

int attackSpeed = gameStats.getAttackSpeed().getCurrent();

long milis = System.currentTimeMillis();
// network ping..
if (milis - lastAttackMilis + 300 < attackSpeed) {
// hack
return;
}
lastAttackMilis = milis;

/**
* notify attack observers
*/
super.attackTarget(target, time);

}

@Override
public void onAttack(Creature creature, int skillId, TYPE type, int damage, boolean notifyAttack, LOG log) {
if (getOwner().getLifeStats().isAlreadyDead()) {
return;
}

if (getOwner().isInvul() || getOwner().isProtectionActive()) {
damage = 0;
}

if (getOwner().getBattleGround() != null && !getOwner().getBattleGround().running) {
damage = 0;
}

if (getOwner().getActionList() != null) {
getOwner().getActionList().addDamage(creature, damage);
}

cancelUseItem();
cancelGathering();
super.onAttack(creature, skillId, type, damage, notifyAttack, log);

PacketSendUtility.broadcastPacket(getOwner(), new SM_ATTACK_STATUS(getOwner(), type, skillId, damage, log), true);

if (creature instanceof Npc) {
QuestEngine.getInstance().onAttack(new QuestEnv(creature, getOwner(), 0, 0));
}

lastAttackedMilis = System.currentTimeMillis();
}

/**
* @param skillId
* @param targetType
* @param x
* @param y
* @param z
*/
public void useSkill(int skillId, int targetType, float x, float y, float z, int time) {
Player player = getOwner();

Skill skill = SkillEngine.getInstance().getSkillFor(player, skillId, player.getTarget());

if (skill != null) {
if (!RestrictionsManager.canUseSkill(player, skill)) {
return;
}

skill.setTargetType(targetType, x, y, z);
skill.setHitTime(time);
skill.useSkill();
}
}

/**
* @param template
* @param targetType
* @param x
* @param y
* @param z
* @param clientHitTime
*/
public void useSkill(SkillTemplate template, int targetType, float x, float y, float z, int clientHitTime,
int skillLevel) {
Player player = getOwner();
Skill skill = null;
skill = SkillEngine.getInstance().getSkillFor(player, template, player.getTarget());
if (skill == null && player.isTransformed()) {
SkillPanel panel = DataManager.PANEL_SKILL_DATA.getSkillPanel(player.getTransformModel().getPanelId());
if (panel != null && panel.canUseSkill(template.getSkillId(), skillLevel)) {
skill = SkillEngine.getInstance().getSkillFor(player, template, player.getTarget(), skillLevel);
}
}

if (skill != null) {
if (!RestrictionsManager.canUseSkill(player, skill)) {
return;
}

skill.setTargetType(targetType, x, y, z);
skill.setHitTime(clientHitTime);
skill.useSkill();
}
}

@Override
public void onMove() {
getOwner().getObserveController().notifyMoveObservers();
super.onMove();
}

@Override
public void onStopMove() {
PlayerMoveTaskManager.getInstance().removePlayer(getOwner());
getOwner().getObserveController().notifyMoveObservers();
getOwner().getMoveController().setInMove(false);
cancelCurrentSkill();
updateZone();
super.onStopMove();
}

@Override
public void onStartMove() {
getOwner().getMoveController().setInMove(true);
PlayerMoveTaskManager.getInstance().addPlayer(getOwner());
cancelUseItem();
cancelCurrentSkill();
super.onStartMove();
}

@Override
public void cancelCurrentSkill() {
if (getOwner().getCastingSkill() == null) {
return;
}

Player player = getOwner();
Skill castingSkill = player.getCastingSkill();
castingSkill.cancelCast();
player.removeSkillCoolDown(castingSkill.getSkillTemplate().getCooldownId());
player.setCasting(null);
player.setNextSkillUse(0);
if (castingSkill.getSkillMethod() == SkillMethod.CAST || castingSkill.getSkillMethod() == SkillMethod.CHARGE) {
PacketSendUtility.broadcastPacket(player, new SM_SKILL_CANCEL(player, castingSkill.getSkillTemplate().getSkillId()), true);
PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_SKILL_CANCELED);
} else if (castingSkill.getSkillMethod() == SkillMethod.ITEM) {
PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_ITEM_CANCELED(new DescriptionId(castingSkill.getItemTemplate().getNameId())));
player.removeItemCoolDown(castingSkill.getItemTemplate().getUseLimits().getDelayId());
PacketSendUtility.broadcastPacket(player, new SM_ITEM_USAGE_ANIMATION(player.getObjectId(), castingSkill.getFirstTarget().getObjectId(), castingSkill.getItemObjectId(), castingSkill.getItemTemplate().getTemplateId(), 0, 3, 0), true);
}
}

@Override
public void cancelUseItem() {
Player player = getOwner();
Item usingItem = player.getUsingItem();
player.setUsingItem(null);
if (hasTask(TaskId.ITEM_USE)) {
cancelTask(TaskId.ITEM_USE);
PacketSendUtility.broadcastPacket(player, new SM_ITEM_USAGE_ANIMATION(player.getObjectId(), usingItem == null ? 0 : usingItem.getObjectId(), usingItem == null ? 0 : usingItem.getItemTemplate().getTemplateId(), 0, 3, 0), true);
}
}

public void cancelGathering() {
Player player = getOwner();
if (player.getTarget() instanceof Gatherable) {
Gatherable g = (Gatherable) player.getTarget();
g.getController().finishGathering(player);
}
}

public void updatePassiveStats() {
Player player = getOwner();
for (PlayerSkillEntry skillEntry : player.getSkillList().getAllSkills()) {
Skill skill = SkillEngine.getInstance().getSkillFor(player, skillEntry.getSkillId(), player.getTarget());
if (skill != null && skill.isPassive()) {
skill.useSkill();
}
}
}

@Override
public Player getOwner() {
return (Player) super.getOwner();
}

@Override
public void onRestore(HealType healType, int value) {
super.onRestore(healType, value);
switch (healType) {
case DP:
getOwner().getCommonData().addDp(value);
break;
default:
break;
}
}

/**
* @param player
* @return
*/
// TODO [AT] move to Player
public boolean isDueling(Player player) {
return DuelService.getInstance().isDueling(player.getObjectId(), getOwner().getObjectId());
}

// TODO [AT] rename or remove
public boolean isInShutdownProgress() {
return isInShutdownProgress;
}

// TODO [AT] rename or remove
public void setInShutdownProgress(boolean isInShutdownProgress) {
this.isInShutdownProgress = isInShutdownProgress;
}

@Override
public void onDialogSelect(int dialogId, Player player, int questId, int extendedRewardIndex) {
switch (dialogId) {
case 2:
PacketSendUtility.sendPacket(player, new SM_PRIVATE_STORE(getOwner().getStore(), player));
break;
}
}

public void upgradePlayer() {
Player player = getOwner();
byte level = player.getLevel();

PlayerStatsTemplate statsTemplate = DataManager.PLAYER_STATS_DATA.getTemplate(player);
player.setPlayerStatsTemplate(statsTemplate);

player.getLifeStats().synchronizeWithMaxStats();
player.getLifeStats().updateCurrentStats();

PacketSendUtility.broadcastPacket(player, new SM_LEVEL_UPDATE(player.getObjectId(), 0, level), true);

// Guides Html on level up
if (HTMLConfig.ENABLE_GUIDES) {
HTMLService.sendGuideHtml(player);
}

// Temporal
ClassChangeService.showClassChangeDialog(player);

QuestEngine.getInstance().onLvlUp(new QuestEnv(null, player, 0, 0));
updateNearbyQuests();

// add new skills
SkillLearnService.addNewSkills(player);

PacketSendUtility.broadcastPacket(player, new SM_PACKAGE_INFO_NOTIFY(0), true);

player.getController().updatePassiveStats();

// add recipe for morph
if (level == 10) {
CraftSkillUpdateService.getInstance().setMorphRecipe(player);
}

if (player.isInTeam()) {
TeamEffectUpdater.getInstance().startTask(player);
}
if (player.isLegionMember()) {
LegionService.getInstance().updateMemberInfo(player);
}
player.getNpcFactions().onLevelUp();
PacketSendUtility.sendPacket(player, new SM_STATS_INFO(player));
}

/**
* After entering game player char is "blinking" which means that it's in
* under some protection, after making an action char stops blinking. -
* Starts protection active - Schedules task to end protection
*/
public void startProtectionActiveTask() {
if (!getOwner().isProtectionActive()) {
getOwner().setVisualState(CreatureVisualState.BLINKING);
AttackUtil.cancelCastOn((Creature) getOwner());
AttackUtil.removeTargetFrom((Creature) getOwner());
PacketSendUtility.broadcastPacket(getOwner(), new SM_PLAYER_STATE(getOwner()), true);
Future<?> task = ThreadPoolManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
stopProtectionActiveTask();
}
}, 60000);
addTask(TaskId.PROTECTION_ACTIVE, task);
}
}

/**
* Stops protection active task after first move or use skill
*/
public void stopProtectionActiveTask() {
cancelTask(TaskId.PROTECTION_ACTIVE);
Player player = getOwner();
if (player != null && player.isSpawned()) {
player.unsetVisualState(CreatureVisualState.BLINKING);
PacketSendUtility.broadcastPacket(player, new SM_PLAYER_STATE(player), true);
notifyAIOnMove();
}
}

/**
* When player arrives at destination point of flying teleport
*/
public void onFlyTeleportEnd() {
Player player = getOwner();
if (player.isInPlayerMode(PlayerMode.WINDSTREAM)) {
player.unsetPlayerMode(PlayerMode.WINDSTREAM);
player.getLifeStats().triggerFpReduce();
player.unsetState(CreatureState.FLYING);
player.setState(CreatureState.ACTIVE);
player.setState(CreatureState.GLIDING);
player.getGameStats().updateStatsAndSpeedVisually();
} else {
player.unsetState(CreatureState.FLIGHT_TELEPORT);
player.setFlightTeleportId(0);

if (SecurityConfig.ENABLE_FLYPATH_VALIDATOR) {
long diff = (System.currentTimeMillis() - player.getFlyStartTime());
FlyPathEntry path = player.getCurrentFlyPath();

if (player.getWorldId() != path.getEndWorldId()) {
AuditLogger.info(player, "Player tried to use flyPath #" + path.getId() + " from not native start world "
+ player.getWorldId() + ". expected " + path.getEndWorldId());
}

if (diff < path.getTimeInMs()) {
AuditLogger.info(player,
"Player " + player.getName() + " used flypath bug " + diff + " instead of " + path.getTimeInMs());
/*
* todo if works teleport player to start_* xyz, or even ban
*/
}

player.setCurrentFlypath(null);
}

player.setFlightDistance(0);
player.setState(CreatureState.ACTIVE);
updateZone();
}
}

public boolean addItems(int itemId, int count) {
return ItemService.addQuestItems(getOwner(), Collections.singletonList(new QuestItems(itemId, count)));
}

public void startStance(final int skillId) {
stance = skillId;
}

public void stopStance() {
getOwner().getEffectController().removeEffect(stance);
PacketSendUtility.sendPacket(getOwner(), new SM_PLAYER_STANCE(getOwner(), 0));
stance = 0;
}

public int getStanceSkillId() {
return stance;
}

public boolean isUnderStance() {
return stance != 0;
}

public void updateSoulSickness(int skillId) {
Player player = getOwner();
House house = player.getActiveHouse();
if (house != null) {
switch (house.getHouseType()) {
case MANSION:
case ESTATE:
case PALACE:
return;
default:
break;
}
}

if (!player.havePermission(MembershipConfig.DISABLE_SOULSICKNESS)) {
int deathCount = player.getCommonData().getDeathCount();
if (deathCount < 10) {
deathCount++;
player.getCommonData().setDeathCount(deathCount);
}

if (skillId == 0) {
skillId = 8291;
}
SkillEngine.getInstance().getSkill(player, skillId, deathCount, player).useSkill();
}
}

/**
* Player is considered in combat if he's been attacked or has attacked less
* or equal 10s before
*
* @return true if the player is actively in combat
*/
public boolean isInCombat() {
return (((System.currentTimeMillis() - lastAttackedMilis) <= 10000) || ((System.currentTimeMillis() - lastAttackMilis) <= 10000));
}

/**
* Check if NoDeathPenalty is active
*
* @param player
* @return boolean
*/
public boolean isNoDeathPenaltyInEffect() {
// Check if NoDeathPenalty is active
Iterator<Effect> iterator = getOwner().getEffectController().iterator();
while (iterator.hasNext()) {
Effect effect = iterator.next();
if (effect.isNoDeathPenalty()) {
return true;
}
}
return false;
}

/**
* Check if NoResurrectPenalty is active
*
* @param player
* @return boolean
*/
public boolean isNoResurrectPenaltyInEffect() {
// Check if NoResurrectPenalty is active
Iterator<Effect> iterator = getOwner().getEffectController().iterator();
while (iterator.hasNext()) {
Effect effect = iterator.next();
if (effect.isNoResurrectPenalty()) {
return true;
}
}
return false;
}

/**
* Check if HiPass is active
*
* @param player
* @return boolean
*/
public boolean isHiPassInEffect() {
// Check if HiPass is active
Iterator<Effect> iterator = getOwner().getEffectController().iterator();
while (iterator.hasNext()) {
Effect effect = iterator.next();
if (effect.isHiPass()) {
return true;
}
}
return false;
}

public void registerListener(Listener listener) {
this.mListener = listener;
}

public void unregisterListener() {
this.mListener = null;
}

public static abstract interface Listener {
public abstract void onPlayerUsedSkill(int paramInt, Player paramPlayer);
}
}
 
Последнее редактирование модератором:
You need source code. Fix code at class PvpService and Player Controller.
If you do not know how to fix it look in the assembly where it works these classes
перевод:
Если вы не знаете, как это исправить, посмотрите в сборке, где работают эти классы
Ответ топ:D ответ на миллион. Ссылку скинешь где смотришь?:LOL:
 
Ответ топ:D ответ на миллион. Ссылку скинешь где смотришь?:LOL:
Неграмотные люди пользуются гугл-переводчиком потом копипастят мусор.
[DOUBLEPOST=1563198323,1563198139][/DOUBLEPOST]Адекватный ответ Автору темы был дан где смотреть. Кто имеет базовые знания справится.
 
Неграмотные люди пользуются гугл-переводчиком потом копипастят мусор.
[DOUBLEPOST=1563198323,1563198139][/DOUBLEPOST]Адекватный ответ Автору темы был дан где смотреть. Кто имеет базовые знания справится.
Мусор это как раз твои ответы в разделе помощи грамотный ты наш, да наверное и всё остальное что ты ту постишь.
или у этого есть ещё какой то смысл ?
If you do not know how to fix it look in the assembly where it works these classes
кроме как, если вы не шарите ищите в шаровых сборках где это работает :ROFLMAO:

просвети нас неграмотных:D на чисто русском языке, на русском форуме.
Тем более автору темы, всё равно этот текст переводить на немецкий, как бы международного скандала не возникло бы :LOL:.

Или ты только посты, где указаны ошибки в твоей сборке можешь удалять и закрывать поспешно тему?
Кто имеет базовые знания справится.

Я думаю, кто имеет базовые знания и с этим справится, в отличии от тебя.
http://javaclub.ru/forum/threads/2396/#post-14973
http://mmorpg-devs.ru/threads/Сборка-m-o-g-aion-4-75.18087/ На сегодня она может и не актуальна, можешь посмеяться, а на тот момент лучше не было. Понимаю что с тобой наверное некогда не сойдемся характерами, но все же напишу тебе и всем как есть. Нет Чат сервера, даже сейчас на всех версиях, сто миллионов раз просил его сделать. Я было обрадовался что, сделал, но потом выяснилось что для себя. Я взял пробник у Метавинда фикса на чат, а он не жужу и выяснилось что не будет никакого чата и фикс негде взять под его изобретение. Работает чат только под его IP и только под 64 битку. Чудесный фикс получился у Паши за 3 года моих просьб. Не корректно работают откаты данжей, то-есть распустил пати, сделал релог и заходи крабь, сколько хочешь. На мой вопрос почему в шаре работает, он ответа не знает. Не работает защита которую он мне втулил за 6к рублей типа как дополнительная разработка и кинул мне ее с 4.9. Сама защита его связана со скилами, можете представить какой это фикс с такой разницей в скиллах по версиям. В итоге деньги взял, повесил на меня эти скилы . Отказался доделывать, сказал нет времени, бери каждым классом бей скиллами и если защита срабатывает в чат, вписывай в игнор в ядре, показал куда. Ну думаю если я вручную весь дроп перелопатил то скилы перелопатить это мелочь. Ладно, может реально занят, закрыл глаза, добавил фулл все скиллы, потому что все срабатывали на эту защиту типо я читер, в итоге людей как банило так и банит. Времени у Пашки небыло, плюнул, вырубил в конфигах все что было, но все ровно за превышение скорости атаки, садит в тюрьму, а именно синов, если одеть два кинжала. Печаль, беда а ему так сказать насрать. Мне получаться еще заплатить надо что бы он мне теперь вырезал это дерьмо? У меня все работает, сказал он. Я не знаю что там у тебя у меня все четко. Даже пальцем не пошевелил что бы разобраться. А зачем? Деньги уже в кармане у меня. Получил деньги в перед и должен был это сделать качественно под эту версию, а не кидать мне как кусок говна с 4.9 где якобы все было идеально у него. Не коректно работают скиллы прорыва, сколько бы шмоток не купил перс, делаешь смену с инвентаря и вся эта пачка скиллов, работает нету проверки с инвентаря. Так же есть недоработки по осадам, незначительные, куча дырок в барьерах неправильно работающие бафы от артефактов и так далие. В данже гипериона не работают иды, в шаре иди пашут чудесно. Дайнатум так же есть баг в том что заряжать можно только 1 артефакт, нет связки в AI все ровно тп будет не надо напрягатся игрокам и Паше нахер надо. На Мост Йормунганда можно танк не гнать так как если убежать с поля зрения Бомбарда, когда висит баф, прибегаешь обратно, бафа нет на нем и мост так же можно не открывать, потому что стоит не видемая текстура моста и игрок бежит через мост как боженька. Есть баг с телепортом к Атраксе, после захвата крепы в пангее он не появляется в месте с остальными тп для захватившей рассы, хотя прописан по координатам и может появиться только если сделать рестарт. В самом данже Атраксы не работает, ворота они нейтральные для игрока, с AI вообще не понятно, а так же с самими спавнами кламбур в данже у него гооврит все пашет. Есть недоработки со скиллами, нейтралками, не доработан союз по дропу и распределению, не пашет поиск группы, в игре шиго есть баг, бывает не падает приз игроку. Есть баг с Лордами заступниками, они могут отхилиться и можно превратить их даже в каляску закла, короче говоря станы, оковы все пашет на них. За ворота любым изгибом можно тепешнуться, есть баги с барьерами на осадах, кап на статы есть в конфиге, но он не работает почему-то. Не правильно дает ап тут так же большая магия. Не работает привязка зон по наградам на осадах, тут присутствует я так понял магия, а так же рейтинг работает 1 только со списка конфига. Не правильно работают посланники здесь они спавняться только в Герхе и Кальдоре, Паша просто упертый сделал по своему. Регистрация на дерики кривая, у всех игроков разный вход, что бы войти, надо делать кучу релогов, на Арене до начало боя, можно тепешнуться через барьер и убить противника. Баг с покупкой дома, если игрок не продал предыдущий дом то он может завладеть новым домом, багнуться оба. Плата за аренду домов, неработает, можно не платить игрокам. Ивенты на половину рабочие, старые спавны, награды так же. Северный каталам и Южный в данжах недоработки как по дропу так и по Ai. Все мелочи не буду писать. Если это все исправить, думаю Паша еще косарь как минимум потребует и пару год будет делать это все. При выкупе сорцов не дал исходов на commons, чат сервер, логин сервер, сказал и не даст. На выше версиях можно представить что твориться. Если честно я устал, просить его. Регламент сам придумал сам и нарушел его, относится безответственно и делает не под заказчика, а под себя, продал и когда у него есть время он будет фиксить а не когда вам нужно. Продает как вы видите дорого, а элементарные фиксы есть в шаре, а он про них даже слышать не хочет. Я думал спрыгнуть с этой версии на выше, но опять же чем выше версии тем больше багов, делаеться только новое, все баги остаются старые, редко что правится и много делаться как он сам придумает или как у него получиться. Фишка Паши запутаться в фиксах, а происходит это в тот момент когда он делает фиксы на у себя на 5.6 версии грубо говоря, перекидывает их на 4.7 и тут дамы и господа происходит магия, думаю вы поняли какое качество фиксов. В конце концов в этом винегрете он не может разобраться и предлагает перейти на выше версию с маленькой доплатой за последнюю накрутил мне 300$ и по этому сценарию, переходы были еще на 4 версии 4.9, 5.1, 5.3 и 5.6. Куча потраченного времени и нервов . По моей просьбе сделать компенсацию и дать сорцы хотя бы от одной сборки, он отказался. По моим подсчетам я дал ему 900$ продает он эти сборки сейчас по 500$. При покупке у него договор был что все будет фиксится сразу, и вовремя, но 4.75 вы сами видите как профикшена и дело даже не в деньгах. Ивенты DLC свои втулил, потому что ему было лень вырезать, а мне они нахер ненужны были еще и навязывает мне их встоимость,нагло. Зачем мне еще нагрузка на сервак не понимаю? Фиксы если были то не то что просил и раз в 3 месяца если выдавливао с него, то это хорошо. Когда втулил мне сборку 5.1 пол года меня игнорировал, везде ответов 0. Само собой все расстроились и потеряли интерес и без сорцов запускать сервер, тратить кучу денег на рекламу, никто не захотел. Оказалось со временем что он подписал мего-конракт с климой. Сорцы не было смысла выкупать так как в его регламенте, четко написано что фиксит только он по ядру, а иначе, он отключён от SVN . Сам SVN переустанавливает, после каждого фикса, не понятно что фиксил даже незаписывает. Короче говоря SVN для показа лохам, типо он есть, для покупателя, но безполезный и к тому же там бардак полный. В итоге на Клизме не сложилось, больно игроки придирчивы были и баги на той же клизме по баг репорту, в точности как на нашем форуме. Я не мог запустить сервер с такими багами не имея ядра и в игноре. Короче судите сами, прав я или нет. Думаете я должен за это все платить сверху, не запустив сервер, боевой? Хотя предлагал ему сделать это все и заплатить но не сразу, а частями. Просил поменять взгляды и отношение к клиету, все напрасно. Что бы разойтись с ним мне хватит 5.3 или 5.6 исхода в котором, он мне отказал. А если уж нет то и терять мне нечего сами понимае, накипело у меня.
 
Мусор это как раз твои ответы в разделе помощи грамотный ты наш, да наверное и всё остальное что ты ту постишь.
или у этого есть ещё какой то смысл ?

кроме как, если вы не шарите ищите в шаровых сборках где это работает :ROFLMAO:

просвети нас неграмотных:D на чисто русском языке, на русском форуме.
Тем более автору темы, всё равно этот текст переводить на немецкий, как бы международного скандала не возникло бы :LOL:.

Или ты только посты, где указаны ошибки в твоей сборке можешь удалять и закрывать поспешно тему?


Я думаю, кто имеет базовые знания и с этим справится, в отличии от тебя.
http://javaclub.ru/forum/threads/2396/#post-14973
Ясно, понятно мусор неадекватный который пришел по рофлить. Откуда ты вылез вообще.
[DOUBLEPOST=1563225413,1563222738][/DOUBLEPOST]
PvpService és a Player Controller

Sorry, I can't find the error:

PvpService.java

package com.aionemu.gameserver.services;

import java.util.ArrayList;
import java.util.List;

import javolution.util.FastMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aionemu.commons.utils.Rnd;
import com.aionemu.gameserver.configs.main.CustomConfig;
import com.aionemu.gameserver.configs.main.EventSystem;
import com.aionemu.gameserver.configs.main.GroupConfig;
import com.aionemu.gameserver.configs.main.LoggingConfig;
import com.aionemu.gameserver.configs.main.PunishmentConfig;
import com.aionemu.gameserver.controllers.attack.AggroInfo;
import com.aionemu.gameserver.controllers.attack.KillList;
import com.aionemu.gameserver.eventEngine.crazy_daeva.CrazyDaevaService;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.player.RewardType;
import com.aionemu.gameserver.model.ingameshop.InGameShopEn;
import com.aionemu.gameserver.model.team2.alliance.PlayerAlliance;
import com.aionemu.gameserver.model.team2.group.PlayerGroup;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.questEngine.QuestEngine;
import com.aionemu.gameserver.questEngine.model.QuestEnv;
import com.aionemu.gameserver.services.abyss.AbyssPointsService;
import com.aionemu.gameserver.services.item.ItemService;
import com.aionemu.gameserver.utils.MathUtil;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.audit.AuditLogger;
import com.aionemu.gameserver.utils.stats.AbyssRankEnum;
import com.aionemu.gameserver.utils.stats.StatFunctions;

/**
* @author Sarynth
*/
public class PvpService {

private static Logger log = LoggerFactory.getLogger("KILL_LOG");

public static final PvpService getInstance() {
return SingletonHolder.instance;
}

private FastMap<Integer, KillList> pvpKillLists;

private PvpService() {
pvpKillLists = new FastMap<Integer, KillList>();
}

/**
* @param winnerId
* @param victimId
* @return
*/
private int getKillsFor(int winnerId, int victimId) {
KillList winnerKillList = pvpKillLists.get(winnerId);

if (winnerKillList == null) {
return 0;
}
return winnerKillList.getKillsFor(victimId);
}

/**
* @param winnerId
* @param victimId
*/
private void addKillFor(int winnerId, int victimId) {
KillList winnerKillList = pvpKillLists.get(winnerId);
if (winnerKillList == null) {
winnerKillList = new KillList();
pvpKillLists.put(winnerId, winnerKillList);
}
winnerKillList.addKillFor(victimId);
}

/**
* @param victim
*/
public void doReward(Player victim) {
// winner is the player that receives the kill count
final Player winner = victim.getAggroList().getMostPlayerDamage();

int totalDamage = victim.getAggroList().getTotalDamage();

if (totalDamage == 0 || winner == null || winner.getRace() == victim.getRace()) {
return;
}

if (victim.getBattleGround() != null) {
return;
}

// Add Player Kill to record.
if (this.getKillsFor(winner.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
winner.getAbyssRank().setAllKill();
int kills = winner.getAbyssRank().getAllKill();
// Pvp Kill Reward.
if (CustomConfig.ENABLE_KILL_REWARD) {
if (kills % CustomConfig.KILLS_NEEDED1 == 1) {
ItemService.addItem(winner, CustomConfig.REWARD1, 1);
PacketSendUtility.sendMessage(winner, "Congratulations, you have won " + "[item: " + CustomConfig.REWARD1
+ "] for having killed " + CustomConfig.KILLS_NEEDED1 + " players !");
log.info("[REWARD] Player [" + winner.getName() + "] win 2 [" + CustomConfig.REWARD1 + "]");
}
if (kills % CustomConfig.KILLS_NEEDED2 == 3) {
ItemService.addItem(winner, CustomConfig.REWARD2, 1);
PacketSendUtility.sendMessage(winner, "Congratulations, you have won " + "[item: " + CustomConfig.REWARD2
+ "] for having killed " + CustomConfig.KILLS_NEEDED2 + " players !");
log.info("[REWARD] Player [" + winner.getName() + "] win 4 [" + CustomConfig.REWARD2 + "]");
}
if (kills % CustomConfig.KILLS_NEEDED3 == 5) {
ItemService.addItem(winner, CustomConfig.REWARD3, 1);
PacketSendUtility.sendMessage(winner, "Congratulations, you have won " + "[item: " + CustomConfig.REWARD3
+ "] for having killed " + CustomConfig.KILLS_NEEDED3 + " players !");
log.info("[REWARD] Player [" + winner.getName() + "] win 6 [" + CustomConfig.REWARD3 + "]");
}
}
// PvP Toll Reward
if (CustomConfig.ENABLE_TOLL_REWARD) {
if (Rnd.get(0, 100) > CustomConfig.TOLL_CHANCE){
InGameShopEn.getInstance().addToll(winner, CustomConfig.TOLL_QUANTITY);
PacketSendUtility.sendMessage(winner, "You've recived " + CustomConfig.TOLL_QUANTITY + " tolls from PvP!");
}
}
}

//Crazy kill
if (EventSystem.ENABLE_CRAZY) {
if (winner.getRndCrazy() >= EventSystem.CRAZY_LOWEST_RND) {
AbyssPointsService.addAp(winner, 500);
AbyssPointsService.addGp(winner, 20);
}
}

// Announce that player has died.
PacketSendUtility.broadcastPacketAndReceive(victim, SM_SYSTEM_MESSAGE.STR_MSG_COMBAT_FRIENDLY_DEATH_TO_B(victim.getName(), winner.getName()));

// Pvp Kill Reward.
int reduceap = PunishmentConfig.PUNISHMENT_REDUCEAP;
if (reduceap < 0) {
reduceap *= -1;
}
if (reduceap > 100) {
reduceap = 100;
}

//Kill-log
if (LoggingConfig.LOG_KILL) {
log.info("[KILL] Player [" + winner.getName() + "] killed [" + victim.getName() + "]");
}

if ((LoggingConfig.LOG_PL) || (reduceap > 0)) {
String ip1 = winner.getClientConnection().getIP();
String mac1 = winner.getClientConnection().getMacAddress();
String ip2 = victim.getClientConnection().getIP();
String mac2 = victim.getClientConnection().getMacAddress();
if ((mac1 != null) && (mac2 != null)) {
if ((ip1.equalsIgnoreCase(ip2)) && (mac1.equalsIgnoreCase(mac2))) {
AuditLogger.info(winner, "Power Leveling : " + winner.getName() + " with " + victim.getName() + ", They have the sames ip=" + ip1 + " and mac=" + mac1 + ".");
if (reduceap > 0) {
int win_ap = winner.getAbyssRank().getAp() * reduceap / 100;
int vic_ap = victim.getAbyssRank().getAp() * reduceap / 100;
AbyssPointsService.addAp(winner, -win_ap);
AbyssPointsService.addAp(victim, -vic_ap);
PacketSendUtility.sendMessage(winner, "[PL-AP] You lost " + reduceap + "% of your total ap");
PacketSendUtility.sendMessage(victim, "[PL-AP] You lost " + reduceap + "% of your total ap");
}
return;
}
if (ip1.equalsIgnoreCase(ip2)) {
AuditLogger.info(winner, "Possible Power Leveling : " + winner.getName() + " with " + victim.getName() + ", They have the sames ip=" + ip1 + ".");
AuditLogger.info(winner, "Check if " + winner.getName() + " and " + victim.getName() + " are Brothers-Sisters-Lovers-dogs-cats...");
}
}
}

// Keep track of how much damage was dealt by players
// so we can remove AP based on player damage...
int playerDamage = 0;
boolean success;

// Distribute AP to groups and players that had damage.
for (AggroInfo aggro : victim.getAggroList().getFinalDamageList(true)) {
success = false;
if (aggro.getAttacker() instanceof Player) {
success = rewardPlayer(victim, totalDamage, aggro);
} else if (aggro.getAttacker() instanceof PlayerGroup) {
success = rewardPlayerGroup(victim, totalDamage, aggro);
} else if (aggro.getAttacker() instanceof PlayerAlliance) {
success = rewardPlayerAlliance(victim, totalDamage, aggro);
}

// Add damage last, so we don't include damage from same race. (Duels, Arena)
if (success) {
playerDamage += aggro.getDamage();
}
}

SerialKillerService.getInstance().updateRank(winner, victim);

//notify Quest engine for winner + his group
notifyKillQuests(winner, victim);

// Apply lost AP to defeated player
final int apLost = StatFunctions.calculatePvPApLost(victim, winner);
final int apActuallyLost = (int) (apLost * playerDamage / totalDamage);

if (apActuallyLost > 0) {
AbyssPointsService.addAp(victim, -apActuallyLost);
}
}

/**
* @param victim
* @param totalDamage
* @param aggro
* @return true if group is not same race
*/
private boolean rewardPlayerGroup(Player victim, int totalDamage, AggroInfo aggro) {
// Reward Group
PlayerGroup group = ((PlayerGroup) aggro.getAttacker());

// Don't Reward Player of Same Faction.
if (group.getRace() == victim.getRace()) {
return false;
}

// Find group members in range
List<Player> players = new ArrayList<Player>();

// Find highest rank and level in local group
int maxRank = AbyssRankEnum.GRADE9_SOLDIER.getId();
int maxLevel = 0;

for (Player member : group.getMembers()) {
if (MathUtil.isIn3dRange(member, victim, GroupConfig.GROUP_MAX_DISTANCE)) {
// Don't distribute AP to a dead player!
if (!member.getLifeStats().isAlreadyDead()) {
players.add(member);
if (member.getLevel() > maxLevel) {
maxLevel = member.getLevel();
}
if (member.getAbyssRank().getRank().getId() > maxRank) {
maxRank = member.getAbyssRank().getRank().getId();
}
}
}
}

// They are all dead or out of range.
if (players.isEmpty()) {
return false;
}

int baseApReward = StatFunctions.calculatePvpApGained(victim, maxRank, maxLevel);
int baseXpReward = StatFunctions.calculatePvpXpGained(victim, maxRank, maxLevel);
int baseDpReward = StatFunctions.calculatePvpDpGained(victim, maxRank, maxLevel);
float groupPercentage = (float) aggro.getDamage() / totalDamage;
int apRewardPerMember = Math.round(baseApReward * groupPercentage / players.size());
int xpRewardPerMember = Math.round(baseXpReward * groupPercentage / players.size());
int dpRewardPerMember = Math.round(baseDpReward * groupPercentage / players.size());

for (Player member : players) {
int memberApGain = 1;
int memberXpGain = 1;
int memberDpGain = 1;
if (this.getKillsFor(member.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
if (apRewardPerMember > 0) {
memberApGain = Math.round(RewardType.AP_PLAYER.calcReward(member, apRewardPerMember));
}
if (xpRewardPerMember > 0) {
memberXpGain = Math.round(xpRewardPerMember * member.getRates().getXpPlayerGainRate());
}
if (dpRewardPerMember > 0) {
memberDpGain = Math.round(StatFunctions.adjustPvpDpGained(dpRewardPerMember, victim.getLevel(), member.getLevel()) * member.getRates().getDpPlayerRate());
}

}
Player partner = member.findPartner();
if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
AbyssPointsService.addAp(member, victim, memberApGain + (memberApGain * 20 / 100)); //20% more AP for weddings
} else {
AbyssPointsService.addAp(member, victim, memberApGain);
}
member.getCommonData().addExp(memberXpGain, RewardType.PVP_KILL, victim.getName());
member.getCommonData().addEventExp(memberXpGain);
member.getCommonData().addDp(memberDpGain);
this.addKillFor(member.getObjectId(), victim.getObjectId());
}

return true;
}

/**
* @param victim
* @param totalDamage
* @param aggro
* @return true if group is not same race
*/
private boolean rewardPlayerAlliance(Player victim, int totalDamage, AggroInfo aggro) {
// Reward Alliance
PlayerAlliance alliance = ((PlayerAlliance) aggro.getAttacker());

// Don't Reward Player of Same Faction.
if (alliance.getLeaderObject().getRace() == victim.getRace()) {
return false;
}

// Find group members in range
List<Player> players = new ArrayList<Player>();

// Find highest rank and level in local group
int maxRank = AbyssRankEnum.GRADE9_SOLDIER.getId();
int maxLevel = 0;

for (Player member : alliance.getMembers()) {
if (!member.isOnline()) {
continue;
}
if (MathUtil.isIn3dRange(member, victim, GroupConfig.GROUP_MAX_DISTANCE)) {
// Don't distribute AP to a dead player!
if (!member.getLifeStats().isAlreadyDead()) {
players.add(member);
if (member.getLevel() > maxLevel) {
maxLevel = member.getLevel();
}
if (member.getAbyssRank().getRank().getId() > maxRank) {
maxRank = member.getAbyssRank().getRank().getId();
}
}
}
}

// They are all dead or out of range.
if (players.isEmpty()) {
return false;
}

int baseApReward = StatFunctions.calculatePvpApGained(victim, maxRank, maxLevel);
int baseXpReward = StatFunctions.calculatePvpXpGained(victim, maxRank, maxLevel);
int baseDpReward = StatFunctions.calculatePvpDpGained(victim, maxRank, maxLevel);
float groupPercentage = (float) aggro.getDamage() / totalDamage;
int apRewardPerMember = Math.round(baseApReward * groupPercentage / players.size());
int xpRewardPerMember = Math.round(baseXpReward * groupPercentage / players.size());
int dpRewardPerMember = Math.round(baseDpReward * groupPercentage / players.size());

for (Player member : players) {
int memberApGain = 1;
int memberXpGain = 1;
int memberDpGain = 1;
if (this.getKillsFor(member.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
if (apRewardPerMember > 0) {
memberApGain = Math.round(RewardType.AP_PLAYER.calcReward(member, apRewardPerMember));
}
if (xpRewardPerMember > 0) {
memberXpGain = Math.round(xpRewardPerMember * member.getRates().getXpPlayerGainRate());
}
if (dpRewardPerMember > 0) {
memberDpGain = Math.round(StatFunctions.adjustPvpDpGained(dpRewardPerMember, victim.getLevel(), member.getLevel()) * member.getRates().getDpPlayerRate());
}
}
AbyssPointsService.addAp(member, victim, memberApGain);
member.getCommonData().addExp(memberXpGain, RewardType.PVP_KILL, victim.getName());
member.getCommonData().addEventExp(memberXpGain);
member.getCommonData().addDp(memberDpGain);

this.addKillFor(member.getObjectId(), victim.getObjectId());
}

return true;
}

/**
* @param victim
* @param totalDamage
* @param aggro
* @return true if player is not same race
*/
private boolean rewardPlayer(Player victim, int totalDamage, AggroInfo aggro) {
// Reward Player
Player winner = ((Player) aggro.getAttacker());

// Don't Reward Player out of range/dead/same faction
if (winner.getRace() == victim.getRace() || !MathUtil.isIn3dRange(winner, victim, GroupConfig.GROUP_MAX_DISTANCE) || winner.getLifeStats().isAlreadyDead()) {
return false;
}

int baseApReward = 1;
int baseXpReward = 1;
int baseDpReward = 1;

if (this.getKillsFor(winner.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
baseApReward = StatFunctions.calculatePvpApGained(victim, winner.getAbyssRank().getRank().getId(), winner.getLevel());
baseXpReward = StatFunctions.calculatePvpXpGained(victim, winner.getAbyssRank().getRank().getId(), winner.getLevel());
baseDpReward = StatFunctions.calculatePvpDpGained(victim, winner.getAbyssRank().getRank().getId(), winner.getLevel());
if (EventSystem.ENABLE_CRAZY) {
if (winner.getRace() != victim.getRace()) {
CrazyDaevaService.getInstance().increaseRawKillCount(winner);
}
}
}

int apPlayerReward = Math.round(baseApReward * aggro.getDamage() / totalDamage);
apPlayerReward = (int) RewardType.AP_PLAYER.calcReward(winner, apPlayerReward);
int xpPlayerReward = Math.round(baseXpReward * winner.getRates().getXpPlayerGainRate() * aggro.getDamage() / totalDamage);
int dpPlayerReward = Math.round(baseDpReward * winner.getRates().getDpPlayerRate() * aggro.getDamage() / totalDamage);

AbyssPointsService.addAp(winner, victim, apPlayerReward);
winner.getCommonData().addExp(xpPlayerReward, RewardType.PVP_KILL, victim.getName());
winner.getCommonData().addEventExp(xpPlayerReward);
winner.getCommonData().addDp(dpPlayerReward);
this.addKillFor(winner.getObjectId(), victim.getObjectId());
return true;
}

private void notifyKillQuests(Player winner, Player victim) {
if (winner.getRace() == victim.getRace()) {
return;
}

List<Player> rewarded = new ArrayList<Player>();
int worldId = victim.getWorldId();

if (winner.isInGroup2()) {
rewarded.addAll(winner.getPlayerGroup2().getOnlineMembers());
} else if (winner.isInAlliance2()) {
rewarded.addAll(winner.getPlayerAllianceGroup2().getOnlineMembers());
} else {
rewarded.add(winner);
}

for (Player p : rewarded) {
if (!MathUtil.isIn3dRange(p, victim, GroupConfig.GROUP_MAX_DISTANCE) || p.getLifeStats().isAlreadyDead()) {
continue;
}

QuestEngine.getInstance().onKillInWorld(new QuestEnv(victim, p, 0, 0), worldId);
QuestEngine.getInstance().onKillRanked(new QuestEnv(victim, p, 0, 0), victim.getAbyssRank().getRank());
}
rewarded.clear();
}

@SuppressWarnings("synthetic-access")
private static class SingletonHolder {

protected static final PvpService instance = new PvpService();
}
}

-------------------------------------------------------
PlayerController.java

package com.aionemu.gameserver.controllers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.Future;

import com.aionemu.gameserver.ai2.manager.LookManager;
import com.aionemu.gameserver.configs.main.EventSystem;
import com.aionemu.gameserver.configs.main.HTMLConfig;
import com.aionemu.gameserver.configs.main.MembershipConfig;
import com.aionemu.gameserver.configs.main.SecurityConfig;
import com.aionemu.gameserver.controllers.attack.AttackUtil;
import com.aionemu.gameserver.dataholders.DataManager;
import com.aionemu.gameserver.dataholders.PlayerInitialData;
import com.aionemu.gameserver.eventEngine.battleground.model.templates.BattleGroundTemplate;
import com.aionemu.gameserver.eventEngine.battleground.services.battleground.AssaultBattleGround;
import com.aionemu.gameserver.eventEngine.battleground.services.battleground.BattleGroundManager;
import com.aionemu.gameserver.eventEngine.battleground.services.battleground.CTFBattleGround;
import com.aionemu.gameserver.eventEngine.crazy_daeva.CrazyDaevaService;
import com.aionemu.gameserver.model.DescriptionId;
import com.aionemu.gameserver.model.EmotionType;
import com.aionemu.gameserver.model.Race;
import com.aionemu.gameserver.model.TaskId;
import com.aionemu.gameserver.model.actions.PlayerMode;
import com.aionemu.gameserver.model.gameobjects.Kisk;
import com.aionemu.gameserver.model.gameobjects.Npc;
import com.aionemu.gameserver.model.gameobjects.Summon;
import com.aionemu.gameserver.model.gameobjects.VisibleObject;
import com.aionemu.gameserver.model.gameobjects.Item;
import com.aionemu.gameserver.model.gameobjects.Creature;
import com.aionemu.gameserver.model.gameobjects.Pet;
import com.aionemu.gameserver.model.gameobjects.Gatherable;
import com.aionemu.gameserver.model.gameobjects.StaticObject;
import com.aionemu.gameserver.model.gameobjects.player.AbyssRank;
import com.aionemu.gameserver.model.gameobjects.player.BindPointPosition;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.state.CreatureState;
import com.aionemu.gameserver.model.gameobjects.state.CreatureVisualState;
import com.aionemu.gameserver.model.house.House;
import com.aionemu.gameserver.model.skill.PlayerSkillEntry;
import com.aionemu.gameserver.model.stats.container.PlayerGameStats;
import com.aionemu.gameserver.model.summons.SummonMode;
import com.aionemu.gameserver.model.summons.UnsummonType;
import com.aionemu.gameserver.model.team2.group.PlayerFilters.ExcludePlayerFilter;
import com.aionemu.gameserver.model.templates.flypath.FlyPathEntry;
import com.aionemu.gameserver.model.templates.panels.SkillPanel;
import com.aionemu.gameserver.model.templates.quest.QuestItems;
import com.aionemu.gameserver.model.templates.stats.PlayerStatsTemplate;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EMOTION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PET;
import com.aionemu.gameserver.network.aion.serverpackets.SM_MOTION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_NPC_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_KISK_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EMOTION_SWITCH;
import com.aionemu.gameserver.network.aion.serverpackets.SM_HEADING_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_GATHERABLE_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_DELETE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_NEARBY_QUESTS;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_DIE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ATTACK_STATUS;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SKILL_CANCEL;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ITEM_USAGE_ANIMATION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PRIVATE_STORE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEVEL_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PACKAGE_INFO_NOTIFY;
import com.aionemu.gameserver.network.aion.serverpackets.SM_STATS_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_STATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_STANCE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ATTACK_STATUS.LOG;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ATTACK_STATUS.TYPE;
import com.aionemu.gameserver.questEngine.QuestEngine;
import com.aionemu.gameserver.questEngine.model.QuestEnv;
import com.aionemu.gameserver.restrictions.RestrictionsManager;
import com.aionemu.gameserver.services.QuestService;
import com.aionemu.gameserver.services.SerialKillerService;
import com.aionemu.gameserver.services.SiegeService;
import com.aionemu.gameserver.services.DuelService;
import com.aionemu.gameserver.services.PvpService;
import com.aionemu.gameserver.services.HTMLService;
import com.aionemu.gameserver.services.ClassChangeService;
import com.aionemu.gameserver.services.SkillLearnService;
import com.aionemu.gameserver.services.LegionService;
import com.aionemu.gameserver.services.abyss.AbyssService;
import com.aionemu.gameserver.services.craft.CraftSkillUpdateService;
import com.aionemu.gameserver.services.ecfunctions.oneVsone.ArenaMasterService;
import com.aionemu.gameserver.services.ecfunctions.oneVsone.OneVsOneStruct;
import com.aionemu.gameserver.services.instance.InstanceService;
import com.aionemu.gameserver.services.item.ItemService;
import com.aionemu.gameserver.services.summons.SummonsService;
import com.aionemu.gameserver.skillengine.SkillEngine;
import com.aionemu.gameserver.skillengine.model.Effect;
import com.aionemu.gameserver.skillengine.model.DispelCategoryType;
import com.aionemu.gameserver.skillengine.model.SkillTargetSlot;
import com.aionemu.gameserver.skillengine.model.Skill;
import com.aionemu.gameserver.skillengine.model.SkillTemplate;
import com.aionemu.gameserver.skillengine.model.HealType;
import com.aionemu.gameserver.skillengine.model.Skill.SkillMethod;
import com.aionemu.gameserver.taskmanager.tasks.PlayerMoveTaskManager;
import com.aionemu.gameserver.taskmanager.tasks.TeamEffectUpdater;
import com.aionemu.gameserver.utils.MathUtil;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.ThreadPoolManager;
import com.aionemu.gameserver.utils.audit.AuditLogger;
import com.aionemu.gameserver.world.MapRegion;
import com.aionemu.gameserver.world.World;
import com.aionemu.gameserver.world.WorldType;
import com.aionemu.gameserver.world.geo.GeoService;
import com.aionemu.gameserver.world.zone.ZoneInstance;
import com.aionemu.gameserver.world.zone.ZoneName;

/**
* This class is for controlling players.
*
* @author -Nemesiss-, ATracer, xavier, Sarynth, RotO, xTz, KID, Sippolo
*/
public class PlayerController extends CreatureController<Player> {

private Logger log = LoggerFactory.getLogger(PlayerController.class);
private boolean isInShutdownProgress;
private long lastAttackMilis = 0;
private long lastAttackedMilis = 0;
private int stance = 0;
@SuppressWarnings("unused")
private Listener mListener;
protected BattleGroundTemplate template;

@Override
public void see(VisibleObject object) {
super.see(object);
if (object instanceof Player) {
Player player = (Player) object;
PacketSendUtility.sendPacket(getOwner(), new SM_PLAYER_INFO(player, getOwner().isAggroIconTo(player)));
PacketSendUtility.sendPacket(getOwner(), new SM_MOTION(player.getObjectId(), player.getMotions().getActiveMotions()));
if (player.isInPlayerMode(PlayerMode.RIDE)) {
PacketSendUtility.sendPacket(getOwner(), new SM_EMOTION(player, EmotionType.RIDE, 0, player.ride.getNpcId()));
}
if (player.getPet() != null) {
LoggerFactory.getLogger(PlayerController.class).debug("Player " + getOwner().getName() + " sees " + object.getName() + " that has toypet");
PacketSendUtility.sendPacket(getOwner(), new SM_PET(3, player.getPet()));
}
player.getEffectController().sendEffectIconsTo(getOwner());
} else if (object instanceof Kisk) {
Kisk kisk = ((Kisk) object);
PacketSendUtility.sendPacket(getOwner(), new SM_NPC_INFO(kisk, getOwner()));
if (getOwner().getRace() == kisk.getOwnerRace()) {
PacketSendUtility.sendPacket(getOwner(), new SM_KISK_UPDATE(kisk));
}
} else if (object instanceof Npc) {
Npc npc = ((Npc) object);
LookManager.corrigateHeading(npc, this.getOwner());
PacketSendUtility.sendPacket(getOwner(), new SM_NPC_INFO(npc, getOwner()));
PacketSendUtility.sendPacket(getOwner(), new SM_EMOTION_SWITCH(npc, npc.getState(), EmotionType.SELECT_TARGET));
PacketSendUtility.sendPacket(getOwner(), new SM_HEADING_UPDATE(object.getObjectId(), (byte) object.getHeading()));
if (!npc.getEffectController().isEmpty()) {
npc.getEffectController().sendEffectIconsTo(getOwner());
}
QuestEngine.getInstance().onAtDistance(new QuestEnv(object, getOwner(), 0, 0));
} else if (object instanceof Summon) {
Summon npc = ((Summon) object);
PacketSendUtility.sendPacket(getOwner(), new SM_NPC_INFO(npc, getOwner()));
if (!npc.getEffectController().isEmpty()) {
npc.getEffectController().sendEffectIconsTo(getOwner());
}
} else if (object instanceof Gatherable || object instanceof StaticObject) {
PacketSendUtility.sendPacket(getOwner(), new SM_GATHERABLE_INFO(object));
} else if (object instanceof Pet) {
PacketSendUtility.sendPacket(getOwner(), new SM_PET(3, (Pet) object));
}
}

@Override
public void notSee(VisibleObject object, boolean isOutOfRange) {
super.notSee(object, isOutOfRange);
if (object instanceof Pet) {
PacketSendUtility.sendPacket(getOwner(), new SM_PET(4, (Pet) object));
} else {
PacketSendUtility.sendPacket(getOwner(), new SM_DELETE(object, isOutOfRange ? 0 : 15));
}
}

public void updateNearbyQuests() {
HashMap<Integer, Integer> nearbyQuestList = new HashMap<>();
for (int questId : getOwner().getPosition().getMapRegion().getParent().getQuestIds()) {
int diff = 0;
if (questId <= 0xFFFF) {
diff = QuestService.getLevelRequirementDiff(questId, getOwner().getCommonData().getLevel());
}
if (diff <= 2 && QuestService.checkStartConditions(new QuestEnv(null, getOwner(), questId, 0), false)) {
nearbyQuestList.put(questId, diff);
}
}
PacketSendUtility.sendPacket(getOwner(), new SM_NEARBY_QUESTS(nearbyQuestList));
}

@Override
public void onEnterZone(ZoneInstance zone) {
Player player = getOwner();
if (!zone.canRide() && player.isInPlayerMode(PlayerMode.RIDE)) {
player.unsetPlayerMode(PlayerMode.RIDE);
}
InstanceService.onEnterZone(player, zone);
if (zone.getAreaTemplate().getZoneName() == null) {
log.error("No name found for a Zone in the map " + zone.getAreaTemplate().getWorldId());
} else {
QuestEngine.getInstance().onEnterZone(new QuestEnv(null, player, 0, 0), zone.getAreaTemplate().getZoneName());
}
}

@Override
public void onLeaveZone(ZoneInstance zone) {
Player player = getOwner();
InstanceService.onLeaveZone(player, zone);
ZoneName zoneName = zone.getAreaTemplate().getZoneName();
if (zoneName == null) {
log.warn("No name for zone template in " + zone.getAreaTemplate().getWorldId());
return;
}
QuestEngine.getInstance().onLeaveZone(new QuestEnv(null, player, 0, 0), zoneName);
}

/**
* {@inheritDoc} Should only be triggered from one place (life stats)
*/
// TODO [AT] move
public void onEnterWorld() {

InstanceService.onEnterInstance(getOwner());
if (getOwner().getPosition().getWorldMapInstance().getParent().isExceptBuff()) {
getOwner().getEffectController().removeAllEffects();
}

if (getOwner().getBattleGround() != null && getOwner().getWorldId() != getOwner().getBattleGround().getWorldId()) {
BattleGroundManager.unregisterPlayer(getOwner());
getOwner().battlegroundWaiting = false;
getOwner().setBattleGround(null);
}

for (Effect ef : getOwner().getEffectController().getAbnormalEffects()) {
if (ef.isDeityAvatar()) {
// remove abyss transformation if worldtype != abyss && worldtype != balaurea
if (getOwner().getWorldType() != WorldType.ABYSS && getOwner().getWorldType() != WorldType.BALAUREA || getOwner().isInInstance() || getOwner().getWorldId() == 600040000) {
ef.endEffect();
getOwner().getEffectController().clearEffect(ef);
}
} else if (ef.getSkillTemplate().getDispelCategory() == DispelCategoryType.NPC_BUFF) {
ef.endEffect();
getOwner().getEffectController().clearEffect(ef);
}
}
}

// TODO [AT] move
public void onLeaveWorld() {
SerialKillerService.getInstance().onLeaveMap(getOwner());
ArenaMasterService.getInstance().onLeaveInstance(getOwner());
InstanceService.onLeaveInstance(getOwner());
}

public void validateLoginZone() {
int mapId;
float x, y, z;
byte h;
boolean moveToBind = false;

BindPointPosition bind = getOwner().getBindPoint();

if (bind != null) {
mapId = bind.getMapId();
x = bind.getX();
y = bind.getY();
z = bind.getZ();
h = bind.getHeading();
} else {
PlayerInitialData.LocationData start = DataManager.PLAYER_INITIAL_DATA.getSpawnLocation(getOwner().getRace());

mapId = start.getMapId();
x = start.getX();
y = start.getY();
z = start.getZ();
h = start.getHeading();
}
if (!SiegeService.getInstance().validateLoginZone(getOwner())) {
moveToBind = true;
} else {
long lastOnline = getOwner().getCommonData().getLastOnline().getTime();
long secondsOffline = (System.currentTimeMillis() / 1000) - lastOnline / 1000;
if (secondsOffline > 10 * 60) { //Logout in no-recall zone sends you to bindpoint after 10 (??) minutes
for (ZoneInstance zone : getOwner().getPosition().getMapRegion().getZones(getOwner())) {
if (!zone.canRecall()) {
moveToBind = true;
break;
}
}
}
}

if (moveToBind) {
World.getInstance().setPosition(getOwner(), mapId, x, y, z, h);
}
}

public void onDie(@Nonnull Creature lastAttacker, boolean showPacket) {
Player player = this.getOwner();
player.getController().cancelCurrentSkill();
player.setRebirthRevive(getOwner().haveSelfRezEffect());
showPacket = player.hasResurrectBase() ? false : showPacket;
Creature master = lastAttacker.getMaster();

// crazy Daeva
if (EventSystem.ENABLE_CRAZY) {
if (((master instanceof Player)) && (master.getRace() != player.getRace())) {
CrazyDaevaService.getInstance().crazyOnDie(player, (Player) master, true);
}
}

// Battelground
if (master instanceof Player) {
if (((Player) master).getBattleGround() != null && ((Player) master).getBattleGround() instanceof AssaultBattleGround) {
((AssaultBattleGround) (((Player) master).getBattleGround())).onKillPlayer(player, (Player) master);
}
}
// 1 vs 1 Event
if (EventSystem.ENABLE_ONEVONE){
if (((master instanceof Player)) && ((Player) master).isInPkMode()){
for(int worldId : OneVsOneStruct.worldid){
if(master.getWorldId() == worldId){
ArenaMasterService.getInstance().onDie((Player) master, player);
}
}
}
}

// High ranked kill announce
AbyssRank ar = player.getAbyssRank();
if (AbyssService.isOnPvpMap(player) && ar != null) {
if (ar.getRank().getId() >= 10) {
AbyssService.rankedKillAnnounce(player);
}
}

if (DuelService.getInstance().isDueling(player.getObjectId())) {
if (master != null && DuelService.getInstance().isDueling(player.getObjectId(), master.getObjectId())) {
DuelService.getInstance().loseDuel(player);
player.getEffectController().removeAbnormalEffectsByTargetSlot(SkillTargetSlot.DEBUFF);
player.getLifeStats().setCurrentHpPercent(33);
player.getLifeStats().setCurrentMpPercent(33);
return;
}
DuelService.getInstance().loseDuel(player);
}

/**
* Release summon
*/
Summon summon = player.getSummon();
if (summon != null) {
SummonsService.doMode(SummonMode.RELEASE, summon, UnsummonType.UNSPECIFIED);
}

// setIsFlyingBeforeDead for PlayerReviveService
if (player.isInState(CreatureState.FLYING)) {
player.setIsFlyingBeforeDeath(true);
}

// ride
player.setPlayerMode(PlayerMode.RIDE, null);
player.unsetState(CreatureState.RESTING);
player.unsetState(CreatureState.FLOATING_CORPSE);

// unsetflying
player.unsetState(CreatureState.FLYING);
player.unsetState(CreatureState.GLIDING);
player.setFlyState(0);

if (player.isInInstance()) {
if (player.getPosition().getWorldMapInstance().getInstanceHandler().onDie(player, lastAttacker)) {
super.onDie(lastAttacker);
return;
}
}

MapRegion mapRegion = player.getPosition().getMapRegion();
if (mapRegion != null && mapRegion.onDie(lastAttacker, getOwner())) {
return;
}

this.doReward();

if (master instanceof Npc || master == player) {
if (player.getLevel() > 4 && !isNoDeathPenaltyInEffect())
player.getCommonData().calculateExpLoss();
}
// Effects removed with super.onDie()
super.onDie(lastAttacker);

//test it if bug (maybe not needed)
if (player.getBattleGround() != null && player.getBattleGround() instanceof CTFBattleGround && master instanceof Player) {
int tplId = player.getBattleGround().getTplId();
template = DataManager.BATTLEGROUND_DATA.getBattleGroundTemplate(tplId);
player.getBattleGround().increasePoints((Player) master, template.getRules().getKillPlayer());
}
if (player.battlegroundFlag != null) {
player.getBattleGround().broadcastToBattleGround(player.getCommonData().getName() + (player.getLegion() != null ? " de " + player.getLegion().getLegionName() : "") + " got the " + (player.battlegroundFlag.getRace() == Race.ELYOS ? "Elyséen" : "Asmodien") + " !", null);
if (master instanceof Player) {
player.getBattleGround().increasePoints((Player) master, template.getRules().getFlagBase());
}

player.battlegroundFlag.getController().dropped = true;
player.battlegroundFlag.setFlagHolder(null);
player.battlegroundFlag = null;
if (player.getController().getTask(TaskId.BATTLEGROUND_CARRY_FLAG) != null) {
player.getController().getTask(TaskId.BATTLEGROUND_CARRY_FLAG).cancel(true);
player.getController().addTask(TaskId.BATTLEGROUND_CARRY_FLAG, null);
}
}
player.getActionList().clearAll();

// send sm_emotion with DIE
// have to be send after state is updated!
sendDieFromCreature(lastAttacker, showPacket);

QuestEngine.getInstance().onDie(new QuestEnv(null, player, 0, 0));

if (player.isInGroup2()) {
player.getPlayerGroup2().sendPacket(SM_SYSTEM_MESSAGE.STR_MSG_COMBAT_FRIENDLY_DEATH(player.getName()), new ExcludePlayerFilter(player));
}
}

@Override
public void onDie(@Nonnull Creature lastAttacker) {
this.onDie(lastAttacker, true);
}

public void sendDie() {
sendDieFromCreature(getOwner(), true);
}

private void sendDieFromCreature(@Nonnull Creature lastAttacker, boolean showPacket) {
Player player = this.getOwner();

PacketSendUtility.broadcastPacket(player, new SM_EMOTION(player, EmotionType.DIE, 0, player.equals(lastAttacker) ? 0 : lastAttacker.getObjectId()), true);

if (showPacket) {
int kiskTimeRemaining = (player.getKisk() != null ? player.getKisk().getRemainingLifetime() : 0);
PacketSendUtility.sendPacket(player, new SM_DIE(player.canUseRebirthRevive(), player.haveSelfRezItem(), kiskTimeRemaining, 0, isInvader(player)));
}

PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_COMBAT_MY_DEATH);
}

private boolean isInvader(Player player) {
if (player.getRace().equals(Race.ASMODIANS)) {
return player.getWorldId() == 210060000;
} else {
return player.getWorldId() == 220050000;
}
}

@Override
public void doReward() {
PvpService.getInstance().doReward(getOwner());
}

@Override
public void onBeforeSpawn() {
this.onBeforeSpawn(true);
/*
super.onBeforeSpawn();
startProtectionActiveTask();
if (getOwner().getIsFlyingBeforeDeath()) {
getOwner().unsetState(CreatureState.FLOATING_CORPSE);
} else {
getOwner().unsetState(CreatureState.DEAD);
}
getOwner().setState(CreatureState.ACTIVE);
*/
}

public void onBeforeSpawn(boolean blink) {
super.onBeforeSpawn();
if (blink) {
startProtectionActiveTask();
}
if (getOwner().getIsFlyingBeforeDeath()) {
getOwner().unsetState(CreatureState.FLOATING_CORPSE);
} else {
getOwner().unsetState(CreatureState.DEAD);
}
getOwner().setState(CreatureState.ACTIVE);
}

@Override
public void attackTarget(Creature target, int time) {

PlayerGameStats gameStats = getOwner().getGameStats();

if (!RestrictionsManager.canAttack(getOwner(), target)) {
return;
}

// Normal attack is already limited client side (ex. Press C and attacker approaches target)
// but need a check server side too also for Z axis issue
if (!MathUtil.isInAttackRange(getOwner(), target, (float) (getOwner().getGameStats().getAttackRange().getCurrent() / 1000f) + 1)) {
return;
}

if (!GeoService.getInstance().canSee(getOwner(), target)) {
PacketSendUtility.sendPacket(getOwner(), SM_SYSTEM_MESSAGE.STR_ATTACK_OBSTACLE_EXIST);
return;
}

if (target instanceof Npc) {
QuestEngine.getInstance().onAttack(new QuestEnv(target, getOwner(), 0, 0));
}

int attackSpeed = gameStats.getAttackSpeed().getCurrent();

long milis = System.currentTimeMillis();
// network ping..
if (milis - lastAttackMilis + 300 < attackSpeed) {
// hack
return;
}
lastAttackMilis = milis;

/**
* notify attack observers
*/
super.attackTarget(target, time);

}

@Override
public void onAttack(Creature creature, int skillId, TYPE type, int damage, boolean notifyAttack, LOG log) {
if (getOwner().getLifeStats().isAlreadyDead()) {
return;
}

if (getOwner().isInvul() || getOwner().isProtectionActive()) {
damage = 0;
}

if (getOwner().getBattleGround() != null && !getOwner().getBattleGround().running) {
damage = 0;
}

if (getOwner().getActionList() != null) {
getOwner().getActionList().addDamage(creature, damage);
}

cancelUseItem();
cancelGathering();
super.onAttack(creature, skillId, type, damage, notifyAttack, log);

PacketSendUtility.broadcastPacket(getOwner(), new SM_ATTACK_STATUS(getOwner(), type, skillId, damage, log), true);

if (creature instanceof Npc) {
QuestEngine.getInstance().onAttack(new QuestEnv(creature, getOwner(), 0, 0));
}

lastAttackedMilis = System.currentTimeMillis();
}

/**
* @param skillId
* @param targetType
* @param x
* @param y
* @param z
*/
public void useSkill(int skillId, int targetType, float x, float y, float z, int time) {
Player player = getOwner();

Skill skill = SkillEngine.getInstance().getSkillFor(player, skillId, player.getTarget());

if (skill != null) {
if (!RestrictionsManager.canUseSkill(player, skill)) {
return;
}

skill.setTargetType(targetType, x, y, z);
skill.setHitTime(time);
skill.useSkill();
}
}

/**
* @param template
* @param targetType
* @param x
* @param y
* @param z
* @param clientHitTime
*/
public void useSkill(SkillTemplate template, int targetType, float x, float y, float z, int clientHitTime,
int skillLevel) {
Player player = getOwner();
Skill skill = null;
skill = SkillEngine.getInstance().getSkillFor(player, template, player.getTarget());
if (skill == null && player.isTransformed()) {
SkillPanel panel = DataManager.PANEL_SKILL_DATA.getSkillPanel(player.getTransformModel().getPanelId());
if (panel != null && panel.canUseSkill(template.getSkillId(), skillLevel)) {
skill = SkillEngine.getInstance().getSkillFor(player, template, player.getTarget(), skillLevel);
}
}

if (skill != null) {
if (!RestrictionsManager.canUseSkill(player, skill)) {
return;
}

skill.setTargetType(targetType, x, y, z);
skill.setHitTime(clientHitTime);
skill.useSkill();
}
}

@Override
public void onMove() {
getOwner().getObserveController().notifyMoveObservers();
super.onMove();
}

@Override
public void onStopMove() {
PlayerMoveTaskManager.getInstance().removePlayer(getOwner());
getOwner().getObserveController().notifyMoveObservers();
getOwner().getMoveController().setInMove(false);
cancelCurrentSkill();
updateZone();
super.onStopMove();
}

@Override
public void onStartMove() {
getOwner().getMoveController().setInMove(true);
PlayerMoveTaskManager.getInstance().addPlayer(getOwner());
cancelUseItem();
cancelCurrentSkill();
super.onStartMove();
}

@Override
public void cancelCurrentSkill() {
if (getOwner().getCastingSkill() == null) {
return;
}

Player player = getOwner();
Skill castingSkill = player.getCastingSkill();
castingSkill.cancelCast();
player.removeSkillCoolDown(castingSkill.getSkillTemplate().getCooldownId());
player.setCasting(null);
player.setNextSkillUse(0);
if (castingSkill.getSkillMethod() == SkillMethod.CAST || castingSkill.getSkillMethod() == SkillMethod.CHARGE) {
PacketSendUtility.broadcastPacket(player, new SM_SKILL_CANCEL(player, castingSkill.getSkillTemplate().getSkillId()), true);
PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_SKILL_CANCELED);
} else if (castingSkill.getSkillMethod() == SkillMethod.ITEM) {
PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_ITEM_CANCELED(new DescriptionId(castingSkill.getItemTemplate().getNameId())));
player.removeItemCoolDown(castingSkill.getItemTemplate().getUseLimits().getDelayId());
PacketSendUtility.broadcastPacket(player, new SM_ITEM_USAGE_ANIMATION(player.getObjectId(), castingSkill.getFirstTarget().getObjectId(), castingSkill.getItemObjectId(), castingSkill.getItemTemplate().getTemplateId(), 0, 3, 0), true);
}
}

@Override
public void cancelUseItem() {
Player player = getOwner();
Item usingItem = player.getUsingItem();
player.setUsingItem(null);
if (hasTask(TaskId.ITEM_USE)) {
cancelTask(TaskId.ITEM_USE);
PacketSendUtility.broadcastPacket(player, new SM_ITEM_USAGE_ANIMATION(player.getObjectId(), usingItem == null ? 0 : usingItem.getObjectId(), usingItem == null ? 0 : usingItem.getItemTemplate().getTemplateId(), 0, 3, 0), true);
}
}

public void cancelGathering() {
Player player = getOwner();
if (player.getTarget() instanceof Gatherable) {
Gatherable g = (Gatherable) player.getTarget();
g.getController().finishGathering(player);
}
}

public void updatePassiveStats() {
Player player = getOwner();
for (PlayerSkillEntry skillEntry : player.getSkillList().getAllSkills()) {
Skill skill = SkillEngine.getInstance().getSkillFor(player, skillEntry.getSkillId(), player.getTarget());
if (skill != null && skill.isPassive()) {
skill.useSkill();
}
}
}

@Override
public Player getOwner() {
return (Player) super.getOwner();
}

@Override
public void onRestore(HealType healType, int value) {
super.onRestore(healType, value);
switch (healType) {
case DP:
getOwner().getCommonData().addDp(value);
break;
default:
break;
}
}

/**
* @param player
* @return
*/
// TODO [AT] move to Player
public boolean isDueling(Player player) {
return DuelService.getInstance().isDueling(player.getObjectId(), getOwner().getObjectId());
}

// TODO [AT] rename or remove
public boolean isInShutdownProgress() {
return isInShutdownProgress;
}

// TODO [AT] rename or remove
public void setInShutdownProgress(boolean isInShutdownProgress) {
this.isInShutdownProgress = isInShutdownProgress;
}

@Override
public void onDialogSelect(int dialogId, Player player, int questId, int extendedRewardIndex) {
switch (dialogId) {
case 2:
PacketSendUtility.sendPacket(player, new SM_PRIVATE_STORE(getOwner().getStore(), player));
break;
}
}

public void upgradePlayer() {
Player player = getOwner();
byte level = player.getLevel();

PlayerStatsTemplate statsTemplate = DataManager.PLAYER_STATS_DATA.getTemplate(player);
player.setPlayerStatsTemplate(statsTemplate);

player.getLifeStats().synchronizeWithMaxStats();
player.getLifeStats().updateCurrentStats();

PacketSendUtility.broadcastPacket(player, new SM_LEVEL_UPDATE(player.getObjectId(), 0, level), true);

// Guides Html on level up
if (HTMLConfig.ENABLE_GUIDES) {
HTMLService.sendGuideHtml(player);
}

// Temporal
ClassChangeService.showClassChangeDialog(player);

QuestEngine.getInstance().onLvlUp(new QuestEnv(null, player, 0, 0));
updateNearbyQuests();

// add new skills
SkillLearnService.addNewSkills(player);

PacketSendUtility.broadcastPacket(player, new SM_PACKAGE_INFO_NOTIFY(0), true);

player.getController().updatePassiveStats();

// add recipe for morph
if (level == 10) {
CraftSkillUpdateService.getInstance().setMorphRecipe(player);
}

if (player.isInTeam()) {
TeamEffectUpdater.getInstance().startTask(player);
}
if (player.isLegionMember()) {
LegionService.getInstance().updateMemberInfo(player);
}
player.getNpcFactions().onLevelUp();
PacketSendUtility.sendPacket(player, new SM_STATS_INFO(player));
}

/**
* After entering game player char is "blinking" which means that it's in
* under some protection, after making an action char stops blinking. -
* Starts protection active - Schedules task to end protection
*/
public void startProtectionActiveTask() {
if (!getOwner().isProtectionActive()) {
getOwner().setVisualState(CreatureVisualState.BLINKING);
AttackUtil.cancelCastOn((Creature) getOwner());
AttackUtil.removeTargetFrom((Creature) getOwner());
PacketSendUtility.broadcastPacket(getOwner(), new SM_PLAYER_STATE(getOwner()), true);
Future<?> task = ThreadPoolManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
stopProtectionActiveTask();
}
}, 60000);
addTask(TaskId.PROTECTION_ACTIVE, task);
}
}

/**
* Stops protection active task after first move or use skill
*/
public void stopProtectionActiveTask() {
cancelTask(TaskId.PROTECTION_ACTIVE);
Player player = getOwner();
if (player != null && player.isSpawned()) {
player.unsetVisualState(CreatureVisualState.BLINKING);
PacketSendUtility.broadcastPacket(player, new SM_PLAYER_STATE(player), true);
notifyAIOnMove();
}
}

/**
* When player arrives at destination point of flying teleport
*/
public void onFlyTeleportEnd() {
Player player = getOwner();
if (player.isInPlayerMode(PlayerMode.WINDSTREAM)) {
player.unsetPlayerMode(PlayerMode.WINDSTREAM);
player.getLifeStats().triggerFpReduce();
player.unsetState(CreatureState.FLYING);
player.setState(CreatureState.ACTIVE);
player.setState(CreatureState.GLIDING);
player.getGameStats().updateStatsAndSpeedVisually();
} else {
player.unsetState(CreatureState.FLIGHT_TELEPORT);
player.setFlightTeleportId(0);

if (SecurityConfig.ENABLE_FLYPATH_VALIDATOR) {
long diff = (System.currentTimeMillis() - player.getFlyStartTime());
FlyPathEntry path = player.getCurrentFlyPath();

if (player.getWorldId() != path.getEndWorldId()) {
AuditLogger.info(player, "Player tried to use flyPath #" + path.getId() + " from not native start world "
+ player.getWorldId() + ". expected " + path.getEndWorldId());
}

if (diff < path.getTimeInMs()) {
AuditLogger.info(player,
"Player " + player.getName() + " used flypath bug " + diff + " instead of " + path.getTimeInMs());
/*
* todo if works teleport player to start_* xyz, or even ban
*/
}

player.setCurrentFlypath(null);
}

player.setFlightDistance(0);
player.setState(CreatureState.ACTIVE);
updateZone();
}
}

public boolean addItems(int itemId, int count) {
return ItemService.addQuestItems(getOwner(), Collections.singletonList(new QuestItems(itemId, count)));
}

public void startStance(final int skillId) {
stance = skillId;
}

public void stopStance() {
getOwner().getEffectController().removeEffect(stance);
PacketSendUtility.sendPacket(getOwner(), new SM_PLAYER_STANCE(getOwner(), 0));
stance = 0;
}

public int getStanceSkillId() {
return stance;
}

public boolean isUnderStance() {
return stance != 0;
}

public void updateSoulSickness(int skillId) {
Player player = getOwner();
House house = player.getActiveHouse();
if (house != null) {
switch (house.getHouseType()) {
case MANSION:
case ESTATE:
case PALACE:
return;
default:
break;
}
}

if (!player.havePermission(MembershipConfig.DISABLE_SOULSICKNESS)) {
int deathCount = player.getCommonData().getDeathCount();
if (deathCount < 10) {
deathCount++;
player.getCommonData().setDeathCount(deathCount);
}

if (skillId == 0) {
skillId = 8291;
}
SkillEngine.getInstance().getSkill(player, skillId, deathCount, player).useSkill();
}
}

/**
* Player is considered in combat if he's been attacked or has attacked less
* or equal 10s before
*
* @return true if the player is actively in combat
*/
public boolean isInCombat() {
return (((System.currentTimeMillis() - lastAttackedMilis) <= 10000) || ((System.currentTimeMillis() - lastAttackMilis) <= 10000));
}

/**
* Check if NoDeathPenalty is active
*
* @param player
* @return boolean
*/
public boolean isNoDeathPenaltyInEffect() {
// Check if NoDeathPenalty is active
Iterator<Effect> iterator = getOwner().getEffectController().iterator();
while (iterator.hasNext()) {
Effect effect = iterator.next();
if (effect.isNoDeathPenalty()) {
return true;
}
}
return false;
}

/**
* Check if NoResurrectPenalty is active
*
* @param player
* @return boolean
*/
public boolean isNoResurrectPenaltyInEffect() {
// Check if NoResurrectPenalty is active
Iterator<Effect> iterator = getOwner().getEffectController().iterator();
while (iterator.hasNext()) {
Effect effect = iterator.next();
if (effect.isNoResurrectPenalty()) {
return true;
}
}
return false;
}

/**
* Check if HiPass is active
*
* @param player
* @return boolean
*/
public boolean isHiPassInEffect() {
// Check if HiPass is active
Iterator<Effect> iterator = getOwner().getEffectController().iterator();
while (iterator.hasNext()) {
Effect effect = iterator.next();
if (effect.isHiPass()) {
return true;
}
}
return false;
}

public void registerListener(Listener listener) {
this.mListener = listener;
}

public void unregisterListener() {
this.mListener = null;
}

public static abstract interface Listener {
public abstract void onPlayerUsedSkill(int paramInt, Player paramPlayer);
}
}

PlayerController method inDie. Add comment custom event and check die mode
[DOUBLEPOST=1563225562][/DOUBLEPOST]
PvpService és a Player Controller

Sorry, I can't find the error:

PvpService.java

package com.aionemu.gameserver.services;

import java.util.ArrayList;
import java.util.List;

import javolution.util.FastMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aionemu.commons.utils.Rnd;
import com.aionemu.gameserver.configs.main.CustomConfig;
import com.aionemu.gameserver.configs.main.EventSystem;
import com.aionemu.gameserver.configs.main.GroupConfig;
import com.aionemu.gameserver.configs.main.LoggingConfig;
import com.aionemu.gameserver.configs.main.PunishmentConfig;
import com.aionemu.gameserver.controllers.attack.AggroInfo;
import com.aionemu.gameserver.controllers.attack.KillList;
import com.aionemu.gameserver.eventEngine.crazy_daeva.CrazyDaevaService;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.player.RewardType;
import com.aionemu.gameserver.model.ingameshop.InGameShopEn;
import com.aionemu.gameserver.model.team2.alliance.PlayerAlliance;
import com.aionemu.gameserver.model.team2.group.PlayerGroup;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.questEngine.QuestEngine;
import com.aionemu.gameserver.questEngine.model.QuestEnv;
import com.aionemu.gameserver.services.abyss.AbyssPointsService;
import com.aionemu.gameserver.services.item.ItemService;
import com.aionemu.gameserver.utils.MathUtil;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.audit.AuditLogger;
import com.aionemu.gameserver.utils.stats.AbyssRankEnum;
import com.aionemu.gameserver.utils.stats.StatFunctions;

/**
* @author Sarynth
*/
public class PvpService {

private static Logger log = LoggerFactory.getLogger("KILL_LOG");

public static final PvpService getInstance() {
return SingletonHolder.instance;
}

private FastMap<Integer, KillList> pvpKillLists;

private PvpService() {
pvpKillLists = new FastMap<Integer, KillList>();
}

/**
* @param winnerId
* @param victimId
* @return
*/
private int getKillsFor(int winnerId, int victimId) {
KillList winnerKillList = pvpKillLists.get(winnerId);

if (winnerKillList == null) {
return 0;
}
return winnerKillList.getKillsFor(victimId);
}

/**
* @param winnerId
* @param victimId
*/
private void addKillFor(int winnerId, int victimId) {
KillList winnerKillList = pvpKillLists.get(winnerId);
if (winnerKillList == null) {
winnerKillList = new KillList();
pvpKillLists.put(winnerId, winnerKillList);
}
winnerKillList.addKillFor(victimId);
}

/**
* @param victim
*/
public void doReward(Player victim) {
// winner is the player that receives the kill count
final Player winner = victim.getAggroList().getMostPlayerDamage();

int totalDamage = victim.getAggroList().getTotalDamage();

if (totalDamage == 0 || winner == null || winner.getRace() == victim.getRace()) {
return;
}

if (victim.getBattleGround() != null) {
return;
}

// Add Player Kill to record.
if (this.getKillsFor(winner.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
winner.getAbyssRank().setAllKill();
int kills = winner.getAbyssRank().getAllKill();
// Pvp Kill Reward.
if (CustomConfig.ENABLE_KILL_REWARD) {
if (kills % CustomConfig.KILLS_NEEDED1 == 1) {
ItemService.addItem(winner, CustomConfig.REWARD1, 1);
PacketSendUtility.sendMessage(winner, "Congratulations, you have won " + "[item: " + CustomConfig.REWARD1
+ "] for having killed " + CustomConfig.KILLS_NEEDED1 + " players !");
log.info("[REWARD] Player [" + winner.getName() + "] win 2 [" + CustomConfig.REWARD1 + "]");
}
if (kills % CustomConfig.KILLS_NEEDED2 == 3) {
ItemService.addItem(winner, CustomConfig.REWARD2, 1);
PacketSendUtility.sendMessage(winner, "Congratulations, you have won " + "[item: " + CustomConfig.REWARD2
+ "] for having killed " + CustomConfig.KILLS_NEEDED2 + " players !");
log.info("[REWARD] Player [" + winner.getName() + "] win 4 [" + CustomConfig.REWARD2 + "]");
}
if (kills % CustomConfig.KILLS_NEEDED3 == 5) {
ItemService.addItem(winner, CustomConfig.REWARD3, 1);
PacketSendUtility.sendMessage(winner, "Congratulations, you have won " + "[item: " + CustomConfig.REWARD3
+ "] for having killed " + CustomConfig.KILLS_NEEDED3 + " players !");
log.info("[REWARD] Player [" + winner.getName() + "] win 6 [" + CustomConfig.REWARD3 + "]");
}
}
// PvP Toll Reward
if (CustomConfig.ENABLE_TOLL_REWARD) {
if (Rnd.get(0, 100) > CustomConfig.TOLL_CHANCE){
InGameShopEn.getInstance().addToll(winner, CustomConfig.TOLL_QUANTITY);
PacketSendUtility.sendMessage(winner, "You've recived " + CustomConfig.TOLL_QUANTITY + " tolls from PvP!");
}
}
}

//Crazy kill
if (EventSystem.ENABLE_CRAZY) {
if (winner.getRndCrazy() >= EventSystem.CRAZY_LOWEST_RND) {
AbyssPointsService.addAp(winner, 500);
AbyssPointsService.addGp(winner, 20);
}
}

// Announce that player has died.
PacketSendUtility.broadcastPacketAndReceive(victim, SM_SYSTEM_MESSAGE.STR_MSG_COMBAT_FRIENDLY_DEATH_TO_B(victim.getName(), winner.getName()));

// Pvp Kill Reward.
int reduceap = PunishmentConfig.PUNISHMENT_REDUCEAP;
if (reduceap < 0) {
reduceap *= -1;
}
if (reduceap > 100) {
reduceap = 100;
}

//Kill-log
if (LoggingConfig.LOG_KILL) {
log.info("[KILL] Player [" + winner.getName() + "] killed [" + victim.getName() + "]");
}

if ((LoggingConfig.LOG_PL) || (reduceap > 0)) {
String ip1 = winner.getClientConnection().getIP();
String mac1 = winner.getClientConnection().getMacAddress();
String ip2 = victim.getClientConnection().getIP();
String mac2 = victim.getClientConnection().getMacAddress();
if ((mac1 != null) && (mac2 != null)) {
if ((ip1.equalsIgnoreCase(ip2)) && (mac1.equalsIgnoreCase(mac2))) {
AuditLogger.info(winner, "Power Leveling : " + winner.getName() + " with " + victim.getName() + ", They have the sames ip=" + ip1 + " and mac=" + mac1 + ".");
if (reduceap > 0) {
int win_ap = winner.getAbyssRank().getAp() * reduceap / 100;
int vic_ap = victim.getAbyssRank().getAp() * reduceap / 100;
AbyssPointsService.addAp(winner, -win_ap);
AbyssPointsService.addAp(victim, -vic_ap);
PacketSendUtility.sendMessage(winner, "[PL-AP] You lost " + reduceap + "% of your total ap");
PacketSendUtility.sendMessage(victim, "[PL-AP] You lost " + reduceap + "% of your total ap");
}
return;
}
if (ip1.equalsIgnoreCase(ip2)) {
AuditLogger.info(winner, "Possible Power Leveling : " + winner.getName() + " with " + victim.getName() + ", They have the sames ip=" + ip1 + ".");
AuditLogger.info(winner, "Check if " + winner.getName() + " and " + victim.getName() + " are Brothers-Sisters-Lovers-dogs-cats...");
}
}
}

// Keep track of how much damage was dealt by players
// so we can remove AP based on player damage...
int playerDamage = 0;
boolean success;

// Distribute AP to groups and players that had damage.
for (AggroInfo aggro : victim.getAggroList().getFinalDamageList(true)) {
success = false;
if (aggro.getAttacker() instanceof Player) {
success = rewardPlayer(victim, totalDamage, aggro);
} else if (aggro.getAttacker() instanceof PlayerGroup) {
success = rewardPlayerGroup(victim, totalDamage, aggro);
} else if (aggro.getAttacker() instanceof PlayerAlliance) {
success = rewardPlayerAlliance(victim, totalDamage, aggro);
}

// Add damage last, so we don't include damage from same race. (Duels, Arena)
if (success) {
playerDamage += aggro.getDamage();
}
}

SerialKillerService.getInstance().updateRank(winner, victim);

//notify Quest engine for winner + his group
notifyKillQuests(winner, victim);

// Apply lost AP to defeated player
final int apLost = StatFunctions.calculatePvPApLost(victim, winner);
final int apActuallyLost = (int) (apLost * playerDamage / totalDamage);

if (apActuallyLost > 0) {
AbyssPointsService.addAp(victim, -apActuallyLost);
}
}

/**
* @param victim
* @param totalDamage
* @param aggro
* @return true if group is not same race
*/
private boolean rewardPlayerGroup(Player victim, int totalDamage, AggroInfo aggro) {
// Reward Group
PlayerGroup group = ((PlayerGroup) aggro.getAttacker());

// Don't Reward Player of Same Faction.
if (group.getRace() == victim.getRace()) {
return false;
}

// Find group members in range
List<Player> players = new ArrayList<Player>();

// Find highest rank and level in local group
int maxRank = AbyssRankEnum.GRADE9_SOLDIER.getId();
int maxLevel = 0;

for (Player member : group.getMembers()) {
if (MathUtil.isIn3dRange(member, victim, GroupConfig.GROUP_MAX_DISTANCE)) {
// Don't distribute AP to a dead player!
if (!member.getLifeStats().isAlreadyDead()) {
players.add(member);
if (member.getLevel() > maxLevel) {
maxLevel = member.getLevel();
}
if (member.getAbyssRank().getRank().getId() > maxRank) {
maxRank = member.getAbyssRank().getRank().getId();
}
}
}
}

// They are all dead or out of range.
if (players.isEmpty()) {
return false;
}

int baseApReward = StatFunctions.calculatePvpApGained(victim, maxRank, maxLevel);
int baseXpReward = StatFunctions.calculatePvpXpGained(victim, maxRank, maxLevel);
int baseDpReward = StatFunctions.calculatePvpDpGained(victim, maxRank, maxLevel);
float groupPercentage = (float) aggro.getDamage() / totalDamage;
int apRewardPerMember = Math.round(baseApReward * groupPercentage / players.size());
int xpRewardPerMember = Math.round(baseXpReward * groupPercentage / players.size());
int dpRewardPerMember = Math.round(baseDpReward * groupPercentage / players.size());

for (Player member : players) {
int memberApGain = 1;
int memberXpGain = 1;
int memberDpGain = 1;
if (this.getKillsFor(member.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
if (apRewardPerMember > 0) {
memberApGain = Math.round(RewardType.AP_PLAYER.calcReward(member, apRewardPerMember));
}
if (xpRewardPerMember > 0) {
memberXpGain = Math.round(xpRewardPerMember * member.getRates().getXpPlayerGainRate());
}
if (dpRewardPerMember > 0) {
memberDpGain = Math.round(StatFunctions.adjustPvpDpGained(dpRewardPerMember, victim.getLevel(), member.getLevel()) * member.getRates().getDpPlayerRate());
}

}
Player partner = member.findPartner();
if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
AbyssPointsService.addAp(member, victim, memberApGain + (memberApGain * 20 / 100)); //20% more AP for weddings
} else {
AbyssPointsService.addAp(member, victim, memberApGain);
}
member.getCommonData().addExp(memberXpGain, RewardType.PVP_KILL, victim.getName());
member.getCommonData().addEventExp(memberXpGain);
member.getCommonData().addDp(memberDpGain);
this.addKillFor(member.getObjectId(), victim.getObjectId());
}

return true;
}

/**
* @param victim
* @param totalDamage
* @param aggro
* @return true if group is not same race
*/
private boolean rewardPlayerAlliance(Player victim, int totalDamage, AggroInfo aggro) {
// Reward Alliance
PlayerAlliance alliance = ((PlayerAlliance) aggro.getAttacker());

// Don't Reward Player of Same Faction.
if (alliance.getLeaderObject().getRace() == victim.getRace()) {
return false;
}

// Find group members in range
List<Player> players = new ArrayList<Player>();

// Find highest rank and level in local group
int maxRank = AbyssRankEnum.GRADE9_SOLDIER.getId();
int maxLevel = 0;

for (Player member : alliance.getMembers()) {
if (!member.isOnline()) {
continue;
}
if (MathUtil.isIn3dRange(member, victim, GroupConfig.GROUP_MAX_DISTANCE)) {
// Don't distribute AP to a dead player!
if (!member.getLifeStats().isAlreadyDead()) {
players.add(member);
if (member.getLevel() > maxLevel) {
maxLevel = member.getLevel();
}
if (member.getAbyssRank().getRank().getId() > maxRank) {
maxRank = member.getAbyssRank().getRank().getId();
}
}
}
}

// They are all dead or out of range.
if (players.isEmpty()) {
return false;
}

int baseApReward = StatFunctions.calculatePvpApGained(victim, maxRank, maxLevel);
int baseXpReward = StatFunctions.calculatePvpXpGained(victim, maxRank, maxLevel);
int baseDpReward = StatFunctions.calculatePvpDpGained(victim, maxRank, maxLevel);
float groupPercentage = (float) aggro.getDamage() / totalDamage;
int apRewardPerMember = Math.round(baseApReward * groupPercentage / players.size());
int xpRewardPerMember = Math.round(baseXpReward * groupPercentage / players.size());
int dpRewardPerMember = Math.round(baseDpReward * groupPercentage / players.size());

for (Player member : players) {
int memberApGain = 1;
int memberXpGain = 1;
int memberDpGain = 1;
if (this.getKillsFor(member.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
if (apRewardPerMember > 0) {
memberApGain = Math.round(RewardType.AP_PLAYER.calcReward(member, apRewardPerMember));
}
if (xpRewardPerMember > 0) {
memberXpGain = Math.round(xpRewardPerMember * member.getRates().getXpPlayerGainRate());
}
if (dpRewardPerMember > 0) {
memberDpGain = Math.round(StatFunctions.adjustPvpDpGained(dpRewardPerMember, victim.getLevel(), member.getLevel()) * member.getRates().getDpPlayerRate());
}
}
AbyssPointsService.addAp(member, victim, memberApGain);
member.getCommonData().addExp(memberXpGain, RewardType.PVP_KILL, victim.getName());
member.getCommonData().addEventExp(memberXpGain);
member.getCommonData().addDp(memberDpGain);

this.addKillFor(member.getObjectId(), victim.getObjectId());
}

return true;
}

/**
* @param victim
* @param totalDamage
* @param aggro
* @return true if player is not same race
*/
private boolean rewardPlayer(Player victim, int totalDamage, AggroInfo aggro) {
// Reward Player
Player winner = ((Player) aggro.getAttacker());

// Don't Reward Player out of range/dead/same faction
if (winner.getRace() == victim.getRace() || !MathUtil.isIn3dRange(winner, victim, GroupConfig.GROUP_MAX_DISTANCE) || winner.getLifeStats().isAlreadyDead()) {
return false;
}

int baseApReward = 1;
int baseXpReward = 1;
int baseDpReward = 1;

if (this.getKillsFor(winner.getObjectId(), victim.getObjectId()) < CustomConfig.MAX_DAILY_PVP_KILLS) {
baseApReward = StatFunctions.calculatePvpApGained(victim, winner.getAbyssRank().getRank().getId(), winner.getLevel());
baseXpReward = StatFunctions.calculatePvpXpGained(victim, winner.getAbyssRank().getRank().getId(), winner.getLevel());
baseDpReward = StatFunctions.calculatePvpDpGained(victim, winner.getAbyssRank().getRank().getId(), winner.getLevel());
if (EventSystem.ENABLE_CRAZY) {
if (winner.getRace() != victim.getRace()) {
CrazyDaevaService.getInstance().increaseRawKillCount(winner);
}
}
}

int apPlayerReward = Math.round(baseApReward * aggro.getDamage() / totalDamage);
apPlayerReward = (int) RewardType.AP_PLAYER.calcReward(winner, apPlayerReward);
int xpPlayerReward = Math.round(baseXpReward * winner.getRates().getXpPlayerGainRate() * aggro.getDamage() / totalDamage);
int dpPlayerReward = Math.round(baseDpReward * winner.getRates().getDpPlayerRate() * aggro.getDamage() / totalDamage);

AbyssPointsService.addAp(winner, victim, apPlayerReward);
winner.getCommonData().addExp(xpPlayerReward, RewardType.PVP_KILL, victim.getName());
winner.getCommonData().addEventExp(xpPlayerReward);
winner.getCommonData().addDp(dpPlayerReward);
this.addKillFor(winner.getObjectId(), victim.getObjectId());
return true;
}

private void notifyKillQuests(Player winner, Player victim) {
if (winner.getRace() == victim.getRace()) {
return;
}

List<Player> rewarded = new ArrayList<Player>();
int worldId = victim.getWorldId();

if (winner.isInGroup2()) {
rewarded.addAll(winner.getPlayerGroup2().getOnlineMembers());
} else if (winner.isInAlliance2()) {
rewarded.addAll(winner.getPlayerAllianceGroup2().getOnlineMembers());
} else {
rewarded.add(winner);
}

for (Player p : rewarded) {
if (!MathUtil.isIn3dRange(p, victim, GroupConfig.GROUP_MAX_DISTANCE) || p.getLifeStats().isAlreadyDead()) {
continue;
}

QuestEngine.getInstance().onKillInWorld(new QuestEnv(victim, p, 0, 0), worldId);
QuestEngine.getInstance().onKillRanked(new QuestEnv(victim, p, 0, 0), victim.getAbyssRank().getRank());
}
rewarded.clear();
}

@SuppressWarnings("synthetic-access")
private static class SingletonHolder {

protected static final PvpService instance = new PvpService();
}
}

-------------------------------------------------------
PlayerController.java

package com.aionemu.gameserver.controllers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.Future;

import com.aionemu.gameserver.ai2.manager.LookManager;
import com.aionemu.gameserver.configs.main.EventSystem;
import com.aionemu.gameserver.configs.main.HTMLConfig;
import com.aionemu.gameserver.configs.main.MembershipConfig;
import com.aionemu.gameserver.configs.main.SecurityConfig;
import com.aionemu.gameserver.controllers.attack.AttackUtil;
import com.aionemu.gameserver.dataholders.DataManager;
import com.aionemu.gameserver.dataholders.PlayerInitialData;
import com.aionemu.gameserver.eventEngine.battleground.model.templates.BattleGroundTemplate;
import com.aionemu.gameserver.eventEngine.battleground.services.battleground.AssaultBattleGround;
import com.aionemu.gameserver.eventEngine.battleground.services.battleground.BattleGroundManager;
import com.aionemu.gameserver.eventEngine.battleground.services.battleground.CTFBattleGround;
import com.aionemu.gameserver.eventEngine.crazy_daeva.CrazyDaevaService;
import com.aionemu.gameserver.model.DescriptionId;
import com.aionemu.gameserver.model.EmotionType;
import com.aionemu.gameserver.model.Race;
import com.aionemu.gameserver.model.TaskId;
import com.aionemu.gameserver.model.actions.PlayerMode;
import com.aionemu.gameserver.model.gameobjects.Kisk;
import com.aionemu.gameserver.model.gameobjects.Npc;
import com.aionemu.gameserver.model.gameobjects.Summon;
import com.aionemu.gameserver.model.gameobjects.VisibleObject;
import com.aionemu.gameserver.model.gameobjects.Item;
import com.aionemu.gameserver.model.gameobjects.Creature;
import com.aionemu.gameserver.model.gameobjects.Pet;
import com.aionemu.gameserver.model.gameobjects.Gatherable;
import com.aionemu.gameserver.model.gameobjects.StaticObject;
import com.aionemu.gameserver.model.gameobjects.player.AbyssRank;
import com.aionemu.gameserver.model.gameobjects.player.BindPointPosition;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.state.CreatureState;
import com.aionemu.gameserver.model.gameobjects.state.CreatureVisualState;
import com.aionemu.gameserver.model.house.House;
import com.aionemu.gameserver.model.skill.PlayerSkillEntry;
import com.aionemu.gameserver.model.stats.container.PlayerGameStats;
import com.aionemu.gameserver.model.summons.SummonMode;
import com.aionemu.gameserver.model.summons.UnsummonType;
import com.aionemu.gameserver.model.team2.group.PlayerFilters.ExcludePlayerFilter;
import com.aionemu.gameserver.model.templates.flypath.FlyPathEntry;
import com.aionemu.gameserver.model.templates.panels.SkillPanel;
import com.aionemu.gameserver.model.templates.quest.QuestItems;
import com.aionemu.gameserver.model.templates.stats.PlayerStatsTemplate;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EMOTION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PET;
import com.aionemu.gameserver.network.aion.serverpackets.SM_MOTION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_NPC_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_KISK_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_EMOTION_SWITCH;
import com.aionemu.gameserver.network.aion.serverpackets.SM_HEADING_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_GATHERABLE_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_DELETE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_NEARBY_QUESTS;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SYSTEM_MESSAGE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_DIE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ATTACK_STATUS;
import com.aionemu.gameserver.network.aion.serverpackets.SM_SKILL_CANCEL;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ITEM_USAGE_ANIMATION;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PRIVATE_STORE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_LEVEL_UPDATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PACKAGE_INFO_NOTIFY;
import com.aionemu.gameserver.network.aion.serverpackets.SM_STATS_INFO;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_STATE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_PLAYER_STANCE;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ATTACK_STATUS.LOG;
import com.aionemu.gameserver.network.aion.serverpackets.SM_ATTACK_STATUS.TYPE;
import com.aionemu.gameserver.questEngine.QuestEngine;
import com.aionemu.gameserver.questEngine.model.QuestEnv;
import com.aionemu.gameserver.restrictions.RestrictionsManager;
import com.aionemu.gameserver.services.QuestService;
import com.aionemu.gameserver.services.SerialKillerService;
import com.aionemu.gameserver.services.SiegeService;
import com.aionemu.gameserver.services.DuelService;
import com.aionemu.gameserver.services.PvpService;
import com.aionemu.gameserver.services.HTMLService;
import com.aionemu.gameserver.services.ClassChangeService;
import com.aionemu.gameserver.services.SkillLearnService;
import com.aionemu.gameserver.services.LegionService;
import com.aionemu.gameserver.services.abyss.AbyssService;
import com.aionemu.gameserver.services.craft.CraftSkillUpdateService;
import com.aionemu.gameserver.services.ecfunctions.oneVsone.ArenaMasterService;
import com.aionemu.gameserver.services.ecfunctions.oneVsone.OneVsOneStruct;
import com.aionemu.gameserver.services.instance.InstanceService;
import com.aionemu.gameserver.services.item.ItemService;
import com.aionemu.gameserver.services.summons.SummonsService;
import com.aionemu.gameserver.skillengine.SkillEngine;
import com.aionemu.gameserver.skillengine.model.Effect;
import com.aionemu.gameserver.skillengine.model.DispelCategoryType;
import com.aionemu.gameserver.skillengine.model.SkillTargetSlot;
import com.aionemu.gameserver.skillengine.model.Skill;
import com.aionemu.gameserver.skillengine.model.SkillTemplate;
import com.aionemu.gameserver.skillengine.model.HealType;
import com.aionemu.gameserver.skillengine.model.Skill.SkillMethod;
import com.aionemu.gameserver.taskmanager.tasks.PlayerMoveTaskManager;
import com.aionemu.gameserver.taskmanager.tasks.TeamEffectUpdater;
import com.aionemu.gameserver.utils.MathUtil;
import com.aionemu.gameserver.utils.PacketSendUtility;
import com.aionemu.gameserver.utils.ThreadPoolManager;
import com.aionemu.gameserver.utils.audit.AuditLogger;
import com.aionemu.gameserver.world.MapRegion;
import com.aionemu.gameserver.world.World;
import com.aionemu.gameserver.world.WorldType;
import com.aionemu.gameserver.world.geo.GeoService;
import com.aionemu.gameserver.world.zone.ZoneInstance;
import com.aionemu.gameserver.world.zone.ZoneName;

/**
* This class is for controlling players.
*
* @author -Nemesiss-, ATracer, xavier, Sarynth, RotO, xTz, KID, Sippolo
*/
public class PlayerController extends CreatureController<Player> {

private Logger log = LoggerFactory.getLogger(PlayerController.class);
private boolean isInShutdownProgress;
private long lastAttackMilis = 0;
private long lastAttackedMilis = 0;
private int stance = 0;
@SuppressWarnings("unused")
private Listener mListener;
protected BattleGroundTemplate template;

@Override
public void see(VisibleObject object) {
super.see(object);
if (object instanceof Player) {
Player player = (Player) object;
PacketSendUtility.sendPacket(getOwner(), new SM_PLAYER_INFO(player, getOwner().isAggroIconTo(player)));
PacketSendUtility.sendPacket(getOwner(), new SM_MOTION(player.getObjectId(), player.getMotions().getActiveMotions()));
if (player.isInPlayerMode(PlayerMode.RIDE)) {
PacketSendUtility.sendPacket(getOwner(), new SM_EMOTION(player, EmotionType.RIDE, 0, player.ride.getNpcId()));
}
if (player.getPet() != null) {
LoggerFactory.getLogger(PlayerController.class).debug("Player " + getOwner().getName() + " sees " + object.getName() + " that has toypet");
PacketSendUtility.sendPacket(getOwner(), new SM_PET(3, player.getPet()));
}
player.getEffectController().sendEffectIconsTo(getOwner());
} else if (object instanceof Kisk) {
Kisk kisk = ((Kisk) object);
PacketSendUtility.sendPacket(getOwner(), new SM_NPC_INFO(kisk, getOwner()));
if (getOwner().getRace() == kisk.getOwnerRace()) {
PacketSendUtility.sendPacket(getOwner(), new SM_KISK_UPDATE(kisk));
}
} else if (object instanceof Npc) {
Npc npc = ((Npc) object);
LookManager.corrigateHeading(npc, this.getOwner());
PacketSendUtility.sendPacket(getOwner(), new SM_NPC_INFO(npc, getOwner()));
PacketSendUtility.sendPacket(getOwner(), new SM_EMOTION_SWITCH(npc, npc.getState(), EmotionType.SELECT_TARGET));
PacketSendUtility.sendPacket(getOwner(), new SM_HEADING_UPDATE(object.getObjectId(), (byte) object.getHeading()));
if (!npc.getEffectController().isEmpty()) {
npc.getEffectController().sendEffectIconsTo(getOwner());
}
QuestEngine.getInstance().onAtDistance(new QuestEnv(object, getOwner(), 0, 0));
} else if (object instanceof Summon) {
Summon npc = ((Summon) object);
PacketSendUtility.sendPacket(getOwner(), new SM_NPC_INFO(npc, getOwner()));
if (!npc.getEffectController().isEmpty()) {
npc.getEffectController().sendEffectIconsTo(getOwner());
}
} else if (object instanceof Gatherable || object instanceof StaticObject) {
PacketSendUtility.sendPacket(getOwner(), new SM_GATHERABLE_INFO(object));
} else if (object instanceof Pet) {
PacketSendUtility.sendPacket(getOwner(), new SM_PET(3, (Pet) object));
}
}

@Override
public void notSee(VisibleObject object, boolean isOutOfRange) {
super.notSee(object, isOutOfRange);
if (object instanceof Pet) {
PacketSendUtility.sendPacket(getOwner(), new SM_PET(4, (Pet) object));
} else {
PacketSendUtility.sendPacket(getOwner(), new SM_DELETE(object, isOutOfRange ? 0 : 15));
}
}

public void updateNearbyQuests() {
HashMap<Integer, Integer> nearbyQuestList = new HashMap<>();
for (int questId : getOwner().getPosition().getMapRegion().getParent().getQuestIds()) {
int diff = 0;
if (questId <= 0xFFFF) {
diff = QuestService.getLevelRequirementDiff(questId, getOwner().getCommonData().getLevel());
}
if (diff <= 2 && QuestService.checkStartConditions(new QuestEnv(null, getOwner(), questId, 0), false)) {
nearbyQuestList.put(questId, diff);
}
}
PacketSendUtility.sendPacket(getOwner(), new SM_NEARBY_QUESTS(nearbyQuestList));
}

@Override
public void onEnterZone(ZoneInstance zone) {
Player player = getOwner();
if (!zone.canRide() && player.isInPlayerMode(PlayerMode.RIDE)) {
player.unsetPlayerMode(PlayerMode.RIDE);
}
InstanceService.onEnterZone(player, zone);
if (zone.getAreaTemplate().getZoneName() == null) {
log.error("No name found for a Zone in the map " + zone.getAreaTemplate().getWorldId());
} else {
QuestEngine.getInstance().onEnterZone(new QuestEnv(null, player, 0, 0), zone.getAreaTemplate().getZoneName());
}
}

@Override
public void onLeaveZone(ZoneInstance zone) {
Player player = getOwner();
InstanceService.onLeaveZone(player, zone);
ZoneName zoneName = zone.getAreaTemplate().getZoneName();
if (zoneName == null) {
log.warn("No name for zone template in " + zone.getAreaTemplate().getWorldId());
return;
}
QuestEngine.getInstance().onLeaveZone(new QuestEnv(null, player, 0, 0), zoneName);
}

/**
* {@inheritDoc} Should only be triggered from one place (life stats)
*/
// TODO [AT] move
public void onEnterWorld() {

InstanceService.onEnterInstance(getOwner());
if (getOwner().getPosition().getWorldMapInstance().getParent().isExceptBuff()) {
getOwner().getEffectController().removeAllEffects();
}

if (getOwner().getBattleGround() != null && getOwner().getWorldId() != getOwner().getBattleGround().getWorldId()) {
BattleGroundManager.unregisterPlayer(getOwner());
getOwner().battlegroundWaiting = false;
getOwner().setBattleGround(null);
}

for (Effect ef : getOwner().getEffectController().getAbnormalEffects()) {
if (ef.isDeityAvatar()) {
// remove abyss transformation if worldtype != abyss && worldtype != balaurea
if (getOwner().getWorldType() != WorldType.ABYSS && getOwner().getWorldType() != WorldType.BALAUREA || getOwner().isInInstance() || getOwner().getWorldId() == 600040000) {
ef.endEffect();
getOwner().getEffectController().clearEffect(ef);
}
} else if (ef.getSkillTemplate().getDispelCategory() == DispelCategoryType.NPC_BUFF) {
ef.endEffect();
getOwner().getEffectController().clearEffect(ef);
}
}
}

// TODO [AT] move
public void onLeaveWorld() {
SerialKillerService.getInstance().onLeaveMap(getOwner());
ArenaMasterService.getInstance().onLeaveInstance(getOwner());
InstanceService.onLeaveInstance(getOwner());
}

public void validateLoginZone() {
int mapId;
float x, y, z;
byte h;
boolean moveToBind = false;

BindPointPosition bind = getOwner().getBindPoint();

if (bind != null) {
mapId = bind.getMapId();
x = bind.getX();
y = bind.getY();
z = bind.getZ();
h = bind.getHeading();
} else {
PlayerInitialData.LocationData start = DataManager.PLAYER_INITIAL_DATA.getSpawnLocation(getOwner().getRace());

mapId = start.getMapId();
x = start.getX();
y = start.getY();
z = start.getZ();
h = start.getHeading();
}
if (!SiegeService.getInstance().validateLoginZone(getOwner())) {
moveToBind = true;
} else {
long lastOnline = getOwner().getCommonData().getLastOnline().getTime();
long secondsOffline = (System.currentTimeMillis() / 1000) - lastOnline / 1000;
if (secondsOffline > 10 * 60) { //Logout in no-recall zone sends you to bindpoint after 10 (??) minutes
for (ZoneInstance zone : getOwner().getPosition().getMapRegion().getZones(getOwner())) {
if (!zone.canRecall()) {
moveToBind = true;
break;
}
}
}
}

if (moveToBind) {
World.getInstance().setPosition(getOwner(), mapId, x, y, z, h);
}
}

public void onDie(@Nonnull Creature lastAttacker, boolean showPacket) {
Player player = this.getOwner();
player.getController().cancelCurrentSkill();
player.setRebirthRevive(getOwner().haveSelfRezEffect());
showPacket = player.hasResurrectBase() ? false : showPacket;
Creature master = lastAttacker.getMaster();

// crazy Daeva
if (EventSystem.ENABLE_CRAZY) {
if (((master instanceof Player)) && (master.getRace() != player.getRace())) {
CrazyDaevaService.getInstance().crazyOnDie(player, (Player) master, true);
}
}

// Battelground
if (master instanceof Player) {
if (((Player) master).getBattleGround() != null && ((Player) master).getBattleGround() instanceof AssaultBattleGround) {
((AssaultBattleGround) (((Player) master).getBattleGround())).onKillPlayer(player, (Player) master);
}
}
// 1 vs 1 Event
if (EventSystem.ENABLE_ONEVONE){
if (((master instanceof Player)) && ((Player) master).isInPkMode()){
for(int worldId : OneVsOneStruct.worldid){
if(master.getWorldId() == worldId){
ArenaMasterService.getInstance().onDie((Player) master, player);
}
}
}
}

// High ranked kill announce
AbyssRank ar = player.getAbyssRank();
if (AbyssService.isOnPvpMap(player) && ar != null) {
if (ar.getRank().getId() >= 10) {
AbyssService.rankedKillAnnounce(player);
}
}

if (DuelService.getInstance().isDueling(player.getObjectId())) {
if (master != null && DuelService.getInstance().isDueling(player.getObjectId(), master.getObjectId())) {
DuelService.getInstance().loseDuel(player);
player.getEffectController().removeAbnormalEffectsByTargetSlot(SkillTargetSlot.DEBUFF);
player.getLifeStats().setCurrentHpPercent(33);
player.getLifeStats().setCurrentMpPercent(33);
return;
}
DuelService.getInstance().loseDuel(player);
}

/**
* Release summon
*/
Summon summon = player.getSummon();
if (summon != null) {
SummonsService.doMode(SummonMode.RELEASE, summon, UnsummonType.UNSPECIFIED);
}

// setIsFlyingBeforeDead for PlayerReviveService
if (player.isInState(CreatureState.FLYING)) {
player.setIsFlyingBeforeDeath(true);
}

// ride
player.setPlayerMode(PlayerMode.RIDE, null);
player.unsetState(CreatureState.RESTING);
player.unsetState(CreatureState.FLOATING_CORPSE);

// unsetflying
player.unsetState(CreatureState.FLYING);
player.unsetState(CreatureState.GLIDING);
player.setFlyState(0);

if (player.isInInstance()) {
if (player.getPosition().getWorldMapInstance().getInstanceHandler().onDie(player, lastAttacker)) {
super.onDie(lastAttacker);
return;
}
}

MapRegion mapRegion = player.getPosition().getMapRegion();
if (mapRegion != null && mapRegion.onDie(lastAttacker, getOwner())) {
return;
}

this.doReward();

if (master instanceof Npc || master == player) {
if (player.getLevel() > 4 && !isNoDeathPenaltyInEffect())
player.getCommonData().calculateExpLoss();
}
// Effects removed with super.onDie()
super.onDie(lastAttacker);

//test it if bug (maybe not needed)
if (player.getBattleGround() != null && player.getBattleGround() instanceof CTFBattleGround && master instanceof Player) {
int tplId = player.getBattleGround().getTplId();
template = DataManager.BATTLEGROUND_DATA.getBattleGroundTemplate(tplId);
player.getBattleGround().increasePoints((Player) master, template.getRules().getKillPlayer());
}
if (player.battlegroundFlag != null) {
player.getBattleGround().broadcastToBattleGround(player.getCommonData().getName() + (player.getLegion() != null ? " de " + player.getLegion().getLegionName() : "") + " got the " + (player.battlegroundFlag.getRace() == Race.ELYOS ? "Elyséen" : "Asmodien") + " !", null);
if (master instanceof Player) {
player.getBattleGround().increasePoints((Player) master, template.getRules().getFlagBase());
}

player.battlegroundFlag.getController().dropped = true;
player.battlegroundFlag.setFlagHolder(null);
player.battlegroundFlag = null;
if (player.getController().getTask(TaskId.BATTLEGROUND_CARRY_FLAG) != null) {
player.getController().getTask(TaskId.BATTLEGROUND_CARRY_FLAG).cancel(true);
player.getController().addTask(TaskId.BATTLEGROUND_CARRY_FLAG, null);
}
}
player.getActionList().clearAll();

// send sm_emotion with DIE
// have to be send after state is updated!
sendDieFromCreature(lastAttacker, showPacket);

QuestEngine.getInstance().onDie(new QuestEnv(null, player, 0, 0));

if (player.isInGroup2()) {
player.getPlayerGroup2().sendPacket(SM_SYSTEM_MESSAGE.STR_MSG_COMBAT_FRIENDLY_DEATH(player.getName()), new ExcludePlayerFilter(player));
}
}

@Override
public void onDie(@Nonnull Creature lastAttacker) {
this.onDie(lastAttacker, true);
}

public void sendDie() {
sendDieFromCreature(getOwner(), true);
}

private void sendDieFromCreature(@Nonnull Creature lastAttacker, boolean showPacket) {
Player player = this.getOwner();

PacketSendUtility.broadcastPacket(player, new SM_EMOTION(player, EmotionType.DIE, 0, player.equals(lastAttacker) ? 0 : lastAttacker.getObjectId()), true);

if (showPacket) {
int kiskTimeRemaining = (player.getKisk() != null ? player.getKisk().getRemainingLifetime() : 0);
PacketSendUtility.sendPacket(player, new SM_DIE(player.canUseRebirthRevive(), player.haveSelfRezItem(), kiskTimeRemaining, 0, isInvader(player)));
}

PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_MSG_COMBAT_MY_DEATH);
}

private boolean isInvader(Player player) {
if (player.getRace().equals(Race.ASMODIANS)) {
return player.getWorldId() == 210060000;
} else {
return player.getWorldId() == 220050000;
}
}

@Override
public void doReward() {
PvpService.getInstance().doReward(getOwner());
}

@Override
public void onBeforeSpawn() {
this.onBeforeSpawn(true);
/*
super.onBeforeSpawn();
startProtectionActiveTask();
if (getOwner().getIsFlyingBeforeDeath()) {
getOwner().unsetState(CreatureState.FLOATING_CORPSE);
} else {
getOwner().unsetState(CreatureState.DEAD);
}
getOwner().setState(CreatureState.ACTIVE);
*/
}

public void onBeforeSpawn(boolean blink) {
super.onBeforeSpawn();
if (blink) {
startProtectionActiveTask();
}
if (getOwner().getIsFlyingBeforeDeath()) {
getOwner().unsetState(CreatureState.FLOATING_CORPSE);
} else {
getOwner().unsetState(CreatureState.DEAD);
}
getOwner().setState(CreatureState.ACTIVE);
}

@Override
public void attackTarget(Creature target, int time) {

PlayerGameStats gameStats = getOwner().getGameStats();

if (!RestrictionsManager.canAttack(getOwner(), target)) {
return;
}

// Normal attack is already limited client side (ex. Press C and attacker approaches target)
// but need a check server side too also for Z axis issue
if (!MathUtil.isInAttackRange(getOwner(), target, (float) (getOwner().getGameStats().getAttackRange().getCurrent() / 1000f) + 1)) {
return;
}

if (!GeoService.getInstance().canSee(getOwner(), target)) {
PacketSendUtility.sendPacket(getOwner(), SM_SYSTEM_MESSAGE.STR_ATTACK_OBSTACLE_EXIST);
return;
}

if (target instanceof Npc) {
QuestEngine.getInstance().onAttack(new QuestEnv(target, getOwner(), 0, 0));
}

int attackSpeed = gameStats.getAttackSpeed().getCurrent();

long milis = System.currentTimeMillis();
// network ping..
if (milis - lastAttackMilis + 300 < attackSpeed) {
// hack
return;
}
lastAttackMilis = milis;

/**
* notify attack observers
*/
super.attackTarget(target, time);

}

@Override
public void onAttack(Creature creature, int skillId, TYPE type, int damage, boolean notifyAttack, LOG log) {
if (getOwner().getLifeStats().isAlreadyDead()) {
return;
}

if (getOwner().isInvul() || getOwner().isProtectionActive()) {
damage = 0;
}

if (getOwner().getBattleGround() != null && !getOwner().getBattleGround().running) {
damage = 0;
}

if (getOwner().getActionList() != null) {
getOwner().getActionList().addDamage(creature, damage);
}

cancelUseItem();
cancelGathering();
super.onAttack(creature, skillId, type, damage, notifyAttack, log);

PacketSendUtility.broadcastPacket(getOwner(), new SM_ATTACK_STATUS(getOwner(), type, skillId, damage, log), true);

if (creature instanceof Npc) {
QuestEngine.getInstance().onAttack(new QuestEnv(creature, getOwner(), 0, 0));
}

lastAttackedMilis = System.currentTimeMillis();
}

/**
* @param skillId
* @param targetType
* @param x
* @param y
* @param z
*/
public void useSkill(int skillId, int targetType, float x, float y, float z, int time) {
Player player = getOwner();

Skill skill = SkillEngine.getInstance().getSkillFor(player, skillId, player.getTarget());

if (skill != null) {
if (!RestrictionsManager.canUseSkill(player, skill)) {
return;
}

skill.setTargetType(targetType, x, y, z);
skill.setHitTime(time);
skill.useSkill();
}
}

/**
* @param template
* @param targetType
* @param x
* @param y
* @param z
* @param clientHitTime
*/
public void useSkill(SkillTemplate template, int targetType, float x, float y, float z, int clientHitTime,
int skillLevel) {
Player player = getOwner();
Skill skill = null;
skill = SkillEngine.getInstance().getSkillFor(player, template, player.getTarget());
if (skill == null && player.isTransformed()) {
SkillPanel panel = DataManager.PANEL_SKILL_DATA.getSkillPanel(player.getTransformModel().getPanelId());
if (panel != null && panel.canUseSkill(template.getSkillId(), skillLevel)) {
skill = SkillEngine.getInstance().getSkillFor(player, template, player.getTarget(), skillLevel);
}
}

if (skill != null) {
if (!RestrictionsManager.canUseSkill(player, skill)) {
return;
}

skill.setTargetType(targetType, x, y, z);
skill.setHitTime(clientHitTime);
skill.useSkill();
}
}

@Override
public void onMove() {
getOwner().getObserveController().notifyMoveObservers();
super.onMove();
}

@Override
public void onStopMove() {
PlayerMoveTaskManager.getInstance().removePlayer(getOwner());
getOwner().getObserveController().notifyMoveObservers();
getOwner().getMoveController().setInMove(false);
cancelCurrentSkill();
updateZone();
super.onStopMove();
}

@Override
public void onStartMove() {
getOwner().getMoveController().setInMove(true);
PlayerMoveTaskManager.getInstance().addPlayer(getOwner());
cancelUseItem();
cancelCurrentSkill();
super.onStartMove();
}

@Override
public void cancelCurrentSkill() {
if (getOwner().getCastingSkill() == null) {
return;
}

Player player = getOwner();
Skill castingSkill = player.getCastingSkill();
castingSkill.cancelCast();
player.removeSkillCoolDown(castingSkill.getSkillTemplate().getCooldownId());
player.setCasting(null);
player.setNextSkillUse(0);
if (castingSkill.getSkillMethod() == SkillMethod.CAST || castingSkill.getSkillMethod() == SkillMethod.CHARGE) {
PacketSendUtility.broadcastPacket(player, new SM_SKILL_CANCEL(player, castingSkill.getSkillTemplate().getSkillId()), true);
PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_SKILL_CANCELED);
} else if (castingSkill.getSkillMethod() == SkillMethod.ITEM) {
PacketSendUtility.sendPacket(player, SM_SYSTEM_MESSAGE.STR_ITEM_CANCELED(new DescriptionId(castingSkill.getItemTemplate().getNameId())));
player.removeItemCoolDown(castingSkill.getItemTemplate().getUseLimits().getDelayId());
PacketSendUtility.broadcastPacket(player, new SM_ITEM_USAGE_ANIMATION(player.getObjectId(), castingSkill.getFirstTarget().getObjectId(), castingSkill.getItemObjectId(), castingSkill.getItemTemplate().getTemplateId(), 0, 3, 0), true);
}
}

@Override
public void cancelUseItem() {
Player player = getOwner();
Item usingItem = player.getUsingItem();
player.setUsingItem(null);
if (hasTask(TaskId.ITEM_USE)) {
cancelTask(TaskId.ITEM_USE);
PacketSendUtility.broadcastPacket(player, new SM_ITEM_USAGE_ANIMATION(player.getObjectId(), usingItem == null ? 0 : usingItem.getObjectId(), usingItem == null ? 0 : usingItem.getItemTemplate().getTemplateId(), 0, 3, 0), true);
}
}

public void cancelGathering() {
Player player = getOwner();
if (player.getTarget() instanceof Gatherable) {
Gatherable g = (Gatherable) player.getTarget();
g.getController().finishGathering(player);
}
}

public void updatePassiveStats() {
Player player = getOwner();
for (PlayerSkillEntry skillEntry : player.getSkillList().getAllSkills()) {
Skill skill = SkillEngine.getInstance().getSkillFor(player, skillEntry.getSkillId(), player.getTarget());
if (skill != null && skill.isPassive()) {
skill.useSkill();
}
}
}

@Override
public Player getOwner() {
return (Player) super.getOwner();
}

@Override
public void onRestore(HealType healType, int value) {
super.onRestore(healType, value);
switch (healType) {
case DP:
getOwner().getCommonData().addDp(value);
break;
default:
break;
}
}

/**
* @param player
* @return
*/
// TODO [AT] move to Player
public boolean isDueling(Player player) {
return DuelService.getInstance().isDueling(player.getObjectId(), getOwner().getObjectId());
}

// TODO [AT] rename or remove
public boolean isInShutdownProgress() {
return isInShutdownProgress;
}

// TODO [AT] rename or remove
public void setInShutdownProgress(boolean isInShutdownProgress) {
this.isInShutdownProgress = isInShutdownProgress;
}

@Override
public void onDialogSelect(int dialogId, Player player, int questId, int extendedRewardIndex) {
switch (dialogId) {
case 2:
PacketSendUtility.sendPacket(player, new SM_PRIVATE_STORE(getOwner().getStore(), player));
break;
}
}

public void upgradePlayer() {
Player player = getOwner();
byte level = player.getLevel();

PlayerStatsTemplate statsTemplate = DataManager.PLAYER_STATS_DATA.getTemplate(player);
player.setPlayerStatsTemplate(statsTemplate);

player.getLifeStats().synchronizeWithMaxStats();
player.getLifeStats().updateCurrentStats();

PacketSendUtility.broadcastPacket(player, new SM_LEVEL_UPDATE(player.getObjectId(), 0, level), true);

// Guides Html on level up
if (HTMLConfig.ENABLE_GUIDES) {
HTMLService.sendGuideHtml(player);
}

// Temporal
ClassChangeService.showClassChangeDialog(player);

QuestEngine.getInstance().onLvlUp(new QuestEnv(null, player, 0, 0));
updateNearbyQuests();

// add new skills
SkillLearnService.addNewSkills(player);

PacketSendUtility.broadcastPacket(player, new SM_PACKAGE_INFO_NOTIFY(0), true);

player.getController().updatePassiveStats();

// add recipe for morph
if (level == 10) {
CraftSkillUpdateService.getInstance().setMorphRecipe(player);
}

if (player.isInTeam()) {
TeamEffectUpdater.getInstance().startTask(player);
}
if (player.isLegionMember()) {
LegionService.getInstance().updateMemberInfo(player);
}
player.getNpcFactions().onLevelUp();
PacketSendUtility.sendPacket(player, new SM_STATS_INFO(player));
}

/**
* After entering game player char is "blinking" which means that it's in
* under some protection, after making an action char stops blinking. -
* Starts protection active - Schedules task to end protection
*/
public void startProtectionActiveTask() {
if (!getOwner().isProtectionActive()) {
getOwner().setVisualState(CreatureVisualState.BLINKING);
AttackUtil.cancelCastOn((Creature) getOwner());
AttackUtil.removeTargetFrom((Creature) getOwner());
PacketSendUtility.broadcastPacket(getOwner(), new SM_PLAYER_STATE(getOwner()), true);
Future<?> task = ThreadPoolManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
stopProtectionActiveTask();
}
}, 60000);
addTask(TaskId.PROTECTION_ACTIVE, task);
}
}

/**
* Stops protection active task after first move or use skill
*/
public void stopProtectionActiveTask() {
cancelTask(TaskId.PROTECTION_ACTIVE);
Player player = getOwner();
if (player != null && player.isSpawned()) {
player.unsetVisualState(CreatureVisualState.BLINKING);
PacketSendUtility.broadcastPacket(player, new SM_PLAYER_STATE(player), true);
notifyAIOnMove();
}
}

/**
* When player arrives at destination point of flying teleport
*/
public void onFlyTeleportEnd() {
Player player = getOwner();
if (player.isInPlayerMode(PlayerMode.WINDSTREAM)) {
player.unsetPlayerMode(PlayerMode.WINDSTREAM);
player.getLifeStats().triggerFpReduce();
player.unsetState(CreatureState.FLYING);
player.setState(CreatureState.ACTIVE);
player.setState(CreatureState.GLIDING);
player.getGameStats().updateStatsAndSpeedVisually();
} else {
player.unsetState(CreatureState.FLIGHT_TELEPORT);
player.setFlightTeleportId(0);

if (SecurityConfig.ENABLE_FLYPATH_VALIDATOR) {
long diff = (System.currentTimeMillis() - player.getFlyStartTime());
FlyPathEntry path = player.getCurrentFlyPath();

if (player.getWorldId() != path.getEndWorldId()) {
AuditLogger.info(player, "Player tried to use flyPath #" + path.getId() + " from not native start world "
+ player.getWorldId() + ". expected " + path.getEndWorldId());
}

if (diff < path.getTimeInMs()) {
AuditLogger.info(player,
"Player " + player.getName() + " used flypath bug " + diff + " instead of " + path.getTimeInMs());
/*
* todo if works teleport player to start_* xyz, or even ban
*/
}

player.setCurrentFlypath(null);
}

player.setFlightDistance(0);
player.setState(CreatureState.ACTIVE);
updateZone();
}
}

public boolean addItems(int itemId, int count) {
return ItemService.addQuestItems(getOwner(), Collections.singletonList(new QuestItems(itemId, count)));
}

public void startStance(final int skillId) {
stance = skillId;
}

public void stopStance() {
getOwner().getEffectController().removeEffect(stance);
PacketSendUtility.sendPacket(getOwner(), new SM_PLAYER_STANCE(getOwner(), 0));
stance = 0;
}

public int getStanceSkillId() {
return stance;
}

public boolean isUnderStance() {
return stance != 0;
}

public void updateSoulSickness(int skillId) {
Player player = getOwner();
House house = player.getActiveHouse();
if (house != null) {
switch (house.getHouseType()) {
case MANSION:
case ESTATE:
case PALACE:
return;
default:
break;
}
}

if (!player.havePermission(MembershipConfig.DISABLE_SOULSICKNESS)) {
int deathCount = player.getCommonData().getDeathCount();
if (deathCount < 10) {
deathCount++;
player.getCommonData().setDeathCount(deathCount);
}

if (skillId == 0) {
skillId = 8291;
}
SkillEngine.getInstance().getSkill(player, skillId, deathCount, player).useSkill();
}
}

/**
* Player is considered in combat if he's been attacked or has attacked less
* or equal 10s before
*
* @return true if the player is actively in combat
*/
public boolean isInCombat() {
return (((System.currentTimeMillis() - lastAttackedMilis) <= 10000) || ((System.currentTimeMillis() - lastAttackMilis) <= 10000));
}

/**
* Check if NoDeathPenalty is active
*
* @param player
* @return boolean
*/
public boolean isNoDeathPenaltyInEffect() {
// Check if NoDeathPenalty is active
Iterator<Effect> iterator = getOwner().getEffectController().iterator();
while (iterator.hasNext()) {
Effect effect = iterator.next();
if (effect.isNoDeathPenalty()) {
return true;
}
}
return false;
}

/**
* Check if NoResurrectPenalty is active
*
* @param player
* @return boolean
*/
public boolean isNoResurrectPenaltyInEffect() {
// Check if NoResurrectPenalty is active
Iterator<Effect> iterator = getOwner().getEffectController().iterator();
while (iterator.hasNext()) {
Effect effect = iterator.next();
if (effect.isNoResurrectPenalty()) {
return true;
}
}
return false;
}

/**
* Check if HiPass is active
*
* @param player
* @return boolean
*/
public boolean isHiPassInEffect() {
// Check if HiPass is active
Iterator<Effect> iterator = getOwner().getEffectController().iterator();
while (iterator.hasNext()) {
Effect effect = iterator.next();
if (effect.isHiPass()) {
return true;
}
}
return false;
}

public void registerListener(Listener listener) {
this.mListener = listener;
}

public void unregisterListener() {
this.mListener = null;
}

public static abstract interface Listener {
public abstract void onPlayerUsedSkill(int paramInt, Player paramPlayer);
}
}

Check console on error message
 
Ясно, понятно мусор неадекватный который пришел по рофлить. Откуда ты вылез вообще.
Оо это уже переход на личности и оскорбления, следи за своим гнилым базаром. Тебя никто тут не оскорблял и право тебе никто тут не давал это делать.

Или тебя так бомбануло? :LOL:
О того, что ты оформил тему с продажей 4.75, а я дополнил тему багами от твоего клиента? Ты сразу почистил тему от моего поста, потом закрыл, а теперь я темы вообще не наблюдаю. Что только подтверждает правдивость всего написанного.

Ты на форуме сидишь с целью продажи своего мусора который все равно никому не нужен, да и ответы в разделах помощи не лучше.
http://javaclub.ru/forum/threads/2396/#post-14973 я представляю что там в версиях выше, если тут такое :rofl-82:
 
Оо это уже переход на личности и оскорбления, следи за своим гнилым базаром. Тебя никто тут не оскорблял и право тебе никто тут не давал это делать.

Или тебя так бомбануло? :LOL:
О того, что ты оформил тему с продажей 4.75, а я дополнил тему багами от твоего клиента? Ты сразу почистил тему от моего поста, потом закрыл, а теперь я темы вообще не наблюдаю. Что только подтверждает правдивость всего написанного.

Ты на форуме сидишь с целью продажи своего мусора который все равно никому не нужен, да и ответы в разделах помощи не лучше.
http://javaclub.ru/forum/threads/2396/#post-14973 я представляю что там в версиях выше, если тут такое :rofl-82:
Крч товарищ подлизалкин иди в игнор. Со мной много проектов работает и все довольны работой.
[DOUBLEPOST=1563283533,1563283388][/DOUBLEPOST]
I'm not getting an error message.
Then comment custom event's at method onDie (PlayerController) and check death.
 
Крч товарищ подлизалкин иди в игнор.
В общем всё ясно понятно, он даже не отрицает по сборке которую поспешил убрать с форума удалив посты.
Только оскорблять пытается в ответ как школьник.
Со мной много проектов работает и все довольны работой.
А вот тут уже интересно, можешь назвать хоть один? Хоть одного довольного клиента?
Помнится на последнем проекте катаклизм 5.3 х5 где стояла сборка этого уникума, даже игроки называли этого разраба аутистом, видя его работу:D.
Или такого не было?
Можешь в принципе не отвечать, уверен ты не одного не назовешь проекта и способен только на детсадовский агр.
 
что за кипишь драки нет ))
P.S. почему бы ТС не написать на форум коров если он использует их сборку или тем же немцам , пускай помогут и гугл переводчик использовать не прийдется ,
ах да забыл всем пох ))) в ру комьюнити хоть кто то еще шевелится а остальные давно забили
 
Hi!

If a married couple is present during any fortress siege, the fortress does not turn into asmodian/elyos. The following error-message appears:

java.lang.NullPointerException: null
at com.aionemu.gameserver.model.team2.common.service.PlayerTeamDistributionService.doReward(PlayerTeamDistributionService.java:117) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.NpcController.doReward(NpcController.java:246) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.NpcController.onDie(NpcController.java:158) ~[AC-Game.jar:na]
at com.aionemu.gameserver.model.stats.container.CreatureLifeStats.reduceHp(CreatureLifeStats.java:143) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.CreatureController.onAttack(CreatureController.java:267) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.NpcController.onAttack(NpcController.java:330) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.CreatureController.onAttack(CreatureController.java:299) ~[AC-Game.jar:na]
at com.aionemu.gameserver.skillengine.effect.DamageEffect.applyEffect(DamageEffect.java:57) ~[AC-Game.jar:na]
at com.aionemu.gameserver.skillengine.model.Effect.applyEffect(Effect.java:745) ~[AC-Game.jar:na]
at com.aionemu.gameserver.skillengine.model.Skill.applyEffect(Skill.java:760) ~[AC-Game.jar:na]
at com.aionemu.gameserver.skillengine.model.Skill$1.run(Skill.java:740) ~[AC-Game.jar:na]
at com.aionemu.commons.utils.concurrent.ExecuteWrapper.execute(ExecuteWrapper.java:56) ~[ac-commons-1.3.jar:na]
at com.aionemu.commons.utils.concurrent.RunnableWrapper.run(RunnableWrapper.java:51) [ac-commons-1.3.jar:na]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [na:1.7.0_95]
at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_95]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178) [na:1.7.0_95]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292) [na:1.7.0_95]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_95]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_95]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_95]

If there is no married couple during fortress siege, this bug does not pop up. Has anyone already encountered this problem? Do you have an advice to give us? Thank you!

Help Please!
 
Hi!

If a married couple is present during any fortress siege, the fortress does not turn into asmodian/elyos. The following error-message appears:

java.lang.NullPointerException: null
at com.aionemu.gameserver.model.team2.common.service.PlayerTeamDistributionService.doReward(PlayerTeamDistributionService.java:117) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.NpcController.doReward(NpcController.java:246) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.NpcController.onDie(NpcController.java:158) ~[AC-Game.jar:na]
at com.aionemu.gameserver.model.stats.container.CreatureLifeStats.reduceHp(CreatureLifeStats.java:143) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.CreatureController.onAttack(CreatureController.java:267) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.NpcController.onAttack(NpcController.java:330) ~[AC-Game.jar:na]
at com.aionemu.gameserver.controllers.CreatureController.onAttack(CreatureController.java:299) ~[AC-Game.jar:na]
at com.aionemu.gameserver.skillengine.effect.DamageEffect.applyEffect(DamageEffect.java:57) ~[AC-Game.jar:na]
at com.aionemu.gameserver.skillengine.model.Effect.applyEffect(Effect.java:745) ~[AC-Game.jar:na]
at com.aionemu.gameserver.skillengine.model.Skill.applyEffect(Skill.java:760) ~[AC-Game.jar:na]
at com.aionemu.gameserver.skillengine.model.Skill$1.run(Skill.java:740) ~[AC-Game.jar:na]
at com.aionemu.commons.utils.concurrent.ExecuteWrapper.execute(ExecuteWrapper.java:56) ~[ac-commons-1.3.jar:na]
at com.aionemu.commons.utils.concurrent.RunnableWrapper.run(RunnableWrapper.java:51) [ac-commons-1.3.jar:na]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [na:1.7.0_95]
at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_95]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178) [na:1.7.0_95]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292) [na:1.7.0_95]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_95]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_95]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_95]

If there is no married couple during fortress siege, this bug does not pop up. Has anyone already encountered this problem? Do you have an advice to give us? Thank you!

Help Please!

Check the custom fragment code in "com.aionemu.gameserver.model.team2.common.service.PlayerTeamDistributionService.doReward" wedding related
 
Check the custom fragment code in "com.aionemu.gameserver.model.team2.common.service.PlayerTeamDistributionService.doReward" wedding related
No errors found.
My PlayerTeamDistributionService.java

package com.aionemu.gameserver.model.team2.common.service;

import java.util.ArrayList;
import java.util.List;

import com.aionemu.gameserver.configs.main.CustomConfig;
import com.aionemu.gameserver.configs.main.GroupConfig;
import com.aionemu.gameserver.model.gameobjects.AionObject;
import com.aionemu.gameserver.model.gameobjects.Npc;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.model.gameobjects.player.RewardType;
import com.aionemu.gameserver.model.gameobjects.player.XPCape;
import com.aionemu.gameserver.model.team2.TemporaryPlayerTeam;
import com.aionemu.gameserver.questEngine.QuestEngine;
import com.aionemu.gameserver.questEngine.model.QuestEnv;
import com.aionemu.gameserver.services.abyss.AbyssPointsService;
import com.aionemu.gameserver.services.drop.DropRegistrationService;
import com.aionemu.gameserver.utils.MathUtil;
import com.aionemu.gameserver.utils.stats.StatFunctions;
import com.google.common.base.Predicate;

/**
* @author ATracer, nrg
*/
public class PlayerTeamDistributionService {

/**
* This method will send a reward if a player is in a team
*/
public static void doReward(TemporaryPlayerTeam<?> team, float damagePercent, Npc owner, AionObject winner) {
if (team == null || owner == null) {
return;
}

// Find team's members and determine highest level
PlayerTeamRewardStats filteredStats = new PlayerTeamRewardStats(owner);
team.applyOnMembers(filteredStats);

// All are dead or not nearby
if (filteredStats.players.isEmpty() || !filteredStats.hasLivingPlayer) {
return;
}

// Reward mode
long expReward;
if (filteredStats.players.size() + filteredStats.mentorCount == 1) {
expReward = (long) (StatFunctions.calculateSoloExperienceReward(filteredStats.players.get(0), owner));
} else {
expReward = (long) (StatFunctions.calculateGroupExperienceReward(filteredStats.highestLevel, owner));
}

// Party Bonus 2 members 10%, 3 members 20% ... 6 members 50%
int size = filteredStats.players.size();
int bonus = 100;
if (size > 1) {
bonus = 150 + (size - 2) * 10;
}

for (Player member : filteredStats.players) {
Player partner = member.findPartner();
//mentor and dead players shouldn't receive AP/EP/DP
if (member.isMentor() || member.getLifeStats().isAlreadyDead()) {
continue;
}

// Reward init
long rewardXp = (long) (expReward * bonus * member.getLevel()) / (filteredStats.partyLvlSum * 100);
int rewardDp = StatFunctions.calculateGroupDPReward(member, owner);
int rewardGP = StatFunctions.calculateGPReward(member, owner);
float rewardAp = 1;

// Players 10 levels below highest member get 0 reward.
if (filteredStats.highestLevel - member.getLevel() >= 10) {
rewardXp = 0;
rewardDp = 0;
} else if (filteredStats.mentorCount > 0) {
int cape = XPCape.values()[(int) member.getLevel()].value();
if (cape < rewardXp) {
rewardXp = cape;
}
}

// Dmg percent correction
rewardXp *= damagePercent;
rewardDp *= damagePercent;
rewardAp *= damagePercent;

if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
member.getCommonData().addExp(rewardXp + (rewardXp * 20 / 100), RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp + (rewardXp * 20 / 100));
} else {
member.getCommonData().addExp(rewardXp, RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp);
}

// DP reward
member.getCommonData().addDp(rewardDp);

// AP reward
if (owner.isRewardAP() && !(filteredStats.mentorCount > 0 && CustomConfig.MENTOR_GROUP_AP)) {
rewardAp *= StatFunctions.calculatePvEApGained(member, owner);
int ap = (int) rewardAp / filteredStats.players.size();
if (ap >= 1) {
AbyssPointsService.addAp(member, owner, ap);
}
}

// GP reward
if (owner.isRewardGP()) {
if (rewardGP >= 1) {
AbyssPointsService.addGp(member, owner, rewardGP);
}
}

}

// Give Drop
Player mostDamagePlayer = owner.getAggroList().getMostPlayerDamageOfMembers(team.getMembers(), filteredStats.highestLevel);
if (mostDamagePlayer == null) {
return;
}

if (winner.equals(team) && (!owner.getAi2().getName().equals("chest") || filteredStats.mentorCount == 0)) {
DropRegistrationService.getInstance().registerDrop(owner, mostDamagePlayer, filteredStats.highestLevel, filteredStats.players);
}
}

private static class PlayerTeamRewardStats implements Predicate<Player> {

final List<Player> players = new ArrayList<Player>();
int partyLvlSum = 0;
int highestLevel = 0;
int mentorCount = 0;
boolean hasLivingPlayer = false;
Npc owner;

public PlayerTeamRewardStats(Npc owner) {
this.owner = owner;
}

@Override
public boolean apply(Player member) {
if (member.isOnline()) {
if (MathUtil.isIn3dRange(member, owner, GroupConfig.GROUP_MAX_DISTANCE)) {
QuestEngine.getInstance().onKill(new QuestEnv(owner, member, 0, 0));

if (member.isMentor()) {
mentorCount++;
return true;
}

if (!hasLivingPlayer && !member.getLifeStats().isAlreadyDead()) {
hasLivingPlayer = true;
}

players.add(member);
partyLvlSum += member.getLevel();
if (member.getLevel() > highestLevel) {
highestLevel = member.getLevel();
}
}
}
return true;
}
}
}
 
Код:
if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
member.getCommonData().addExp(rewardXp + (rewardXp * 20 / 100), RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp + (rewardXp * 20 / 100));
}

View by the logs there is an error
[DOUBLEPOST=1563527950,1563527879][/DOUBLEPOST]Add a check to "null"
[DOUBLEPOST=1563528028][/DOUBLEPOST]And in general this is bad code.
[DOUBLEPOST=1563528303][/DOUBLEPOST]It is better delete code
[DOUBLEPOST=1563528350][/DOUBLEPOST]this
 
Код:
if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
member.getCommonData().addExp(rewardXp + (rewardXp * 20 / 100), RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp + (rewardXp * 20 / 100));
}

View by the logs there is an error
[DOUBLEPOST=1563527950,1563527879][/DOUBLEPOST]Add a check to "null"
[DOUBLEPOST=1563528028][/DOUBLEPOST]And in general this is bad code.
[DOUBLEPOST=1563528303][/DOUBLEPOST]It is better delete code
[DOUBLEPOST=1563528350][/DOUBLEPOST]this

I'm sorry but I do not understand
Delete this code?

if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
member.getCommonData().addExp(rewardXp + (rewardXp * 20 / 100), RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp + (rewardXp * 20 / 100));
}

So what would the code look like?
I'm sorry I don't quite understand what you wrote.
 
I'm sorry but I do not understand
Delete this code?

if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
member.getCommonData().addExp(rewardXp + (rewardXp * 20 / 100), RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp + (rewardXp * 20 / 100));
}

So what would the code look like?
I'm sorry I don't quite understand what you wrote.
Код:
DELETE

if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
member.getCommonData().addExp(rewardXp + (rewardXp * 20 / 100), RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp + (rewardXp * 20 / 100));
} else {
member.getCommonData().addExp(rewardXp, RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp);
}

PAST

member.getCommonData().addExp(rewardXp, RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp);
 
Код:
DELETE

if (member.isMarried() && member.getPlayerGroup2().getMembers() == partner && member.getPlayerGroup2().getMembers().size() == 2) {
member.getCommonData().addExp(rewardXp + (rewardXp * 20 / 100), RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp + (rewardXp * 20 / 100));
} else {
member.getCommonData().addExp(rewardXp, RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp);
}

PAST

member.getCommonData().addExp(rewardXp, RewardType.GROUP_HUNTING, owner.getObjectTemplate().getNameId());
member.getCommonData().addEventExp(rewardXp);


Thanks for the help!
 
Назад
Сверху