package ru.nts.scripts.player;
import host.anzo.core.service.ThreadPoolService;
import ru.nts.commons.math.Rnd;
import ru.nts.core.network.outgoing.S_PARTY_MEMBER_POSITION;
import ru.nts.core.network.outgoing.S_SYSTEM_MSG;
import ru.nts.gameserver.game.messages.items.AutoSoulShotItemAction;
import ru.nts.gameserver.game.messages.items.UseItemAction;
import ru.nts.gameserver.game.models.points.Location;
import ru.nts.gameserver.game.models.social.party.Party;
import ru.nts.gameserver.game.stats.effects.Effect;
import ru.nts.gameserver.game.stats.effects.sub_effects.impl.*;
import ru.nts.gameserver.game.stats.impl.CreatureStats;
import ru.nts.gameserver.game.stats.skills.Skill;
import ru.nts.gameserver.game.world.World;
import ru.nts.gameserver.game.world.objects.creatures.Creature;
import ru.nts.gameserver.game.world.objects.creatures.npcs.Npc;
import ru.nts.gameserver.game.world.objects.creatures.npcs.Servitor;
import ru.nts.gameserver.game.world.objects.creatures.npcs.types.base.Pet;
import ru.nts.gameserver.game.world.objects.creatures.npcs.types.base.Summon;
import ru.nts.gameserver.game.world.objects.creatures.npcs.types.base.Warrior;
import ru.nts.gameserver.game.world.objects.creatures.players.FakePlayer;
import ru.nts.gameserver.game.world.objects.creatures.players.Player;
import ru.nts.gameserver.game.world.objects.items.Item;
import ru.nts.gameserver.system.data.memory.SkillTable;
import ru.nts.gameserver.system.data.pts.holder.CategoryDataHolder;
import ru.nts.gameserver.system.engines.geo.GeoData;
import ru.nts.gameserver.system.engines.geo.GeoEngine;
import ru.nts.gameserver.system.enums.*;
import ru.nts.gameserver.system.interfaces.IVarsSessionable;
import ru.nts.gameserver.tools.PositionUtils;
import ru.nts.scripts.nasc.EventNotifier;
import ru.nts.scripts.nasc.NASCScript;
import ru.nts.scripts.nasc.interfaces.INASCConstant;
import ru.nts.scripts.nasc.interfaces.shared.ISharedCreature;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
public class player_base extends NASCScript {
private static final int CHECK_SPAWN_AFK = -2551;
public player_base() {}
@Override
public void DEBUG_AI(ISharedCreature sCreature, int reply) {
if (getNASCActor() instanceof Player player_actor) {
if (sCreature instanceof Player player && player.isGM()) {
switch (reply) {
case 0 -> player_actor.whisperTo("Debug", player);
}
}
}
}
@Override
public void CHECK_CMD_FOLLOW() { //Проверяем, не пора ли бросить все и бежать за хозяином
if (getNASCActor() instanceof Player player_actor) {
Party party = player_actor.getParty();
if (party != null && (player_actor.isReal() || player_actor instanceof FakePlayer fake_actor && fake_actor.getMasterUserID() == party.getPartyLeaderOID())) {
Player leader = party.getPartyLeader();
if (leader.distance3D(player_actor) >= 1000) {
EventNotifier.getInstance().notify(player_actor, 1000, ENASCEvent.CMD_FOLLOW_ME);
}
}
}
}
@Override
public void CHECK_SWEEP() {
TrySweep();
}
@Override
public void CHECK_SELF_BUFF() {
TrySelfBuff(EDesire.get.extra_high());
}
@Override
public void CHECK_SELF_HEAL() {
if (getNASCActor() instanceof Player player_actor) {
final CreatureStats stats = player_actor.getStats();
if (player_actor.isInCombat()) {
if (CategoryDataHolder.isInCategory(heal_master2_3, player_actor)) {
if (stats.getCurrentHpPercents() <= 33) {
TryHeal(player_actor, 5, EDesire.get.extra_high());
} else if (stats.getCurrentHpPercents() <= 70) {
TryHeal(player_actor, 3, EDesire.get.high() + 50000);
} else {
if (stats.getCurrentHpPercents() <= 90) {
TryHeal(player_actor, 1, EDesire.get.normal(20000));
}
}
} else if (CategoryDataHolder.isInCategory(buff_master2_3, player_actor) && stats.getCurrentHpPercents() <= 50) {
TryHeal(player_actor, 5, EDesire.get.high() + 50000);
} else {
if (CategoryDataHolder.isInCategory(attribute_group_summoner, player_actor) && player_actor.getServitor() instanceof Summon summon && summon.getStats().getCurrentHpPercents() <= 90) {
TryHeal(summon, 3, EDesire.get.high() + 10000);
}
}
} else {
if (stats.getCurrentHpPercents() < 100) {
TryHeal(player_actor, 1, EDesire.get.normal(1000));
} else {
if (player_actor.getServitor() instanceof Summon summon && summon.getStats().getCurrentHpPercents() < 100) {
TryHeal(summon, 1, EDesire.get.normal(-1000));
}
}
}
}
}
@Override
public void CHECK_DISPEL() {
if (getNASCActor() instanceof Player player_actor) {
for (Effect effect : player_actor.getAllEffectsSnapshot()) {
if (effect.getSkill() instanceof Skill skill && skill.isDebuff()) {
if (!TryDispellDebuff(player_actor, skill.getAbnormalType(), skill.getAbnormalLevel(), EDesire.get.high())) {
RequestPartyDispell(skill.getAbnormalType(), skill.getAbnormalLevel());
break;
}
}
}
}
}
@Override
public void CREATED() {
if (getNASCActor() instanceof Player player_actor) {
RemoveAllPCHateInfoIF(COND_IS_INVALID, 0);
RemoveAllPCHateInfoIF(COND_HAS_HATE_LESS_THAN, 100);
RemoveAllPCHateInfoIF(COND_IS_FAR_AWAY, 3000);
TrySummonServitor();
TrySummonCubics();
if (player_actor instanceof FakePlayer fake_actor && fake_actor.isWild()) {
AddTimerEx(CHECK_SPAWN_AFK, 60000);
}
}
}
@Override
public void RECHECK_TARGET() {
if (getNASCActor() instanceof Player player_actor) {
RemoveAllPCHateInfoIF(COND_IS_INVALID, 0);
TrySweep();
if (player_actor.isCastingNow() || player_actor.isAttackingNow()) {
EventNotifier.getInstance().notify(player_actor, 1000, ENASCEvent.RECHECK_TARGET);
return;
}
Creature current_target = player_actor.getTargetAsCreature();
if (current_target == null || current_target.isDead() || current_target == player_actor || current_target.isInArea(EAreaType.peace_zone) || player_actor.getAI().target_black_list.contains(current_target.getObjectId()) || !GeoEngine.CanSee(player_actor, current_target)) {
if (current_target != null && current_target != player_actor) {
RemovePCAttackDesire(current_target.getObjectId());
}
player_actor.setTarget(null, EChangeTargetReason.CTR_BY_USER);
current_target = null;
//Сначала известные цели в границах прямой видимости.
for (Creature creature : player_actor.getHateList().getMostHated(10)) {
if (player_actor.getHateList().getHate(creature) > 100 && !player_actor.getAI().target_black_list.contains(creature.getObjectId()) && player_actor.canSee(creature) && creature.isAlive()) {
current_target = creature;
break;
}
}
//Потом известные цели к которым можно пройти.
if (current_target == null) {
for (Creature creature : player_actor.getHateList().getMostHated(10)) {
if (player_actor.getHateList().getHate(creature) > 100 && !player_actor.getAI().target_black_list.contains(creature.getObjectId()) && player_actor.canMove(creature) && creature.isAlive()) {
current_target = creature;
break;
}
}
}
//Если нет приоритетной цели по хейту, то ищем ближайшую(Только дикие боты)
if (current_target == null && player_actor instanceof FakePlayer fake_actor && fake_actor.isWild()) {
List<Creature> around = fake_actor.getAI().lookAround(fake_actor.sight_distance() / 3, 500);
//Сначала ищем чаров вокруг.
//Порабощенных ботов ненавидим и агримся сразу же
//Если слишком близко подошел, с кармой или флагом, ну или просто не понравился)
current_target = around.stream().filter(creature -> !creature.isInArea(EAreaType.peace_zone)).filter(creature -> !fake_actor.getAI().target_black_list.contains(creature.getObjectId())).filter(creature -> fake_actor.canSee(creature) || fake_actor.canMove(creature)).filter(creature -> {
if (creature instanceof Player player) {
//Порабощенных ботов ненавидим и агримся сразу же
if (player instanceof FakePlayer fake) {
return fake.isSlave();
}
//Если слишком близко подошел, с кармой или флагом, ну или просто не понравился)
if (fake_actor.distance3D(player) < 100 || (player.isGuilty() > 0 || player.getKarma() > 0) && Rnd.chance(15 - fake_actor.getDifficulty().ordinal() * 2)) {
return true;
}
}
return false;
}).min(fake_actor.getRangeComparator()).orElse(null);
//Если чаров нет, то ищем мобов
if (current_target == null) {
current_target = around.stream().filter(creature -> !creature.isInArea(EAreaType.peace_zone)).filter(creature -> !fake_actor.getAI().target_black_list.contains(creature.getObjectId())).filter(creature -> fake_actor.canSee(creature) || fake_actor.canMove(creature)).filter(creature -> {
if (creature instanceof Warrior monster && Math.abs(monster.getLevel() - fake_actor.getLevel()) <= 20) {
return true;
}
return false;
}).min(fake_actor.getRangeComparator()).orElse(null);
}
}
}
if (current_target != null) {
DoAttack(current_target, Math.max(200, player_actor.getHateList().getHate(current_target)), false);
}
}
}
@Override
public void NO_DESIRE() {
if (getNASCActor() instanceof Player player_actor) {
//Рабы отрабатывают социальный контракт.
if (player_actor instanceof FakePlayer fake_actor && (fake_actor.isSlave() || fake_actor.isWildPrivate())) {
//В этом методе, мы чинимся. Если потеряли мастера, ищем. Если не нашли вблизи - бежим на дальнюю дистанцию.
if (fake_actor.lost_master()) {
List<Player> list = World.getInstance().getAroundPlayers(fake_actor, 1500, fake_actor.getReflectionID(),false);
for (Player player : list) {
if (player != null && fake_actor.isMyMaster(player)) {
//Если увидели родителя, обновляем таск следования за ним.
AddFollowDesire2(player, 100, eAFD2_FT_DIST_AND_DEGREE, 120 + Rnd.getInt(0, 50, true), fake_actor.follow_angle);
return;
}
}
Creature master = fake_actor.getMasterUser();
if (master != null && fake_actor.isSlave() && TryTeleportWithCommunityBoard(master.getLoc(), -1)) {
AddMovePartialDesire(master.getLoc(), 5000, 90);
return;
}
}
if (fake_actor.getNextLoc() != null && fake_actor.getNextLoc().distance2D(fake_actor) > 1000) {
Location temp = fake_actor.getNextLoc();
if (TryTeleportWithCommunityBoard(temp, -1)) {
fake_actor.setNextLoc(null);
}
AddMovePartialDesire(temp, 5000, 90);
return;
}
//Только если нет потребностей в починке состояния следования за мастером, то тогда чекаем, можно ли кого-то подлечить.
if (CategoryDataHolder.isInCategory(recom_magic_group, fake_actor)) {
if (fake_actor.getParty() != null && fake_actor.getStats().getCurrentMpPercents() > 50) {
for (Player member : fake_actor.getParty().getPartyMembers()) {
if (member != null && member.getStats().getCurrentHpPercents() < 100) {
Skill skill = SelectSkillForHeal(member, 0);
if (skill != null) {
AddUseSkillDesireEx(skill.getAimingTarget(fake_actor, member), skill, ST_HEAL, AMT_MOVE_TO_TARGET, FALSE, EDesire.get.normal(), 0);
}
}
}
}
}
}
EventNotifier.getInstance().notify(player_actor, ENASCEvent.RECHECK_TARGET);
}
}
@Override
public void SEE_CREATURE(ISharedCreature sCreature) {
if (getNASCActor() instanceof Player player_actor) {
if (sCreature instanceof Creature creature) {
if (player_actor.isDead()) {
return;
}
if (player_actor instanceof FakePlayer fake && !fake.isWild()) {
// Смотреть по сторонам и анализировать обстановку могут только дикие мобы.
return;
}
if (creature.isInArea(EAreaType.peace_zone)) {
// Если цель в мирной зоне, то не трогаем ее.
return;
}
if (player_actor.getHateList().getHate(creature) > 0) {
// Если на существо уже есть хейт, то новый не добавляем.
return;
}
double hate = 0;
double range_add = player_actor.sight_distance() / Math.max(1, player_actor.distance3D(creature));
// В целом, в SEE_CREATURE может попасть либо моб, либо чар.
if (creature instanceof Warrior monster && Math.abs(monster.getLevel() - player_actor.getLevel()) <= 20) {
hate = 100 + range_add;
} else if (creature instanceof Player player) {
if (player.isReal() && player.getKarma() > 0) {
return;
}
if (player instanceof FakePlayer fake) {
if (fake.isWild() && (fake.getFakeFactionId() == -1 || player_actor.isFactionMember(fake))) {
return;
}
if (fake.isSlave() || player_actor.isFactionEnemy(fake)) {
hate = 2000 + range_add;
}
}
if (player_actor.distance3D(player) < 100) {
hate = 200;
}
} else {
return;
}
if (hate > 0) {
AddPCHate(creature, hate, true, 60);
}
}
}
}
@Override
public void DISAPPEAR_CREATURE(ISharedCreature sCreature, int objectId) {
if (sCreature instanceof Creature creature) {
RemovePCAttackDesire(creature.getObjectId());
}
}
@Override
public void ATTACKED(ISharedCreature sAttacker, int damage, long skill_name_id, int skill_id) {
if (getNASCActor() instanceof Player player_actor) {
if (sAttacker instanceof Creature attacker) {
if (damage > 0) {
RequestPartyHeal(); //Всегда проверяем, нужно ли слать запрос на хил в пати.
}
if (attacker instanceof FakePlayer fake && fake.isWild() && !player_actor.isFactionEnemy(fake)) {
return;
}
if (damage != 0 && !(attacker instanceof FakePlayer)) {
AddPCHate(attacker, damage, true, 300);
}
if (damage == 0 && skill_name_id != 0 && !(attacker instanceof FakePlayer)) {
AddPCHate(attacker, 100, true, 300);
}
if (damage != 0 || skill_name_id != 0) {
EquipWeaponPC(); //Всегда проверяем надета ли пушка, когда нас бьют. Если нет, надеваем.
SummonServitor(1000); //Всегда проверяем, нужно ли суммонить сервитора.
}
double desire = EDesire.get.byDamage(damage, player_actor);
if (attacker.isBlockMove() && (player_actor.getAI().battle_distance.get() > attacker.getStats().getPhysicalAttackRange() || player_actor.can_away) || player_actor.isClanMember(attacker) || player_actor.isPartyMember(attacker) || Chance(player_actor.getAI().regroup_chance.get()) && DistancePC(attacker, false) < player_actor.getAI().battle_distance.get() && (player_actor.can_away || attacker.getStats().calcCurrentMoveSpeed() <= player_actor.getStats().calcCurrentMoveSpeed())) {
if (!TryAway(attacker, EDesire.get.extra_high())) {
AddMoveToDesire(PositionUtils.findAroundPosition(player_actor, player_actor.getAI().battle_distance.get() - 50, player_actor.getAI().battle_distance.get() + 50, player_actor.getReflectionID()), EDesire.get.high());
}
if (!(player_actor.isClanMember(attacker) || player_actor.isPartyMember(attacker))) {
DoAttack(attacker, desire - 1, false);
}
return;
}
if (attacker.distance3D(player_actor) > player_actor.getAI().battle_distance.get() && player_actor.getHateList().getHate(attacker) > 5000 || attacker.getStats().calcMoveSpeed(EMoveType.MT_FAST) > player_actor.getStats().calcMoveSpeed(EMoveType.MT_FAST)) {
TryCatch(attacker, desire * 2);
}
DoAttack(attacker, desire, false);
}
}
}
@Override
public void ABNORMAL_STATUS_CHANGED(ISharedCreature speller, long skill_name_id, int skill_id, int skill_level) {
if (getNASCActor() instanceof Player player_actor) {
Skill skill = GetSkill(skill_name_id);
if (skill == null) {
return;
}
//Дебафы из SOA, которые означают, что бот попытался убить РБ и тот его проклял. Это гг и бота надо убирать.
//s_seed_of_annihilation_bestacon_silence1
//s_seed_of_annihilation_cocracon_silence1
//s_seed_of_annihilation_torum_ba_turn_stone1
if ((skill_name_id== 435814401 || skill_name_id == 435879937 || skill_name_id == 419823617) && player_actor instanceof FakePlayer fake_actor && fake_actor.isWild()) {
player_actor.logout(ELogoutType.KICK);
return;
}
//Цикличные дебафы, которые вызывают сами себя. Ботов они не убивают, а висят бесконечно.
//s_npc_deadly_poison
//s_npc_deadly_bleed
if ((skill_id == 6815 || skill_id == 6816) && player_actor instanceof FakePlayer fake_actor && fake_actor.isWild()) {
if (player_actor.getEffectBySkillId(skill_id) instanceof Effect effect) {
effect.stop(true);
}
return;
}
//Если положили дебаф, смотрим, есть ли у нас что-то, что может его снять.
if (skill.isDebuff() && skill_level > 0) {
if (!TryDispellDebuff(player_actor, skill.getAbnormalType(), skill.getAbnormalLevel(), EDesire.get.high())) {
RequestPartyDispell(skill.getAbnormalType(), skill.getAbnormalLevel());
}
}
//Если кончился дизарм, то шедулим надевание пухи
if (Skill_ContainSubEffect(skill, p_disarm.class) && skill_level == 0) {
EquipWeaponPC();
}
if (skill.containSubEffect(p_transform.class)) {
player_actor.doSelfAnalysis();
player_actor.getAI().changeTactics();
}
if (skill.containSubEffect(p_block_move.class) && CategoryDataHolder.isInCategory(INASCConstant.fighter_group, player_actor) && CategoryDataHolder.isInCategory(INASCConstant.mage_group, speller)) {
player_actor.getAI().changeWeapon(skill_level > 0, skill_level <= 0);
}
}
}
@Override
public void USE_SKILL_FINISHED(long skill_name_id, ISharedCreature sTarget, int success) {
if (getNASCActor() instanceof Player player_actor) {
if (sTarget instanceof Creature cTarget) {
RequestPartyRecharge();
if ((player_actor.isClanMember(cTarget) || player_actor.isPartyMember(cTarget))) {
StopPCHate(cTarget);
return;
}
if (cTarget.isDead()) {
StopPCHate(cTarget);
return;
}
if (player_actor.getHateList().getHate(cTarget) <= 0) {
return;
}
Skill skill = SkillTable.getInstance().getInfo(skill_name_id);
if (CategoryDataHolder.isInCategory(heal_master2_3, player_actor)) {
if (skill != null && skill.isGood()) {
return;
}
}
DoAttack(cTarget, EDesire.get.normal(5000), skill != null && skill.getNextAction() == ENextSkillAction.attack);
}
}
}
@Override
public void ATTACK_FINISHED(ISharedCreature sTarget) {
if (getNASCActor() instanceof Player player_actor) {
if (sTarget instanceof Creature cTarget) {
if (player_actor.isClanMember(cTarget) || player_actor.isPartyMember(cTarget)) {
StopPCHate(cTarget);
return;
}
if (cTarget.isDead()) {
StopPCHate(cTarget);
return;
}
if (player_actor.getHateList().getHate(cTarget) <= 0) {
return;
}
DoAttack(cTarget, EDesire.get.normal(5000), true);
}
}
}
//Кастомные методы
@Override
public void PARTIAL_MOVE_FINISH(int x, int y, int z){
if (getNASCActor() instanceof FakePlayer fake_actor) {
Location target_loc = new Location(x, y, z);
if (!target_loc.isEmptyPoint(GeoData.WORLD_MAP_MIN_X, GeoData.WORLD_MAP_MAX_X, GeoData.WORLD_MAP_MIN_Y, GeoData.WORLD_MAP_MAX_Y) && target_loc.distance2D(fake_actor) > 200) {
AddMovePartialDesire(target_loc, 5000, EDesire.get.small());
} else if (!target_loc.isEmptyPoint(GeoData.WORLD_MAP_MIN_X, GeoData.WORLD_MAP_MAX_X, GeoData.WORLD_MAP_MIN_Y, GeoData.WORLD_MAP_MAX_Y) && target_loc.distance2D(fake_actor) <= 200) {
fake_actor.setNextLoc(null);
}
}
}
@Override
public void MOVE_TO_NPC_FINISH(int target_object_id, int next_action_id, Object object1, Object object2){
if (getNASCActor() instanceof FakePlayer fake_actor) {
Creature target = World.getObjects().getWorldObjectAs(target_object_id, Creature.class);
if (target != null) {
try {
switch (next_action_id) {
case MTN_TELEPORT -> { //Teleport, after move finishing
if (fake_actor.isAlive() && object1 instanceof Location temp_loc) {
if (fake_actor.getMasterUser() instanceof Player master && master.isGM()) {
fake_actor.whisperTo("[NPC: " + target.getName() + "][Телепорт: " + temp_loc.toString() + "]", master);
}
fake_actor.teleToLocation(temp_loc.getX(), temp_loc.getY(), temp_loc.getZ(), temp_loc.getReflectionID());
}
}
case MTN_BYPASS_NPC -> { //Request Bypass, after move finishing
if (fake_actor.isAlive() && object1 instanceof String bypass) {
try {
if (target instanceof Npc npc) {
fake_actor.setLastNpc(npc);
fake_actor.setSessionVar(IVarsSessionable.FAKE_BYPASS_NPC, target_object_id);
if (fake_actor.getMasterUser() instanceof Player master && master.isGM()) {
fake_actor.whisperTo("[NPC: " + npc.getName() + "][Bypass: " + bypass + "]", master);
}
}
fake_actor.getBypassHandler().checkBypass(bypass, false);
} finally {
fake_actor.unsetSessionVar(IVarsSessionable.FAKE_BYPASS_NPC);
}
}
}
}
} catch (Exception ignored) {
}
}
}
}
@Override
public void CHAT(int sender_object_id, int chat_type, String message) {
if (getNASCActor() instanceof FakePlayer fake_actor) {
Player sender = World.getObjects().getPlayerByObjectID(sender_object_id);
if (sender != null && fake_actor.isMyMaster(sender)) {
switch (chat_type) {
case 3 -> { //ESayPacketType.PARTY
String answer = "";
if (message.equalsIgnoreCase("ближе")) {
answer = "+";
fake_actor.close = true;
} else if (message.equalsIgnoreCase("дальше")) {
answer = "+";
fake_actor.close = false;
}
if (!answer.isEmpty() && !answer.isBlank()) {
fake_actor.sayToParty(answer);
}
}
}
}
}
}
@Override
public void PARTY_DIED(ISharedCreature party_private, ISharedCreature killer) {
if (getNASCActor() instanceof Player player_actor) {
if (party_private instanceof Servitor servitor && servitor.getPlayer() == player_actor) {
SummonServitor(TimeUnit.SECONDS.toMillis(servitor.getTemplate().corpse_time + 1));
}
}
}
@Override
public void PARTY_JOIN() {
if (getNASCActor() instanceof FakePlayer fake_actor) {
if (fake_actor.isSlave() && fake_actor.getMasterUser() instanceof Player master && master.isReal()) {
Player requestor = fake_actor.getTransactionRequester();
fake_actor.setTransactionRequester(null);
if (requestor == null) {
return;
}
if (requestor.isFake()) {
return;
}
if (requestor.isCursedWeaponEquipped() || fake_actor.isCursedWeaponEquipped()) {
return;
}
if (!requestor.equals(master) && !requestor.isPartyMember(master)) {
return;
}
requestor.setTransactionRequester(null);
if (requestor.getParty() == null) {
return;
}
if (fake_actor.getTransactionType() != ETransactionType.PARTY || fake_actor.getTransactionType() != requestor.getTransactionType() && requestor != master && !requestor.isPartyMember(master)) {
return;
}
if (fake_actor.getSessionVar("event_team_pvp", String.class) != null && fake_actor.getTeam() != requestor.getTeam()) {
return;
}
if (requestor.getParty().member_count() >= 9) {
requestor.sendSysMessage(S_SYSTEM_MSG.m155_THE_PARTY_IS_FULL);
return;
}
fake_actor.joinParty(requestor.getParty());
fake_actor.getParty().broadcastToPartyMembersExclude(fake_actor, new S_PARTY_MEMBER_POSITION(fake_actor));
for (Player member : fake_actor.getParty().getPartyMembers()) {
StopPCHate(member);
RemovePCAttackDesire(member.getObjectId());
if (member instanceof FakePlayer fake) {
StopPCHate(fake_actor);
RemovePCAttackDesire(fake_actor.getObjectId());
}
if (fake_actor.isMyMaster(member)) {
AddFollowDesire2(member, 100, eAFD2_FT_DIST_AND_DEGREE, 120 + Rnd.getInt(0, 50, true), fake_actor.follow_angle);
}
}
fake_actor.getTargetSelector().block();
} else if (fake_actor.isWildPrivate() && fake_actor.getMasterUser() instanceof FakePlayer master && master.isWild()) {
Player requestor = fake_actor.getTransactionRequester();
fake_actor.setTransactionRequester(null);
if (requestor == null) {
return;
}
if (requestor.isReal()) {
return;
}
if (requestor.isCursedWeaponEquipped() || fake_actor.isCursedWeaponEquipped()) {
return;
}
if (!requestor.equals(master)) {
return;
}
requestor.setTransactionRequester(null);
if (requestor.getParty() == null) {
return;
}
if (fake_actor.getTransactionType() != ETransactionType.PARTY || fake_actor.getTransactionType() != requestor.getTransactionType() && requestor != master && !requestor.isPartyMember(master)) {
return;
}
if (fake_actor.getSessionVar("event_team_pvp", String.class) != null && fake_actor.getTeam() != requestor.getTeam()) {
return;
}
if (requestor.getParty().member_count() >= 9) {
return;
}
fake_actor.joinParty(requestor.getParty());
for (Player member : fake_actor.getParty().getPartyMembers()) {
StopPCHate(member);
RemovePCAttackDesire(member.getObjectId());
if (member instanceof FakePlayer fake) {
StopPCHate(fake_actor);
RemovePCAttackDesire(fake_actor.getObjectId());
}
if (fake_actor.isMyMaster(member)) {
AddFollowDesire2(member, 100, eAFD2_FT_DIST_AND_DEGREE, 120 + Rnd.getInt(0, 50, true), fake_actor.follow_angle);
}
}
fake_actor.getTargetSelector().block();
}
}
}
@Override
public void PARTY_LEFT() {
if (getNASCActor() instanceof Player player_actor) {
player_actor.getTargetSelector().unblock();
RemovePCDesire(EPState.PSTATE_FOLLOW);
}
}
@Override
public void CMD_FOLLOW_ME() {
if (getNASCActor() instanceof FakePlayer fake_actor) {
if (fake_actor.getMasterUserID() != 0) {
Party party = fake_actor.getParty();
if (party != null && party.getPartyLeaderOID() == fake_actor.getMasterUserID()) {
Player leader = party.getPartyLeader();
if (leader != null) {
RemoveAllPCHateInfoIF(COND_ALL, 0);
RemoveAllPCDesire();
AddMoveToDesire(leader.getX(), leader.getY(), leader.getZ(), EDesire.get.max());
}
}
}
}
}
@Override
public void PARTY_MEMBER_LEFT() {
if (getNASCActor() instanceof FakePlayer fake_actor) {
if (fake_actor.getParty() instanceof Party party) {
for (Player member : party.getPartyMembers()) {
if (member.getObjectId() == fake_actor.getMasterUserID()) { //Мы не выходим из пати, пока наш мастер в ней.
return;
}
}
party.tryLeaveParty(fake_actor);
}
}
}
@Override
public void REVIVE_REQUEST(int requester_object_id, int pet) {
if (getNASCActor() instanceof FakePlayer fake_actor) {
Creature reviever = World.getObjects().getWorldObjectAs(requester_object_id, Creature.class);
if (fake_actor.death_count.get() <= 0) {
if (reviever != null) {
fake_actor.whisperTo("Даже не пытайся!", reviever);
}
return;
}
if (reviever != null && (fake_actor.isPartyMember(reviever) || fake_actor.isClanMember(reviever))) {
fake_actor.stopTask(EFutureType.PLAYER_AI_REQUEST_RESURRECT_TASK);
fake_actor.stopTask(EFutureType.FAKE_PLAYER_LOGOUT_TASK);
fake_actor.reviveAnswer(1);
if (pet == 1) {
ThreadPoolService.getInstance().schedule(() -> fake_actor.rebuff(true, true), 3000);
}
} else {
fake_actor.reviveAnswer(0);
}
}
}
@Override
public void PARTY_ACTION_REQUEST(int help_type, int requester_object_id, Object object1, Object object2) {
if (getNASCActor() instanceof FakePlayer fake_actor) {
Creature creature = World.getObjects().getWorldObjectAs(requester_object_id, Creature.class);
if (creature instanceof Player requester && fake_actor.isPartyMember(requester)) {
if (help_type == AT_ATTACK && object1 instanceof Creature target_creature && object2 instanceof Number desire) {
if (target_creature.getObjectId() == fake_actor.getAI().current_attacked_target.get()) {
return;
}
if (fake_actor.getAI().af_protect_master.get() && !fake_actor.isMyMaster(requester)) {
return;
}
double chance = 0;
if (EDesire.get.normal() < desire.doubleValue()) {
chance = 75;
} else {
chance = 30;
}
if (fake_actor.isMyMaster(requester)) {
chance += 20;
}
if (!fake_actor.isInCombat()) {
chance += 20;
} else {
if (fake_actor.getStats().getCurrentHpPercents() < 30) {
chance -= 30;
} else {
chance -= 10;
}
}
if (fake_actor.distance3D(target_creature) > 1000) {
chance -= 15;
} else {
if (fake_actor.distance3D(target_creature) > 700) {
chance -= 5;
} else {
chance += (1000 - fake_actor.distance3D(target_creature)) / 100;
}
}
if (Rnd.chance(chance)) {
DoAttack(target_creature, desire.doubleValue(), false);
}
} else if (help_type == AT_PROTECT && object1 instanceof Creature attacker && object2 instanceof Number desire) {
if (attacker.getObjectId() == fake_actor.getAI().current_attacked_target.get()) {
return;
}
if (fake_actor.getAI().af_protect_master.get() && !fake_actor.isMyMaster(requester)) {
return;
}
double chance = 0;
if (EDesire.get.normal() < desire.doubleValue()) {
chance = 75;
} else {
chance = 30;
}
if (fake_actor.isMyMaster(requester) || (CategoryDataHolder.isInCategory(heal_master2_3, requester))) {
chance += 30;
}
if (!fake_actor.isInCombat()) {
chance += 20;
} else {
if (fake_actor.getStats().getCurrentHpPercents() < 30) {
chance -= 30;
} else {
chance -= 10;
}
}
if (fake_actor.distance3D(requester) > 1000) {
chance -= 15;
} else {
if (fake_actor.distance3D(requester) > 700) {
chance -= 5;
} else {
chance += (1000 - fake_actor.distance3D(requester)) / 100;
}
}
if (Rnd.chance(chance)) {
DoAttack(attacker, desire.doubleValue(), false);
}
}
switch (help_type) {
case AT_HEAL -> {
if (object1 instanceof Number hp_percent && object2 instanceof Number counter) {
double actual_hp_percent = requester.getStats().getCurrentHpPercents();
if (actual_hp_percent > 30 && !CategoryDataHolder.isInCategory(heal_master2_3, fake_actor)) {
return;
}
if (actual_hp_percent < hp_percent.doubleValue() - 5 || Rnd.chance(100 - hp_percent.doubleValue()) || counter.intValue() > 0) {
TryHeal(requester, counter.intValue(), EDesire.get.high());
}
}
}
case AT_RECHARGE -> {
if (object1 instanceof Number mp_percent && object2 instanceof Number counter) {
double actual_mp_percent = requester.getStats().getCurrentMpPercents();
if (actual_mp_percent < mp_percent.doubleValue() - 5 || Rnd.chance(100 - mp_percent.doubleValue()) || counter.intValue() > 0) {
TryRecharge(requester, counter.intValue(), EDesire.get.high());
}
}
}
case AT_DISPELL -> {
if (object1 instanceof EAbnormalStatusSlotType abnormal && object2 instanceof Number level) {
TryDispellDebuff(requester, abnormal, level.intValue(), EDesire.get.high());
}
}
case AT_BUFF -> {
}
case AT_RESURRECT -> {
int chance = switch (fake_actor.getDifficulty()) {
case EASY -> 10;
case NORMAL -> 20;
case MANUAL, HARD -> 30;
case EXTRA_HARD -> 50;
default -> 0;
};
if (!TryResurrect(requester, chance * 2, EDesire.get.high())) {
if (Rnd.chance(chance)) {
Item item = fake_actor.getInventory().getItemBySkillSubEffect(i_resurrection.class);
if (item != null) {
if (fake_actor.distance3D(requester) <= 100) {
fake_actor.executeMessage(new UseItemAction(fake_actor, requester, item, false));
} else {
AddMoveToTargetDesire(requester,90,-1, EDesire.get.extra_high());
}
}
}
}
}
case AT_SUMMON -> {
}
case AT_ESCAPE -> {
final Item item = fake_actor.getInventory().getItemBySkillSubEffect(i_escape.class);
if (item != null) {
fake_actor.executeMessage(new UseItemAction(fake_actor, fake_actor, item, false));
}
}
case AT_CMD_ATTACK -> {
if (fake_actor.getAI().af_protect_master.get()) {
return;
}
if (fake_actor.isMyMaster(requester) && object1 instanceof Number number) {
int target_object_id = number.intValue();
if (target_object_id == fake_actor.getAI().current_attacked_target.get()) {
return;
}
Creature target = World.getObjects().getWorldObjectAs(target_object_id, Creature.class);
if (target != null) {
fake_actor.getAI().high_priority_target = target_object_id;
RemoveAllPCAttackDesire();
DoAttack(target, EDesire.get.extra_high(500), false);
}
}
}
case AT_CMD_STOP -> {
if (fake_actor.isMyMaster(requester)) {
try {
fake_actor.setTarget(null, EChangeTargetReason.CTR_BY_USER);
fake_actor.getAI().high_priority_target = 0;
fake_actor.getAI().current_attacked_target.set(0);
RemoveAllPCHateInfoIF(COND_ALL, 0);
RemoveAllPCDesire();
RemoveAllPCAttackDesire();
AddFollowDesire2(requester, 100, eAFD2_FT_DIST_AND_DEGREE, 120 + Rnd.getInt(0, 50, true), fake_actor.follow_angle);
AddMoveToDesire(PositionUtils.getPointInRadius(fake_actor.getLoc(), requester.getLoc(), Rnd.getInt(50, 75, true), fake_actor.follow_angle), 200);
if (fake_actor.getServitor() instanceof Pet pet) {
MakeServitorAction(requester, 100, 17, -2);
} else if (fake_actor.getServitor() instanceof Summon summon) {
MakeServitorAction(requester, 100, 23, -2);
}
} finally {
fake_actor.setTarget(null, EChangeTargetReason.CTR_BY_USER);
}
}
}
case AT_CMD_PICKUP -> {
if (fake_actor.isMyMaster(requester) && object1 instanceof Number number) {
Item item_to_pickup = World.getObjects().getWorldObjectAs(number.intValue(), Item.class);
if (item_to_pickup != null) {
AddGetItemDesireEx(item_to_pickup, EDesire.get.extra_high());
}
}
}
}
}
}
}
@Override
public void CUBIC_DISAPPEAR(int cubic_id, int cubic_level, long skill_index) {
if (getNASCActor() instanceof Player player_actor) {
long[] cubics = SelectSkillsForSummonCubic(cubic_id);
if (cubics.length > 0) {
AddUseSkillDesireEx(player_actor, cubics[0], ST_HEAL, AMT_STAND, TRUE, EDesire.get.normal(), 0);
}
}
}
@Override
public void BUFFER_EFFECT_REMOVED(){
if (getNASCActor() instanceof Player player_actor) {
player_actor.getAI().buff_removed_count.incrementAndGet();
}
}
@Override
public void TIMER_FIRED_EX(int timer_id, Object arg1, Object arg2) {
if (getNASCActor() instanceof FakePlayer fake_actor) {
if (timer_id == CHECK_SPAWN_AFK) {
boolean near = fake_actor.getController() != null && fake_actor.distance3D(fake_actor.getController()) < 300;
if (near && fake_actor.isAlive() && !fake_actor.isInCombat()) {
Location loc = PositionUtils.findAroundPosition(fake_actor.getLoc(), 500, 1000, fake_actor.getReflectionID());
if (fake_actor.getZ() > loc.getZ()) {
fake_actor.teleToLocation(loc);
} else {
AddTimerEx(CHECK_SPAWN_AFK, 250);
}
}
}
}
super.TIMER_FIRED_EX(timer_id, arg1, arg2);
}
@Override
public void SERVITOR_SUMMON_FINISHED() {
if (getNASCActor() instanceof Player player_actor) {
player_actor.rebuff(true, true);
if (player_actor.hasComponent(EComponentType.ITEM_SELECTOR)) {
final List<Item> snapshot = player_actor.getInventory().getItemsSnapshot();
player_actor.getItemSelector().items.stream()
.map(id -> player_actor.getInventory().getItemByItemId(id, snapshot))
.filter(Objects::nonNull)
.filter(item -> item.getTemplate().getAction().isSummonSoulShot())
.forEach(item -> new AutoSoulShotItemAction(player_actor, item.getItemId(), true));
}
}
}
@Override
public void MY_DYING(ISharedCreature sLast_attacker) {
if (getNASCActor() instanceof FakePlayer fake_actor) {
fake_actor.addTaskIfAbsent(EFutureType.PLAYER_AI_REQUEST_RESURRECT_TASK, this::RequestPartyResurrect, 2000, 5000);
if (fake_actor.isWild() && sLast_attacker instanceof Player player) {
if (Rnd.chance(fake_actor.getDifficulty().ordinal() * 15)) {
World.getInstance().getAroundObjects(fake_actor, FakePlayer.class, false, 500, 50)
.stream()
.filter(Creature::isAlive)
.filter(FakePlayer::isWild)
.forEach(fake -> {
AddPCHate(player, 10000 * fake_actor.getDifficulty().ordinal(), true, 60);
EventNotifier.getInstance().notify(fake, ENASCEvent.RECHECK_TARGET);
});
}
}
}
}
@Override
public void DIE_SET(ISharedCreature sDied) {
if (getNASCActor() instanceof Player player_actor) {
if (sDied instanceof Creature died && died.isDead()) {
if (died instanceof Warrior mob) {
for (ISharedCreature creature : mob.getMostDamage(5)) {
if (creature instanceof Player player && player.isReal() && player_actor.distance3D(player) <= 2000) {
AddPCHate(player, 50000, true, 60);
}
}
}
if (player_actor.getHateList().getHate(died) > 0) {
StopPCHate(died);
}
RemovePCAttackDesire(died.getObjectId());
EventNotifier.getInstance().notify(player_actor, ENASCEvent.RECHECK_TARGET);
}
}
}
@Override
public void START_COMBAT() {
if (getNASCActor() instanceof Player player_actor) {
if (player_actor.isAlive()) {
TryToogles(true);
}
player_actor.getHateList().clearAllSnapshots();
player_actor.addTaskIfAbsent(EFutureType.FAKE_PLAYER_HATELIST_SNAPSHOTS_TASK, player_actor.getAI()::doHateSnapshot, 0, 30, TimeUnit.SECONDS);
}
}
@Override
public void STOP_COMBAT() {
if (getNASCActor() instanceof Player player_actor) {
if (player_actor.isAlive()) {
TryToogles(false);
}
player_actor.stopTask(EFutureType.FAKE_PLAYER_HATELIST_SNAPSHOTS_TASK);
}
}
}