Механика агра

  • Автор темы Автор темы nesss
  • Дата начала Дата начала

nesss

Пляшущий с бубном
Участник
Сообщения
235
Розыгрыши
0
Решения
3
Репутация
-2
Реакции
23
Баллы
230
Хроники
  1. Interlude
Исходники
Присутствуют
Сборка
Собственная
Всем привет, подскажите пожалуйста механику скилов агресии, интересует поведение применения на мобов, а также на персонажей и их петов, листаю сборки, все по разному реализуют. Есть ли допустим формула расчета шанса прохождения? Спасибо.
 
Смотрел, она этот момент вскольз затрагивает, не объясняет те вопросы, что я задал.
 
nesss, ну вот что есть в тоталчекере
Код:
skill_begin    skill_name = [s_hate11]    /* [헤이트] */    skill_id = 28    level = 1    operate_type = A2    magic_level = 22    self_effect = {}    effect = {{p_target_me};{i_get_agro}}    end_effect = {}    is_magic = 0    mp_consume2 = 0    cast_range = 400    effective_range = 900    skill_hit_time = 0.7    skill_cool_time = 0.2    skill_hit_cancel_time = 0.5    reuse_delay = 6    reuse_delay_lock = 1    activate_rate = -1    lv_bonus_rate = 0    basic_property = none    abnormal_time = 3    abnormal_lv = 1    abnormal_type = target_lock    abnormal_instant = 0    irreplaceable_buff = 0    buff_protect_level = 0    attribute = {attr_none;0}    trait = {trait_none}    effect_point = -3928    target_type = enemy_only    affect_scope = single    affect_limit = {0;0}    next_action = none    debuff = 1    ride_state = {@ride_none}    multi_class = 0    olympiad_use = 1    skill_end
C++:
 char __fastcall CSkillEffect_i_get_agro::Instant(
        CSkillEffect_i_get_agro *this,
        CCreature *pSkillUser,
        CWorldObject *pTarget,
        const CSkillInfo *pSkillInfo)
{
  unsigned int m_nId; // edi
  unsigned int v7; // esi
  int v9; // [rsp+20h] [rbp-28h]
  unsigned int v10; // [rsp+28h] [rbp-20h]
  int v11; // [rsp+30h] [rbp-18h]

  if ( !((unsigned __int8 (__fastcall *)(CWorldObject *, CCreature *, CWorldObject *, const CSkillInfo *))pTarget->IsNPC)(
          pTarget,
          pSkillUser,
          pTarget,
          pSkillInfo)
    || !pTarget->IsVisible(pTarget) )
  {
    return 0;
  }

  m_nId = pSkillUser->m_nId;
  v7 = pTarget->m_nId;
  v11 = pSkillUser->GetIndex(pSkillUser);
  v10 = m_nId;
  v9 = pTarget->GetIndex(pTarget);
  NpcServer::Send(&g_npcserver, "cdddd", 146i64, v7, v9, v10, v11);
  return 1;
}


void __fastcall CSkillEffect_i_get_agro::CSkillEffect_i_get_agro(CSkillEffect_i_get_agro *this)
{
  *(_QWORD *)&this->nUnitTick = 0i64;
  this->effectCondList._Mypair._Myval2._Myfirst = 0i64;
  this->effectCondList._Mypair._Myval2._Mylast = 0i64;
  this->effectCondList._Mypair._Myval2._Myend = 0i64;
  this->__vftable = (CSkillEffect_i_get_agro_vtbl *)&CSkillEffect_i_get_agro::`vftable';
}


CSkillEffect_i_get_agro *__fastcall CSkillEffect_i_get_agro::`vector deleting destructor'(
        CSkillEffect_i_get_agro *this,
        char a2)
{

  CEffectCondition **Myfirst; // rdx

  this->__vftable = (CSkillEffect_i_get_agro_vtbl *)&CSkillEffect::`vftable';
  Myfirst = this->effectCondList._Mypair._Myval2._Myfirst;
  if ( Myfirst )
  {
    Memory::Free(&g_Memory, Myfirst, 1);
    this->effectCondList._Mypair._Myval2._Myfirst = 0i64;
    this->effectCondList._Mypair._Myval2._Mylast = 0i64;
    this->effectCondList._Mypair._Myval2._Myend = 0i64;
  }

  if ( (a2 & 1) != 0 )
    operator delete(this, 0x28ui64);
  return this;
}

C++:
 char __fastcall CSkillEffect_p_target_me::PumpEnd(
        CSkillEffect_p_target_me *this,
        CCreature *target,
        CCreature *__formal,
        const CSkillInfo *pSkillInfo)
{

  int *p_m_TargetMeCount; // rcx
  int m_TargetMeCount; // eax
  int *v8; // rax
  int v9; // [rsp+38h] [rbp+10h] BYREF

  if ( !((unsigned __int8 (__fastcall *)(CCreature *, CCreature *, CCreature *, const CSkillInfo *))target->IsPC)(
          target,
          target,
          __formal,
          pSkillInfo) )
    return 0;

  p_m_TargetMeCount = &target->m_SkillDurationMod.m_TargetMeCount;
  m_TargetMeCount = target->m_SkillDurationMod.m_TargetMeCount;

  if ( m_TargetMeCount <= 0 )
    return 0;

  v9 = 0;
  *p_m_TargetMeCount = m_TargetMeCount - 1;
  v8 = &v9;

  if ( *p_m_TargetMeCount > 0 )
    v8 = &target->m_SkillDurationMod.m_TargetMeCount;
  *p_m_TargetMeCount = *v8;

  return 1;
}


char __fastcall CSkillEffect_p_target_me::PumpStart(
        CSkillEffect_p_target_me *this,
        CCreature *target,
        CCreature *pCaster,
        const CSkillInfo *pSkillInfo)
{

  __int64 Shuttle; // rax
  _BOOL8 v7; // r8

  if ( !pCaster || !target->IsPC(target) )
    return 0;

  Shuttle = CSmartID::GetShuttle((__crt_locale_data *)&target->m_spTarget);

  if ( !Shuttle || pCaster->m_nId != *(_DWORD *)(Shuttle + 24) )
  {
    LOBYTE(v7) = target->m_AreaMod.m_bIsInBattleField;
    target->Action(target, pCaster, v7, 0);
  }

  ++target->m_SkillDurationMod.m_TargetMeCount;

  return 1;

}


void __fastcall CSkillEffect_p_target_me::CSkillEffect_p_target_me(CSkillEffect_p_target_me *this)
{
  *(_QWORD *)&this->nUnitTick = 0i64;
  this->effectCondList._Mypair._Myval2._Myfirst = 0i64;
  this->effectCondList._Mypair._Myval2._Mylast = 0i64;
  this->effectCondList._Mypair._Myval2._Myend = 0i64;
  this->__vftable = (CSkillEffect_p_target_me_vtbl *)&CSkillEffect_p_target_me::`vftable';
}


CSkillEffect_p_target_me *__fastcall CSkillEffect_p_target_me::`vector deleting destructor'(
        CSkillEffect_p_target_me *this,
        char a2)
{

  CEffectCondition **Myfirst; // rdx

  this->__vftable = (CSkillEffect_p_target_me_vtbl *)&CSkillEffect::`vftable';
  Myfirst = this->effectCondList._Mypair._Myval2._Myfirst;
  if ( Myfirst )
  {
    Memory::Free(&g_Memory, Myfirst, 1);
    this->effectCondList._Mypair._Myval2._Myfirst = 0i64;
    this->effectCondList._Mypair._Myval2._Mylast = 0i64;
    this->effectCondList._Mypair._Myval2._Myend = 0i64;
  }

  if ( (a2 & 1) != 0 )
    operator delete(this, 0x28ui64);
  return this;
}
 
Запрещено публиковать исходный код без BB-кода — CODE
nesss, ну вот что есть в тоталчекере
Код:
skill_begin    skill_name = [s_hate11]    /* [헤이트] */    skill_id = 28    level = 1    operate_type = A2    magic_level = 22    self_effect = {}    effect = {{p_target_me};{i_get_agro}}    end_effect = {}    is_magic = 0    mp_consume2 = 0    cast_range = 400    effective_range = 900    skill_hit_time = 0.7    skill_cool_time = 0.2    skill_hit_cancel_time = 0.5    reuse_delay = 6    reuse_delay_lock = 1    activate_rate = -1    lv_bonus_rate = 0    basic_property = none    abnormal_time = 3    abnormal_lv = 1    abnormal_type = target_lock    abnormal_instant = 0    irreplaceable_buff = 0    buff_protect_level = 0    attribute = {attr_none;0}    trait = {trait_none}    effect_point = -3928    target_type = enemy_only    affect_scope = single    affect_limit = {0;0}    next_action = none    debuff = 1    ride_state = {@ride_none}    multi_class = 0    olympiad_use = 1    skill_end
C++:
 char __fastcall CSkillEffect_i_get_agro::Instant(
        CSkillEffect_i_get_agro *this,
        CCreature *pSkillUser,
        CWorldObject *pTarget,
        const CSkillInfo *pSkillInfo)
{
  unsigned int m_nId; // edi
  unsigned int v7; // esi
  int v9; // [rsp+20h] [rbp-28h]
  unsigned int v10; // [rsp+28h] [rbp-20h]
  int v11; // [rsp+30h] [rbp-18h]

  if ( !((unsigned __int8 (__fastcall *)(CWorldObject *, CCreature *, CWorldObject *, const CSkillInfo *))pTarget->IsNPC)(
          pTarget,
          pSkillUser,
          pTarget,
          pSkillInfo)
    || !pTarget->IsVisible(pTarget) )
  {
    return 0;
  }

  m_nId = pSkillUser->m_nId;
  v7 = pTarget->m_nId;
  v11 = pSkillUser->GetIndex(pSkillUser);
  v10 = m_nId;
  v9 = pTarget->GetIndex(pTarget);
  NpcServer::Send(&g_npcserver, "cdddd", 146i64, v7, v9, v10, v11);
  return 1;
}


void __fastcall CSkillEffect_i_get_agro::CSkillEffect_i_get_agro(CSkillEffect_i_get_agro *this)
{
  *(_QWORD *)&this->nUnitTick = 0i64;
  this->effectCondList._Mypair._Myval2._Myfirst = 0i64;
  this->effectCondList._Mypair._Myval2._Mylast = 0i64;
  this->effectCondList._Mypair._Myval2._Myend = 0i64;
  this->__vftable = (CSkillEffect_i_get_agro_vtbl *)&CSkillEffect_i_get_agro::`vftable';
}


CSkillEffect_i_get_agro *__fastcall CSkillEffect_i_get_agro::`vector deleting destructor'(
        CSkillEffect_i_get_agro *this,
        char a2)
{

  CEffectCondition **Myfirst; // rdx

  this->__vftable = (CSkillEffect_i_get_agro_vtbl *)&CSkillEffect::`vftable';
  Myfirst = this->effectCondList._Mypair._Myval2._Myfirst;
  if ( Myfirst )
  {
    Memory::Free(&g_Memory, Myfirst, 1);
    this->effectCondList._Mypair._Myval2._Myfirst = 0i64;
    this->effectCondList._Mypair._Myval2._Mylast = 0i64;
    this->effectCondList._Mypair._Myval2._Myend = 0i64;
  }

  if ( (a2 & 1) != 0 )
    operator delete(this, 0x28ui64);
  return this;
}

C++:
 char __fastcall CSkillEffect_p_target_me::PumpEnd(
        CSkillEffect_p_target_me *this,
        CCreature *target,
        CCreature *__formal,
        const CSkillInfo *pSkillInfo)
{

  int *p_m_TargetMeCount; // rcx
  int m_TargetMeCount; // eax
  int *v8; // rax
  int v9; // [rsp+38h] [rbp+10h] BYREF

  if ( !((unsigned __int8 (__fastcall *)(CCreature *, CCreature *, CCreature *, const CSkillInfo *))target->IsPC)(
          target,
          target,
          __formal,
          pSkillInfo) )
    return 0;

  p_m_TargetMeCount = &target->m_SkillDurationMod.m_TargetMeCount;
  m_TargetMeCount = target->m_SkillDurationMod.m_TargetMeCount;

  if ( m_TargetMeCount <= 0 )
    return 0;

  v9 = 0;
  *p_m_TargetMeCount = m_TargetMeCount - 1;
  v8 = &v9;

  if ( *p_m_TargetMeCount > 0 )
    v8 = &target->m_SkillDurationMod.m_TargetMeCount;
  *p_m_TargetMeCount = *v8;

  return 1;
}


char __fastcall CSkillEffect_p_target_me::PumpStart(
        CSkillEffect_p_target_me *this,
        CCreature *target,
        CCreature *pCaster,
        const CSkillInfo *pSkillInfo)
{

  __int64 Shuttle; // rax
  _BOOL8 v7; // r8

  if ( !pCaster || !target->IsPC(target) )
    return 0;

  Shuttle = CSmartID::GetShuttle((__crt_locale_data *)&target->m_spTarget);

  if ( !Shuttle || pCaster->m_nId != *(_DWORD *)(Shuttle + 24) )
  {
    LOBYTE(v7) = target->m_AreaMod.m_bIsInBattleField;
    target->Action(target, pCaster, v7, 0);
  }

  ++target->m_SkillDurationMod.m_TargetMeCount;

  return 1;

}


void __fastcall CSkillEffect_p_target_me::CSkillEffect_p_target_me(CSkillEffect_p_target_me *this)
{
  *(_QWORD *)&this->nUnitTick = 0i64;
  this->effectCondList._Mypair._Myval2._Myfirst = 0i64;
  this->effectCondList._Mypair._Myval2._Mylast = 0i64;
  this->effectCondList._Mypair._Myval2._Myend = 0i64;
  this->__vftable = (CSkillEffect_p_target_me_vtbl *)&CSkillEffect_p_target_me::`vftable';
}


CSkillEffect_p_target_me *__fastcall CSkillEffect_p_target_me::`vector deleting destructor'(
        CSkillEffect_p_target_me *this,
        char a2)
{

  CEffectCondition **Myfirst; // rdx

  this->__vftable = (CSkillEffect_p_target_me_vtbl *)&CSkillEffect::`vftable';
  Myfirst = this->effectCondList._Mypair._Myval2._Myfirst;
  if ( Myfirst )
  {
    Memory::Free(&g_Memory, Myfirst, 1);
    this->effectCondList._Mypair._Myval2._Myfirst = 0i64;
    this->effectCondList._Mypair._Myval2._Mylast = 0i64;
    this->effectCondList._Mypair._Myval2._Myend = 0i64;
  }

  if ( (a2 & 1) != 0 )
    operator delete(this, 0x28ui64);
  return this;
}
С твоего позволения накину в java коде что бы человек понял что к чему (хотя бы поверхностно).
/**
* Эффект мгновенного скилла "GetAgro".
* Используется, например, для агро-скиллов, отправляющих пакет на NpcServer.
*/
public class GetAgroEffect extends L2Effect {

public GetAgroEffect(Env env, EffectTemplate template) {
super(env, template);
}

@Override
public boolean onInstant(L2Character effector, L2Character effected, L2Skill skill) {
// Проверяем, что цель — NPC и видима
if (!(effected instanceof L2Npc) || !effected.isVisible()) {
return false;
}

L2Character user = effector;
L2Npc target = (L2Npc) effected;

int userId = user.getObjectId();
int targetId = target.getObjectId();
int userIndex = user.getIndex(); // предполагаемый метод
int targetIndex = target.getIndex();

// Отправляем пакет на NpcServer (opcode 146)
NpcServer.getInstance().sendPacket("cdddd", 146, targetId, targetIndex, userId, userIndex);
return true;
}
}

/**
* Эффект "Target Me" (заставляет монстров переключаться на игрока, получившего эффект).
* Накапливает счётчик на персонаже и управляет сменой цели.
*/
public class TargetMeEffect extends L2Effect {

public TargetMeEffect(Env env, EffectTemplate template) {
super(env, template);
// Инициализация списка условий эффекта (аналог effectCondList)
// В Java это можно оставить пустым или реализовать при необходимости.
}

@Override
public void onStart() {
L2Character caster = getEffector();
L2Character target = getEffected();

// Скилл должен применяться к игроку, и кастер должен существовать
if (caster == null || !(target instanceof L2PcInstance)) {
return;
}

L2PcInstance player = (L2PcInstance) target;

// Получаем текущую цель игрока (или другого существа)
L2Object currentTarget = player.getTarget();
int currentTargetId = (currentTarget != null) ? currentTarget.getObjectId() : 0;

// Если игрок не целится в кастера — принудительно меняем цель и выполняем действие
if (currentTarget == null || currentTarget.getObjectId() != caster.getObjectId()) {
boolean isInBattlefield = player.isInBattlefield(); // m_AreaMod.m_bIsInBattleField
player.setTarget(caster);
// Action(target, pCaster, v7, 0) — вероятно, атака или другая реакция
player.doAction(caster, isInBattlefield, false);
}

// Увеличиваем счётчик TargetMe
player.incrementTargetMeCount();
}

@Override
public void onExit() {
L2Character target = getEffected();
if (!(target instanceof L2PcInstance)) {
return;
}

L2PcInstance player = (L2PcInstance) target;

// Уменьшаем счётчик, если он больше нуля
player.decrementTargetMeCount();
}
}

// Дополнительные методы в L2PcInstance (или другом классе игрока)
public class L2PcInstance extends L2Character {
// ...

private int targetMeCount = 0;

public void incrementTargetMeCount() {
targetMeCount++;
}

public void decrementTargetMeCount() {
if (targetMeCount > 0) {
targetMeCount--; // логика гарантирует, что счётчик не станет отрицательным
}
}

public int getTargetMeCount() {
return targetMeCount;
}
}
 
С твоего позволения накину в java коде что бы человек понял что к чему (хотя бы поверхностно).
/**
* Эффект мгновенного скилла "GetAgro".
* Используется, например, для агро-скиллов, отправляющих пакет на NpcServer.
*/
public class GetAgroEffect extends L2Effect {

public GetAgroEffect(Env env, EffectTemplate template) {
super(env, template);
}

@Override
public boolean onInstant(L2Character effector, L2Character effected, L2Skill skill) {
// Проверяем, что цель — NPC и видима
if (!(effected instanceof L2Npc) || !effected.isVisible()) {
return false;
}

L2Character user = effector;
L2Npc target = (L2Npc) effected;

int userId = user.getObjectId();
int targetId = target.getObjectId();
int userIndex = user.getIndex(); // предполагаемый метод
int targetIndex = target.getIndex();

// Отправляем пакет на NpcServer (opcode 146)
NpcServer.getInstance().sendPacket("cdddd", 146, targetId, targetIndex, userId, userIndex);
return true;
}
}

/**
* Эффект "Target Me" (заставляет монстров переключаться на игрока, получившего эффект).
* Накапливает счётчик на персонаже и управляет сменой цели.
*/
public class TargetMeEffect extends L2Effect {

public TargetMeEffect(Env env, EffectTemplate template) {
super(env, template);
// Инициализация списка условий эффекта (аналог effectCondList)
// В Java это можно оставить пустым или реализовать при необходимости.
}

@Override
public void onStart() {
L2Character caster = getEffector();
L2Character target = getEffected();

// Скилл должен применяться к игроку, и кастер должен существовать
if (caster == null || !(target instanceof L2PcInstance)) {
return;
}

L2PcInstance player = (L2PcInstance) target;

// Получаем текущую цель игрока (или другого существа)
L2Object currentTarget = player.getTarget();
int currentTargetId = (currentTarget != null) ? currentTarget.getObjectId() : 0;

// Если игрок не целится в кастера — принудительно меняем цель и выполняем действие
if (currentTarget == null || currentTarget.getObjectId() != caster.getObjectId()) {
boolean isInBattlefield = player.isInBattlefield(); // m_AreaMod.m_bIsInBattleField
player.setTarget(caster);
// Action(target, pCaster, v7, 0) — вероятно, атака или другая реакция
player.doAction(caster, isInBattlefield, false);
}

// Увеличиваем счётчик TargetMe
player.incrementTargetMeCount();
}

@Override
public void onExit() {
L2Character target = getEffected();
if (!(target instanceof L2PcInstance)) {
return;
}

L2PcInstance player = (L2PcInstance) target;

// Уменьшаем счётчик, если он больше нуля
player.decrementTargetMeCount();
}
}

// Дополнительные методы в L2PcInstance (или другом классе игрока)
public class L2PcInstance extends L2Character {
// ...

private int targetMeCount = 0;

public void incrementTargetMeCount() {
targetMeCount++;
}

public void decrementTargetMeCount() {
if (targetMeCount > 0) {
targetMeCount--; // логика гарантирует, что счётчик не станет отрицательным
}
}

public int getTargetMeCount() {
return targetMeCount;
}
}
Ну ты хоть бы код в ВВ запихнул)
Там по идее i_get_agro для мобов, а p_target_me для игроков.
Сообщение объединено:
Что касательно шанса прохождения, то он равен 100%.
Код:
activate_rate = -1
 
Последнее редактирование:
ООО, спасибо, да я и из ассемблера понял все, то есть получается есть 2 ветки скила, target_me и i_get_agro, первый на персонажа второй на монстра, ну я смотрю персонаж агрится без шанса, то есть 100% изменяется таргет и дает команду сервер атаковать цель, при этом эффект не накладывается, как допустим у фира, как бы сбивает персонажа с атаки, тут более мене понятно, хотя смотрел на ява сборках там по разному в одной например сделали что-то типа Random(100) < 75 то есть дали искусственный шанс в 75%, а вот вопрос по поводу петов, на них так же действует как и на персонажей?? и второй вопрос, а вот по поводу монстров, там я так понимаю тоже 100% прохождение просто добавляется хейт, по формуле power * 150 / targetLevel + 7 вроде так если память не подводит?
 
ООО, спасибо, да я и из ассемблера понял все, то есть получается есть 2 ветки скила, target_me и i_get_agro, первый на персонажа второй на монстра, ну я смотрю персонаж агрится без шанса, то есть 100% изменяется таргет и дает команду сервер атаковать цель, при этом эффект не накладывается, как допустим у фира, как бы сбивает персонажа с атаки, тут более мене понятно, хотя смотрел на ява сборках там по разному в одной например сделали что-то типа Random(100) < 75 то есть дали искусственный шанс в 75%, а вот вопрос по поводу петов, на них так же действует как и на персонажей?? и второй вопрос, а вот по поводу монстров, там я так понимаю тоже 100% прохождение просто добавляется хейт, по формуле power * 150 / targetLevel + 7 вроде так если память не подводит?
Ну по идее просто переключает таргет на танка, на 3 секунды, и запрещает сменить цель. То-есть принудительно заставляет взять на время в таргет того, кто применил агр. А вот как влияет павер я если честно хз, надо Aristo сумонить.

А, так у скила и нету павера в принципе. Есть magic_level, и вот он уже скорее и будет отвечать за шанс наложения.
У последнего лвла не точеного агра magic_level равен 52, если противни выше лвлом, то и шанс прохождения будет не 100%.
С повышением лвла скила меняется лишь magic_level, cast_range и effective_range.

Код:
skill_begin    skill_name = [s_hate93]    /* [헤이트] */    skill_id = 28    level = 27    operate_type = A2    magic_level = 52    self_effect = {}    effect = {{p_target_me};{i_get_agro}}    end_effect = {}    is_magic = 0    mp_consume2 = 0    cast_range = 600    effective_range = 1100    skill_hit_time = 0.7    skill_cool_time = 0.2    skill_hit_cancel_time = 0.5    reuse_delay = 6    reuse_delay_lock = 1    activate_rate = -1    lv_bonus_rate = 0    basic_property = none    abnormal_time = 3    abnormal_lv = 1    abnormal_type = target_lock    abnormal_instant = 0    irreplaceable_buff = 0    buff_protect_level = 0    attribute = {attr_none;0}    trait = {trait_none}    effect_point = -8909    target_type = enemy_only    affect_scope = single    affect_limit = {0;0}    next_action = none    debuff = 1    ride_state = {@ride_none}    multi_class = 0    olympiad_use = 1    skill_end

А вот у ветки павер на +30 уже 85 magic_level.
Код:
skill_begin    skill_name = [s_hate_power_30]    /* [헤이트] */    skill_id = 28    level = 130    operate_type = A2    magic_level = 85    self_effect = {}    effect = {{p_target_me};{i_get_agro}}    end_effect = {}    is_magic = 0    mp_consume2 = 0    cast_range = 800    effective_range = 1300    skill_hit_time = 0.7    skill_cool_time = 0.2    skill_hit_cancel_time = 0.5    reuse_delay = 6    reuse_delay_lock = 1    activate_rate = -1    lv_bonus_rate = 0    basic_property = none    abnormal_time = 3    abnormal_lv = 1    abnormal_type = target_lock    abnormal_instant = 0    irreplaceable_buff = 0    buff_protect_level = 0    attribute = {attr_none;0}    trait = {trait_none}    effect_point = -16113    target_type = enemy_only    affect_scope = single    affect_limit = {0;0}    next_action = none    debuff = 1    ride_state = {@ride_none}    multi_class = 0    olympiad_use = 1    skill_end
 
Последнее редактирование:
Ну если на 3 сек, тогда это как эффект уже идет, то есть накладываем эффект на 3 сек, блокируем интенты и смену таргета. Агр как бы укладывается в ту же схему что и фир, только там своя механика а там своя, но по сути и то эффект и то эффект, хотя его по разному реализуют, вот смотрю сборку, тут без задержки все, просто сменили таргет и дали атаку. А вот по поводу агра монстра, то в SkillData идет effect_point = -4312 смотрел видео с мастором томой, там он объяснял, но я так и не понял, это именно величина хейта? или ее нужно прогнать через формулу еще какую?
 
ООО, спасибо, да я и из ассемблера понял все, то есть получается есть 2 ветки скила, target_me и i_get_agro, первый на персонажа второй на монстра, ну я смотрю персонаж агрится без шанса, то есть 100% изменяется таргет и дает команду сервер атаковать цель, при этом эффект не накладывается, как допустим у фира, как бы сбивает персонажа с атаки, тут более мене понятно, хотя смотрел на ява сборках там по разному в одной например сделали что-то типа Random(100) < 75 то есть дали искусственный шанс в 75%, а вот вопрос по поводу петов, на них так же действует как и на персонажей?? и второй вопрос, а вот по поводу монстров, там я так понимаю тоже 100% прохождение просто добавляется хейт, по формуле power * 150 / targetLevel + 7 вроде так если память не подводит?
Не смотри на другие ява сборки ) бери и переноси себе с тотал чекера, прийдется почти все с нуля переписать, ну это того стоит.
 
Ну если на 3 сек, тогда это как эффект уже идет, то есть накладываем эффект на 3 сек, блокируем интенты и смену таргета. Агр как бы укладывается в ту же схему что и фир, только там своя механика а там своя, но по сути и то эффект и то эффект, хотя его по разному реализуют, вот смотрю сборку, тут без задержки все, просто сменили таргет и дали атаку. А вот по поводу агра монстра, то в SkillData идет effect_point = -4312 смотрел видео с мастором томой, там он объяснял, но я так и не понял, это именно величина хейта? или ее нужно прогнать через формулу еще какую?
 
Да эффекты эти не так важны для агра мобов. effect_point = -3928 - вот что важно для агра МОБОВ

А для персонажей влияет INT, и тут уже нужны эффекты
 
Well, if it's for 3 seconds, then it's already an effect, meaning we apply the effect for 3 seconds, block intents, and change the target. Aggro sort of fits into the same pattern as fear, except one has its own mechanics, and the other has its own. Essentially, both are effects, although they're implemented differently. I'm looking at a build, and there's no delay; they just change the target and attack. Regarding the monster's aggro, the SkillData says effect_point = -4312. I watched a video with Master Toma, he explained it, but I still don't understand. Is that the hate value? Or does it need to be run through some other formula?
Negative effect point is input for 'damage' parameter in ATTACKED event. Then later, attack desire is added to the attacker based on value of damage.

Additionally, aggro skills trigger DESIRE_MANIPULATION event. For many of the cases, additional attack desire is added there.

 
Ну понятно, для персонажа и сумона одинаково применяется хейт, но вот :
Negative effect point is input for 'damage' parameter in ATTACKED event. Then later, attack desire is added to the attacker based on value of damage.

Additionally, aggro skills trigger DESIRE_MANIPULATION event. For many of the cases, additional attack desire is added there.

Это вроде формула расчета хейта от урона по НПС. Вот нашел
Код:
if(myself.Skill_GetEffectPoint(skill_name_id) > 0)
        {
            if(myself.IsInCombatMode(myself.sm) != 0)
            {
                f1 = myself.Skill_GetEffectPoint(skill_name_id);
                f0 = DefaultHate;
                if(HateRace1 > -1)
                {
                    if(HateRace1 == speller.getRace().ordinal())
                    {
                        f0 = (f0 + HateRace1Boost);
                    }
                }
                if(HateRace2 > -1)
                {
                    if(HateRace2 == speller.getRace().ordinal())
                    {
                        f0 = (f0 + HateRace2Boost);
                    }
                }
                if(HateClass1 > -1)
                {
                    if(speller.getActiveClassId() == HateClass1)
                    {
                        f0 = (f0 + HateClass1Boost);
                    }
                }
                if(HateClass2 > -1)
                {
                    if(speller.getActiveClassId() == HateClass2)
                    {
                        f0 = (f0 + HateClass2Boost);
                    }
                }
                if(HateClass3 > -1)
                {
                    if(speller.getActiveClassId() == HateClass3)
                    {
                        f0 = (f0 + HateClass3Boost);
                    }
                }
                if(HateClassGroup1 > -1)
                {
                    if(myself.IsInCategory(HateClassGroup1,speller.getActiveClassId()) > 0)
                    {
                        f0 = (f0 + HateClassGroup1Boost);
                    }
                }
                if(HateClassGroup2 > -1)
                {
                    if(myself.IsInCategory(HateClassGroup2,speller.getActiveClassId()) > 0)
                    {
                        f0 = (f0 + HateClassGroup2Boost);
                    }
                }
                if((f0 + 1) < 0)
                {
                    f0 = 0;
                }
                else
                {
                    f0 = (f1 * (f0 + 1));
                }
                myself.AddAttackDesire(speller,1,(f0 * SEE_SPELL_Weight_Point));
            }
        }
Тут получается учитывается расса и класс, DefaultHate я так понимаю 0, и f0 это модификатор класса и рассы, и по сути если он 0 тогда f1 * 1 получается хейт равен effect_point
 
У агра нет какой-то статичной функции в ядре. Это система почти на 100% управляется через NASC и по сути просто представляет из себя несколько сортированных коллекций(от одной до четырех), в которые моб помещает игровые объекты, путем назначения им определенных значений хейта или урона. Ядро предоставляет просто удобный API для взаимодействия с этими коллекциями(добавление, удаление, сортировка, фильтрация объектов по значениям).
При этом, в самом ядре нет какой-то типизированной логики начисления этих значений и весь процесс полностью управляется из NASC.
А там очень много вариаций: Где-то мобы добавляют сразу хейт при видимости, где-то только ночью, только днем, только конкретной профе, только на конкретные скиллы или действия, очищается он тоже по логике из NASC, запрашивается таргет тоже по логике из NASC.

Не существует какой-то универсальной формулы. Все регулируется вручную через скрипты НПЦ и поведение зависит целиком от конкретного нпц.

Psycho False
 
У агра нет какой-то статичной функции в ядре. Это система почти на 100% управляется через NASC и по сути просто представляет из себя несколько сортированных коллекций(от одной до четырех), в которые моб помещает игровые объекты, путем назначения им определенных значений хейта или урона. Ядро предоставляет просто удобный API для взаимодействия с этими коллекциями(добавление, удаление, сортировка, фильтрация объектов по значениям).
При этом, в самом ядре нет какой-то типизированной логики начисления этих значений и весь процесс полностью управляется из NASC.
А там очень много вариаций: Где-то мобы добавляют сразу хейт при видимости, где-то только ночью, только днем, только конкретной профе, только на конкретные скиллы или действия, очищается он тоже по логике из NASC, запрашивается таргет тоже по логике из NASC.

Не существует какой-то универсальной формулы. Все регулируется вручную через скрипты НПЦ и поведение зависит целиком от конкретного нпц.

Psycho False
Ну а финальное вычисление, именно сколько хейта дать от скила? Вот допустим нашел формулу -
effectPoint * 150L / (level + 7)
 
Ну а финальное вычисление, именно сколько хейта дать от скила? Вот допустим нашел формулу -
effectPoint * 150L / (level + 7)
Еще раз повторяю: Нет какой-то универсальной формулы в движке, которая бы начисляла хейт автоматически. Каждый моб вручную управляет своим хейтом индивидуально полностью. Конкретное значение хейта, которое добавляется в итоге, передается в функцию AddHateInfo как второй аргумент.

AddHateInfo(c0, 500, 0, 1, 1);

Например тут начисляется 500 единиц хейта.

Просто есть более узкие правила, для индивидуальных мобов, а есть более широкие, на уровне родительских классов, которые захватывают кучу мобов, но 99% мобов так или иначе напрямую управляют своим хейтом через ИИ скрипты.
 
ну это понятно, там идет эффект поинт, это идет как базовый хейт, а к нему применяются модификаторы класса и рассы цели, то есть для каждого НПС есть в ОФФе группы расс и классов ненависти, кого-то ненавидит НПС больше а кого-то меньше исходя из этого формируется величина хейта, но в JAVA как я вижу не используют данные рас и классов, а значить по сути хейт это и есть эффект поинт, что показывает из формул выше из ОФФа, но так как нужно было выходить из ситуации, в JAVA сделали линейную формулу хейта а именно effectPoint * 150L / (level + 7) только тут не effectPoint а power, который непонятно где взяли, либо сами вычислили по каким-то закономерностям, вот сижу гадаю )
 
ну это понятно, там идет эффект поинт, это идет как базовый хейт, а к нему применяются модификаторы класса и рассы цели, то есть для каждого НПС есть в ОФФе группы расс и классов ненависти, кого-то ненавидит НПС больше а кого-то меньше исходя из этого формируется величина хейта, но в JAVA как я вижу не используют данные рас и классов, а значить по сути хейт это и есть эффект поинт, что показывает из формул выше из ОФФа, но так как нужно было выходить из ситуации, в JAVA сделали линейную формулу хейта а именно effectPoint * 150L / (level + 7) только тут не effectPoint а power, который непонятно где взяли, либо сами вычислили по каким-то закономерностям, вот сижу гадаю )
Ну за ява сборки не скажу. Там каждый делает в меру своей испорченности. У меня в сборке одним способом, в другой сборке другим способом. Сколько сборок, столько и реализаций.
Общую логику даже описать как-то кратко тяжело более детально чем: "Моб добавляет хейт в хейт лист исходя из игровых событий, а потом использует этот хейт для выбора целей при планировании очереди своих действий". )))

там мобы даже не обязательно постоянно агриться будут. Куча локаций, где у мобов поведение меняется в зависимости от времени суток, профы таргета и прочего.
 
Назад
Сверху Снизу