Ir para conteúdo
  • Cadastre-se
  • 0

Skill Cooltime ( Skill volta do 0 após restart )


Chaazy

Pergunta

Ha algum tempo venho tentando resolver um problema na l2jfrozen 1132, ja pesquisei em vários fóruns,porem sem sucesso.

O que acontece é o seguinte. Skills que contem o reusedelay maior (buffs como heroic, battle roar, rage, frenzy, zealot, ultimate defense etc...) assim que você os usa e deixa ele carregar 30,50,90% que seja, se o player tomar dc, critical error ou ate mesmo dar restart, o skill volta do 0! Ele simplesmente não volta de onde parou, e mesmo ficando 1 hora sem entrar no jogo a skill não termina de carregar, é como se não salva-se os dados das skills.

Alguém pode ajudar? 

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

Posts recomendados


  • 0

Como você mesmo falou, não está salvando no banco de dados essa informação ou essa informação não está sendo restaurada. Você precisa salvar essa informação no método 'onDisconnection' da classe L2GameClient e restaurar no método que carrega os dados do player na classe L2PcInstance. Geralmente essa informação é salva na tabela 'characters_skills_save'.  Infelizmente não conheço a Frozen pra te ajudar além disso.

Editado por KhayrusS
Link para o comentário
Compartilhar em outros sites

  • 0
 

Como você mesmo falou, não está salvando no banco de dados essa informação ou essa informação não está sendo restaurada. Você precisa salvar essa informação no método 'onDisconnection' da classe L2GameClient e restaurar no método que carrega os dados do player na classe L2PcInstance. Geralmente essa informação é salva na tabela 'characters_skills_save'.  Infelizmente não conheço a Frozen pra te ajudar além disso.

Obrigado mesmo assim, já é um ponto de partida!

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

  • 0

Basta ir em L2PcInstance

Procure por
public void restoreEffects(final boolean activateEffects)

Tem todas as informações que você precisa sobre a restauração do player.

Basta corrigir da forma que vc quiser, eu não utilizo frozen, mas corrigi na que eu utilizo à tempos.

Certa vez no meu server, para burlarem o tempo reuse skill, eles trocavam de subclasse, a skill voltava zerada.

Nesse caso precisa modificar tb.

Link para o comentário
Compartilhar em outros sites

  • 0
 

Basta ir em L2PcInstance


Procure por
public void restoreEffects(final boolean activateEffects)

Tem todas as informações que você precisa sobre a restauração do player.

Basta corrigir da forma que vc quiser, eu não utilizo frozen, mas corrigi na que eu utilizo à tempos.

Certa vez no meu server, para burlarem o tempo reuse skill, eles trocavam de subclasse, a skill voltava zerada.

Nesse caso precisa modificar tb.

   

	public void restoreEffects(final boolean activateEffects)
	{
		Connection con = null;
		
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection(false);
			PreparedStatement statement;
			ResultSet rset;
			
			/**
			 * Restore Type 0 These skill were still in effect on the character upon logout. Some of which were self casted and might still have had a long reuse delay which also is restored.
			 */
			statement = con.prepareStatement(RESTORE_SKILL_SAVE);
			statement.setInt(1, getObjectId());
			statement.setInt(2, getClassIndex());
			statement.setInt(3, 0);
			rset = statement.executeQuery();
			
			while (rset.next())
			{
				final int skillId = rset.getInt("skill_id");
				final int skillLvl = rset.getInt("skill_level");
				final int effectCount = rset.getInt("effect_count");
				final int effectCurTime = rset.getInt("effect_cur_time");
				final long reuseDelay = rset.getLong("reuse_delay");
				
				// Just incase the admin minipulated this table incorrectly :x
				if (skillId == -1 || effectCount == -1 || effectCurTime == -1 || reuseDelay < 0)
				{
					continue;
				}
				
				if (activateEffects)
				{
					
					L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
					
					skill.getEffects(this, this, false, false, false);
					skill = null;
					
					for (final L2Effect effect : getAllEffects())
					{
						if (effect.getSkill().getId() == skillId)
						{
							effect.setCount(effectCount);
							effect.setFirstTime(effectCurTime);
						}
					}
				}
				
				if (reuseDelay > 10)
				{
					final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
					
					if (skill == null)
						continue;
					
					disableSkill(skill, reuseDelay);
					addTimeStamp(new TimeStamp(skill, reuseDelay));
				}
				
			}
			DatabaseUtils.close(rset);
			DatabaseUtils.close(statement);
			rset = null;
			statement = null;
			
			/**
			 * Restore Type 1 The remaning skills lost effect upon logout but were still under a high reuse delay.
			 */
			statement = con.prepareStatement(RESTORE_SKILL_SAVE);
			statement.setInt(1, getObjectId());
			statement.setInt(2, getClassIndex());
			statement.setInt(3, 1);
			rset = statement.executeQuery();
			
			while (rset.next())
			{
				final int skillId = rset.getInt("skill_id");
				final int skillLvl = rset.getInt("skill_level");
				final long reuseDelay = rset.getLong("reuse_delay");
				
				if (reuseDelay <= 0)
				{
					continue;
				}
				
				final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
				
				if (skill == null)
					continue;
				
				disableSkill(skill, reuseDelay);
				addTimeStamp(new TimeStamp(skill, reuseDelay));
			}
			DatabaseUtils.close(rset);
			DatabaseUtils.close(statement);
			rset = null;
			
			statement = con.prepareStatement(DELETE_SKILL_SAVE);
			statement.setInt(1, getObjectId());
			statement.setInt(2, getClassIndex());
			statement.executeUpdate();
			DatabaseUtils.close(statement);
			statement = null;
		}
		catch (final Exception e)
		{
			if (Config.ENABLE_ALL_EXCEPTIONS)
				e.printStackTrace();
			
			LOGGER.warn("Could not restore active effect data: " + e);
		}
		finally
		{
			CloseUtil.close(con);
		}
		
		updateEffectIcons();
	}

 

pode me dizer onde devo alterar?

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

  • 0
 

Aparentemente essa parte do código está correta. Procura pelo método que salva essas informações no DB, provavelmente algo parecido com 'storeEffects'.

	@SuppressWarnings("null")
	private synchronized void storeEffect()
	{
		if (!Config.STORE_SKILL_COOLTIME)
			return;
		
		Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection(false);
			PreparedStatement statement;
			// Delete all current stored effects for char to avoid dupe
			statement = con.prepareStatement(DELETE_SKILL_SAVE);
			statement.setInt(1, getObjectId());
			statement.setInt(2, getClassIndex());
			statement.execute();
			DatabaseUtils.close(statement);
			
			// Store all effect data along with calulated remaining
			// reuse delays for matching skills. 'restore_type'= 0.
			final L2Effect[] effects = getAllEffects();
			statement = con.prepareStatement(ADD_SKILL_SAVE);
			
			final List<Integer> storedSkills = new FastList<>();
			
			int buff_index = 0;
			
			for (final L2Effect effect : effects)
			{
				final int skillId = effect.getSkill().getId();
				
				if (storedSkills.contains(skillId))
					continue;
				storedSkills.add(skillId);
				
				if (effect != null && effect.getInUse() && !effect.getSkill().isToggle() && !effect.getStackType().equals("BattleForce") && !effect.getStackType().equals("SpellForce") && effect.getSkill().getSkillType() != SkillType.FORCE_BUFF)
				{
					statement.setInt(1, getObjectId());
					statement.setInt(2, skillId);
					statement.setInt(3, effect.getSkill().getLevel());
					statement.setInt(4, effect.getCount());
					statement.setInt(5, effect.getTime());
					if (ReuseTimeStamps.containsKey(effect.getSkill().getReuseHashCode()))
					{
						final TimeStamp t = ReuseTimeStamps.get(effect.getSkill().getReuseHashCode());
						statement.setLong(6, t.hasNotPassed() ? t.getReuse() : 0);
						statement.setLong(7, t.hasNotPassed() ? t.getStamp() : 0);
					}
					else
					{
						statement.setLong(6, 0);
						statement.setLong(7, 0);
					}
					statement.setInt(8, 0);
					statement.setInt(9, getClassIndex());
					statement.setInt(10, ++buff_index);
					statement.execute();
				}
			}
			// Store the reuse delays of remaining skills which
			// lost effect but still under reuse delay. 'restore_type' 1.
			for (final TimeStamp t : ReuseTimeStamps.values())
			{
				if (t.hasNotPassed())
				{
					final int skillId = t.getSkill().getId();
					final int skillLvl = t.getSkill().getLevel();
					if (storedSkills.contains(skillId))
						continue;
					storedSkills.add(skillId);
					
					statement.setInt(1, getObjectId());
					statement.setInt(2, skillId);
					statement.setInt(3, skillLvl);
					statement.setInt(4, -1);
					statement.setInt(5, -1);
					statement.setLong(6, t.getReuse());
					statement.setLong(7, t.getStamp());
					statement.setInt(8, 1);
					statement.setInt(9, getClassIndex());
					statement.setInt(10, ++buff_index);
					statement.execute();
				}
			}
			DatabaseUtils.close(statement);
		}
		catch (final Exception e)
		{
			LOGGER.warn("Could not store char effect data: ");
			e.printStackTrace();
		}
		finally
		{
			CloseUtil.close(con);
		}
	}

Seria isso?

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

  • 0
 

Isso. Eu preciso só de mais duas informações:

o valor dessa constante  ADD_SKILL_SAVE;

e o código dessa classe: TimeStamp.

 

Código da TimeStamp 

	public static class TimeStamp
	{
		
		public long getStamp()
		{
			return stamp;
		}
		
		public L2Skill getSkill()
		{
			return skill;
		}
		
		public long getReuse()
		{
			return reuse;
		}
		
		public long getRemaining()
		{
			return Math.max(stamp - System.currentTimeMillis(), 0L);
		}
		
		protected boolean hasNotPassed()
		{
			return System.currentTimeMillis() < stamp;
		}
		
		private final L2Skill skill;
		private final long reuse;
		private final long stamp;
		
		protected TimeStamp(final L2Skill _skill, final long _reuse)
		{
			skill = _skill;
			reuse = _reuse;
			stamp = System.currentTimeMillis() + reuse;
		}
		
		protected TimeStamp(final L2Skill _skill, final long _reuse, final long _systime)
		{
			skill = _skill;
			reuse = _reuse;
			stamp = _systime;
		}
	}

Valor da Constant ADD_SKILL_SAVE seria isso?

	/** The Constant ADD_SKILL_SAVE. */
	// private static final String ADD_SKILL_SAVE = "INSERT INTO character_skills_save (char_obj_id,skill_id,skill_level,effect_count,effect_cur_time,reuse_delay,restore_type,class_index,buff_index) VALUES (?,?,?,?,?,?,?,?,?)";
	private static final String ADD_SKILL_SAVE = "INSERT INTO character_skills_save (char_obj_id,skill_id,skill_level,effect_count,effect_cur_time,reuse_delay,systime,restore_type,class_index,buff_index) VALUES (?,?,?,?,?,?,?,?,?,?)";

 

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

  • 0

É isso mesmo. Existem duas abordagens:

  • A skill ser restaurada com o cooltime  que estava quando o player deslogou;
  • O cooltime ser baseado no tempo real, por exemplo: A skill tem restando 10 min de cooltime, se o player logar apenas depois que os 10 min  passou, a skill já estaria pronta pra uso.

Qual delas você quer ?

Link para o comentário
Compartilhar em outros sites

  • 0
 

É isso mesmo. Existem duas abordagens:

  • A skill ser restaurada com o cooltime  que estava quando o player deslogou;
  • O cooltime ser baseado no tempo real, por exemplo: A skill tem restando 10 min de cooltime, se o player logar apenas depois que os 10 min  passou, a skill já estaria pronta pra uso.

Qual delas você quer ?

Com o cooltime baseado no tempo real, pois assim resolve o problema de logar bom tempo depois e a skill começando do 0.

Dessa forma se o player tomar dc e voltar 1 minuto depois, a skill vai continuar seu cooltime normalmente? Exemplo:

Tomei dc com heroic 50%, demorei 1 minuto pra logar novamente e o mesmo vai estar 60%.

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

  • 0

O problema é que está sendo salvo o reuseDelay da skill no DB, por isso ela sempre volta do 0.

Para a skill ser restaurada com o cooltime  que estava quando o player deslogou, no método storeEffect, é necessário apenas mudar essa linha

 

statement.setLong(6, t.getReuse());

para essa :

statement.setLong(6, t.getRemaining());

 

Já para a segunda alternativa a mudança pode ser realizada no método restoreEffects. Após as linhas

final int effectCurTime = rset.getInt("effect_cur_time");
final long reuseDelay = rset.getLong("reuse_delay");

adicionar:

final long coolTime = rset.getLong("systime") - System.currentTimeMillis(); 

Trocar essa parte do código:

if (reuseDelay > 10)
{
  final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);

  if (skill == null)
    continue;

  disableSkill(skill, reuseDelay);
  addTimeStamp(new TimeStamp(skill, reuseDelay));
}

por essa:

if (coolTime > 10)
{
  final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);

  if (skill == null)
    continue;

  disableSkill(skill, coolTime);
  addTimeStamp(new TimeStamp(skill, coolTime));
}

 

Seguir a mesma lógica pra parte mais abaixo do código. Além disso, confirmar que a coluna systime faz parte do select da constante RESTORE_SKILL_SAVE

Link para o comentário
Compartilhar em outros sites

  • 0
 

O problema é que está sendo salvo o reuseDelay da skill no DB, por isso ela sempre volta do 0.

Para a skill ser restaurada com o cooltime  que estava quando o player deslogou, no método storeEffect, é necessário apenas mudar essa linha

para essa :


statement.setLong(6, t.getRemaining());

 

Já para a segunda alternativa a mudança pode ser realizada no método restoreEffects. Após as linhas


final int effectCurTime = rset.getInt("effect_cur_time");
final long reuseDelay = rset.getLong("reuse_delay");

adicionar:


final long coolTime = rset.getLong("systime") - System.currentTimeMillis(); 

Trocar essa parte do código:


if (reuseDelay > 10)
{
  final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);

  if (skill == null)
    continue;

  disableSkill(skill, reuseDelay);
  addTimeStamp(new TimeStamp(skill, reuseDelay));
}

por essa:


if (coolTime > 10)
{
  final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);

  if (skill == null)
    continue;

  disableSkill(skill, coolTime);
  addTimeStamp(new TimeStamp(skill, coolTime));
}

 

Seguir a mesma lógica pra parte mais abaixo do código. Além disso, confirmar que a coluna systime faz parte do select da constante RESTORE_SKILL_SAVE

Muito Obrigado mesmo KhayrusS!!! Me ajudou demais ❤️ Porém fiz algumas alterações nos códigos ficando da seguinte forma:

Adicionei a linha 

final long systime = rset.getLong("systime");

abaixo das linhas 

final int effectCount = rset.getInt("effect_count");
final int effectCurTime = rset.getInt("effect_cur_time");
final long reuseDelay = rset.getLong("reuse_delay");

Troquei esse parte código 

if (reuseDelay > 10)
{
  final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);

  if (skill == null)
    continue;

  disableSkill(skill, reuseDelay);
  addTimeStamp(new TimeStamp(skill, reuseDelay));
}

por esta

				final long remainingTime = systime - System.currentTimeMillis();
				if (remainingTime > 10)
					
				{
					final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
					
					if (skill == null)
						continue;
					
					disableSkill(skill, remainingTime);
					addTimeStamp(new TimeStamp(skill, reuseDelay, systime));
				}

E segui a mesma logica para os codigos abaixo. O meu problema era no RestoreEffects, dessa forma se eu usar a skill e ele tiver 50%, se eu tomar dc ou der restart a skill continua carregando normalmente ? e quando voltar a skill vai continuar de onde ela estiver.

Mas com isso tambem apareceu um novo bug, que nao tinha como saber com a skill voltando do 0 toda vez.

Se eu usar uma skill (ex: Heroic) e der 2 restarts seguidos, a skill volta carregada 100%.

Pode me ajudar a arrumar isso também?

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

  • 0
 

Dois restarts rápidos ? Depois do segundo restart, antes de logar, novamente, valor do systime continua correto no DB ?

Sim 2 restarts rapidos, notei o seguinte. Se usar a skill e atualizar a db com o char logado, não aparece que a skill foi salva, não mostra systime, reuse essas coisas, ai quando dou o primeiro restart com o char e atualizo a db, mostra os dados salvos corretamente, systime e tudo.

Assim que dou o segundo restart, as informações que foram salvas na db somem. Ai a skill volta do 100% 

Editado por Chaazy

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

  • 0
10 horas atrás, KhayrusS disse:

Isso é um pouco estranho mesmo.

Posta o código do método addTimestamp

Vou postar todos os códigos.

StoreEffect

	@SuppressWarnings("null")
	private synchronized void storeEffect()
	{
		if (!Config.STORE_SKILL_COOLTIME)
			return;
		
		Connection con = null;
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection(false);
			PreparedStatement statement;
			// Delete all current stored effects for char to avoid dupe
			statement = con.prepareStatement(DELETE_SKILL_SAVE);
			statement.setInt(1, getObjectId());
			statement.setInt(2, getClassIndex());
			statement.execute();
			DatabaseUtils.close(statement);
			
			// Store all effect data along with calulated remaining
			// reuse delays for matching skills. 'restore_type'= 0.
			final L2Effect[] effects = getAllEffects();
			statement = con.prepareStatement(ADD_SKILL_SAVE);
			
			final List<Integer> storedSkills = new FastList<>();
			
			int buff_index = 0;
			
			for (final L2Effect effect : effects)
			{
				final int skillId = effect.getSkill().getId();
				
				if (storedSkills.contains(skillId))
					continue;
				storedSkills.add(skillId);
				
				if (effect != null && effect.getInUse() && !effect.getSkill().isToggle() && !effect.getStackType().equals("BattleForce") && !effect.getStackType().equals("SpellForce") && effect.getSkill().getSkillType() != SkillType.FORCE_BUFF)
				{
					statement.setInt(1, getObjectId());
					statement.setInt(2, skillId);
					statement.setInt(3, effect.getSkill().getLevel());
					statement.setInt(4, effect.getCount());
					statement.setInt(5, effect.getTime());
					if (ReuseTimeStamps.containsKey(effect.getSkill().getReuseHashCode()))
					{
						final TimeStamp t = ReuseTimeStamps.get(effect.getSkill().getReuseHashCode());
						statement.setLong(6, t.hasNotPassed() ? t.getReuse() : 0);
						statement.setLong(7, t.hasNotPassed() ? t.getStamp() : 0);
					}
					else
					{
						statement.setLong(6, 0);
						statement.setLong(7, 0);
					}
					statement.setInt(8, 0);
					statement.setInt(9, getClassIndex());
					statement.setInt(10, ++buff_index);
					statement.execute();
				}
			}
			// Store the reuse delays of remaining skills which
			// lost effect but still under reuse delay. 'restore_type' 1.
			for (final TimeStamp t : ReuseTimeStamps.values())
			{
				if (t.hasNotPassed())
				{
					final int skillId = t.getSkill().getId();
					final int skillLvl = t.getSkill().getLevel();
					if (storedSkills.contains(skillId))
						continue;
					storedSkills.add(skillId);
					
					statement.setInt(1, getObjectId());
					statement.setInt(2, skillId);
					statement.setInt(3, skillLvl);
					statement.setInt(4, -1);
					statement.setInt(5, -1);
					statement.setLong(6, t.getReuse());
					statement.setLong(7, t.getStamp());
					statement.setInt(8, 1);
					statement.setInt(9, getClassIndex());
					statement.setInt(10, ++buff_index);
					statement.execute();
				}
			}
			DatabaseUtils.close(statement);
		}
		catch (final Exception e)
		{
			LOGGER.warn("Could not store char effect data: ");
			e.printStackTrace();
		}
		finally
		{
			CloseUtil.close(con);
		}
	}

 

restoreEffect

	public void restoreEffects(final boolean activateEffects)
	{
		Connection con = null;
		
		try
		{
			con = L2DatabaseFactory.getInstance().getConnection(false);
			PreparedStatement statement;
			ResultSet rset;
			
			/**
			 * Restore Type 0 These skill were still in effect on the character upon logout. Some of which were self casted and might still have had a long reuse delay which also is restored.
			 */
			statement = con.prepareStatement(RESTORE_SKILL_SAVE);
			statement.setInt(1, getObjectId());
			statement.setInt(2, getClassIndex());
			statement.setInt(3, 0);
			rset = statement.executeQuery();
			
			while (rset.next())
			{
				final int skillId = rset.getInt("skill_id");
				final int skillLvl = rset.getInt("skill_level");
				final int effectCount = rset.getInt("effect_count");
				final int effectCurTime = rset.getInt("effect_cur_time");
				final long reuseDelay = rset.getLong("reuse_delay");
				final long systime = rset.getLong("systime");
				
				// Just incase the admin minipulated this table incorrectly :x
				if (skillId == -1 || effectCount == -1 || effectCurTime == -1 || reuseDelay < 0)
				{
					continue;
				}
				
				if (activateEffects)
				{
					
					L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
					
					skill.getEffects(this, this, false, false, false);
					skill = null;
					
					for (final L2Effect effect : getAllEffects())
					{
						if (effect.getSkill().getId() == skillId)
						{
							effect.setCount(effectCount);
							effect.setFirstTime(effectCurTime);
						}
					}
				}
				
				final long remainingTime = systime - System.currentTimeMillis();
				if (remainingTime > 10)
					
				{
					final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
					
					if (skill == null)
						continue;
					
					disableSkill(skill, remainingTime);
					addTimeStamp(new TimeStamp(skill, reuseDelay, systime));
				}
				
			}
			DatabaseUtils.close(rset);
			DatabaseUtils.close(statement);
			rset = null;
			statement = null;
			
			/**
			 * Restore Type 1 The remaning skills lost effect upon logout but were still under a high reuse delay.
			 */
			statement = con.prepareStatement(RESTORE_SKILL_SAVE);
			statement.setInt(1, getObjectId());
			statement.setInt(2, getClassIndex());
			statement.setInt(3, 1);
			rset = statement.executeQuery();
			
			while (rset.next())
			{
				final int skillId = rset.getInt("skill_id");
				final int skillLvl = rset.getInt("skill_level");
				final long reuseDelay = rset.getLong("reuse_delay");
				final long systime = rset.getLong("systime");
				
				final long remainingTime = systime - System.currentTimeMillis();
				if (remainingTime > 0)
					
				{
					final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
					
					if (skill == null)
						continue;
					
					disableSkill(skill, remainingTime);
					addTimeStamp(new TimeStamp(skill, reuseDelay, systime));
				}
				
			}
			DatabaseUtils.close(rset);
			DatabaseUtils.close(statement);
			rset = null;
			
			statement = con.prepareStatement(DELETE_SKILL_SAVE);
			statement.setInt(1, getObjectId());
			statement.setInt(2, getClassIndex());
			statement.executeUpdate();
			DatabaseUtils.close(statement);
			statement = null;
		}
		catch (final Exception e)
		{
			if (Config.ENABLE_ALL_EXCEPTIONS)
				e.printStackTrace();
			
			LOGGER.warn("Could not restore active effect data: " + e);
		}
		finally
		{
			CloseUtil.close(con);
		}
		
		updateEffectIcons();
	}

TimeStamp

	public static class TimeStamp
	{
		
		public long getStamp()
		{
			return stamp;
		}
		
		public L2Skill getSkill()
		{
			return skill;
		}
		
		public long getReuse()
		{
			return reuse;
		}
		
		public long getRemaining()
		{
			return Math.max(stamp - System.currentTimeMillis(), 0L);
		}
		
		protected boolean hasNotPassed()
		{
			return System.currentTimeMillis() < stamp;
		}
		
		private final L2Skill skill;
		private final long reuse;
		private final long stamp;
		
		protected TimeStamp(final L2Skill _skill, final long _reuse)
		{
			skill = _skill;
			reuse = _reuse;
			stamp = System.currentTimeMillis() + reuse;
		}
		
		protected TimeStamp(final L2Skill _skill, final long _reuse, final long _systime)
		{
			skill = _skill;
			reuse = _reuse;
			stamp = _systime;
		}
	}
	
	/**
	 * Index according to skill id the current timestamp of use.
	 * @param s the s
	 * @param r the r
	 */
	@Override
	public void addTimeStamp(final L2Skill s, final int r)
	{
		ReuseTimeStamps.put(s.getReuseHashCode(), new TimeStamp(s, r));
	}
	
	/**
	 * Index according to skill this TimeStamp instance for restoration purposes only.
	 * @param T the t
	 */
	private void addTimeStamp(final TimeStamp T)
	{
		ReuseTimeStamps.put(T.getSkill().getId(), T);
	}
	
	/**
	 * Index according to skill id the current timestamp of use.
	 * @param s the s
	 */
	@Override
	public void removeTimeStamp(final L2Skill s)
	{
		ReuseTimeStamps.remove(s.getReuseHashCode());
	}
	
	public Collection<TimeStamp> getReuseTimeStamps()
	{
		return ReuseTimeStamps.values();
	}
	
	public void resetSkillTime(final boolean ssl)
	{
		final L2Skill arr$[] = getAllSkills();
		for (final L2Skill skill : arr$)
		{
			if (skill != null && skill.isActive() && skill.getId() != 1324)
				enableSkill(skill);
		}
		
		if (ssl)
			sendSkillList();
		sendPacket(new SkillCoolTime(this));
	}

Valor da ADD/RESTORE skills save

	/** The Constant ADD_SKILL_SAVE. */
	// private static final String ADD_SKILL_SAVE = "INSERT INTO character_skills_save (char_obj_id,skill_id,skill_level,effect_count,effect_cur_time,reuse_delay,restore_type,class_index,buff_index) VALUES (?,?,?,?,?,?,?,?,?)";
	private static final String ADD_SKILL_SAVE = "INSERT INTO character_skills_save (char_obj_id,skill_id,skill_level,effect_count,effect_cur_time,reuse_delay,systime,restore_type,class_index,buff_index) VALUES (?,?,?,?,?,?,?,?,?,?)";
	
	/** The Constant RESTORE_SKILL_SAVE. */
	private static final String RESTORE_SKILL_SAVE = "SELECT skill_id,skill_level,effect_count,effect_cur_time, reuse_delay, systime FROM character_skills_save WHERE char_obj_id=? AND class_index=? AND restore_type=? ORDER BY buff_index ASC";

Acho que são esses os responsaveis. 

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

  • 0

Quando as skills vão ser salvas há uma condição que se aplica quando o efeito ainda está em uso:

1 hora atrás, Chaazy disse:

if (effect != null && effect.getInUse() && !effect.getSkill().isToggle() && !effect.getStackType().equals("BattleForce") && !effect.getStackType().equals("SpellForce") && effect.getSkill().getSkillType() != SkillType.FORCE_BUFF)

 

O problema é que nessa condição o timestamp da skill é procurado utilizando o método getReuseHashCode:

1 hora atrás, Chaazy disse:

if (ReuseTimeStamps.containsKey(effect.getSkill().getReuseHashCode())) { 
   final TimeStamp t = ReuseTimeStamps.get(effect.getSkill().getReuseHashCode()); 
   statement.setLong(6, t.hasNotPassed() ? t.getReuse() : 0); 
   statement.setLong(7, t.hasNotPassed() ? t.getStamp() : 0); 
} else { 
  statement.setLong(6, 0); 
  statement.setLong(7, 0); 
}

 

Mas o método addTimeStamp está utilizando o método getId para salvar a informação:

1 hora atrás, Chaazy disse:

private void addTimeStamp(final TimeStamp T) {
  ReuseTimeStamps.put(T.getSkill().getId(), T); 
}

 

Acredito que modificando-o para utilizar o getReuseHashCode esse problema não irá mais acontecer

private void addTimeStamp(final TimeStamp T) {
  ReuseTimeStamps.put(T.getSkill().getReuseHashCode(), T); 
}

 

Link para o comentário
Compartilhar em outros sites

  • 0
22 horas atrás, KhayrusS disse:

Quando as skills vão ser salvas há uma condição que se aplica quando o efeito ainda está em uso:

O problema é que nessa condição o timestamp da skill é procurado utilizando o método getReuseHashCode:

Mas o método addTimeStamp está utilizando o método getId para salvar a informação:

Acredito que modificando-o para utilizar o getReuseHashCode esse problema não irá mais acontecer


private void addTimeStamp(final TimeStamp T) {
  ReuseTimeStamps.put(T.getSkill().getReuseHashCode(), T); 
}

 

Meu amigo você é demais! Problema resolvido! Vou postar a correção no tópico dos fixes da Frozen 1132.

Muito Obrigado KhayrusS. Abraço

Eduardo Garcia ?

Link para o comentário
Compartilhar em outros sites

  • 0

can you help me too please i use frozen revision=1073 i have the same problem

 

error: cannot find symbol
    [javac]                 final long remainingTime = systime - System.currentTimeMillis();
    [javac]                                            ^

 

error: cannot find symbol
    [javac]                     addTimeStamp(new TimeStamp(skill, reuseDelay, systime));
    [javac]                                                                   ^

 

final long remainingTime = systime - System.currentTimeMillis();
				if (remainingTime > 10)
					
				{
					final L2Skill skill = SkillTable.getInstance().getInfo(skillId, skillLvl);
					
					if (skill == null)
						continue;
					
					disableSkill(skill, remainingTime);
					addTimeStamp(new TimeStamp(skill, reuseDelay, systime));
				}

			}
			DatabaseUtils.close(rset);
			DatabaseUtils.close(statement);
			rset = null;
			statement = null;

 

Editado por ayioko
Link para o comentário
Compartilhar em outros sites

  • 0

Probably ur code is a bit different. So u need to figure out based on what was said here how ur code works.

For instance, on the Rev 1132 there is a class TimeStamp inside of the class L2PCInstance, but on 1073 looks like don't have it. Thats why this error: cannot find symbol

8 horas atrás, ayioko disse:

ddTimeStamp(new TimeStamp(skill, reuseDelay, systime));

 

Link para o comentário
Compartilhar em outros sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Processando...
  • Registre-se

    Faça parte da maior e  mais antigas comunidades sobre Lineage2 da América Latina.





  • Patrocinadores

  • Quem Está Navegando

    • Nenhum usuário registrado visualizando esta página.
  • Posts

    • relaxa jovem gafanhoto, testa as quests. e posTa os erros indesejaveis.  
    • Se alguém pudesse me ensinar como codificar as missões, eu ficaria feliz em fazer isso sozinho ou pelo menos ajudar. Eu realmente quero jogar em um servidor onde todas as quests funcionem bem e melhor ainda se você puder fazer quests customizadas!
    • mas no interlude, nem todas as quests de class,  vai mostrar onde tem que ir, ate o reborn nao mostrava quando era interlude, só mostrou depois que eles colocaram client classic pra rodar, e ficou melhor ainda quando virou hellbound em diante, mas ha sim alguma chance de modificar isso direto no script para fazer igualmente, só basta te um pouco de paciencia e persistencia exato
    • 408_PathToElvenwizard dá Orion eu tive que mexer tbm, até modifiquei e consegui deixar ela igual do Classic, com a seta e a marcação no mapa. (não retail IL) Dá pra importar py de várias revs, o foda é que não da regular as quest py através do debug em tempo real, pelo menos eu não consegui rsrs
    • Hasta el momento todas las QUESTS son completables si te guias con un tutorial de youtube. El problema es que tienen bugs de locacion y de subquests que no avanzan o no te marcan correctamente a donde ir en el mapa, cosa que en Retail si se ve como corresponde.
    • estranho, mas pelo menos a galera nunca reclamo das quests quando tinha aberto 5x, geral fez class primeira e segunda job, poucos que compraram a class
    • en RUSaCis-3.5 data pack, las Quests estan en formato .java y son diferentes a como estan redactadas en jOrion y jFrozen 1.5 (ProyectX) package net.sf.l2j.gameserver.scripting.quest; import net.sf.l2j.commons.random.Rnd; import net.sf.l2j.gameserver.enums.Paperdoll; import net.sf.l2j.gameserver.enums.QuestStatus; import net.sf.l2j.gameserver.enums.actors.ClassId; import net.sf.l2j.gameserver.model.actor.Creature; import net.sf.l2j.gameserver.model.actor.Npc; import net.sf.l2j.gameserver.model.actor.Player; import net.sf.l2j.gameserver.network.serverpackets.SocialAction; import net.sf.l2j.gameserver.scripting.QuestState; public class Q224_TestOfSagittarius extends SecondClassQuest { private static final String QUEST_NAME = "Q224_TestOfSagittarius"; // Items private static final int BERNARD_INTRODUCTION = 3294; private static final int HAMIL_LETTER_1 = 3295; private static final int HAMIL_LETTER_2 = 3296; private static final int HAMIL_LETTER_3 = 3297; private static final int HUNTER_RUNE_1 = 3298; private static final int HUNTER_RUNE_2 = 3299; private static final int TALISMAN_OF_KADESH = 3300; private static final int TALISMAN_OF_SNAKE = 3301; private static final int MITHRIL_CLIP = 3302; private static final int STAKATO_CHITIN = 3303; private static final int REINFORCED_BOWSTRING = 3304; private static final int MANASHEN_HORN = 3305; private static final int BLOOD_OF_LIZARDMAN = 3306; private static final int CRESCENT_MOON_BOW = 3028; private static final int WOODEN_ARROW = 17; // Rewards private static final int MARK_OF_SAGITTARIUS = 3293; // NPCs private static final int BERNARD = 30702; private static final int HAMIL = 30626; private static final int SIR_ARON_TANFORD = 30653; private static final int VOKIAN = 30514; private static final int GAUEN = 30717; // Monsters private static final int ANT = 20079; private static final int ANT_CAPTAIN = 20080; private static final int ANT_OVERSEER = 20081; private static final int ANT_RECRUIT = 20082; private static final int ANT_PATROL = 20084; private static final int ANT_GUARD = 20086; private static final int NOBLE_ANT = 20089; private static final int NOBLE_ANT_LEADER = 20090; private static final int BREKA_ORC_SHAMAN = 20269; private static final int BREKA_ORC_OVERLORD = 20270; private static final int MARSH_STAKATO_WORKER = 20230; private static final int MARSH_STAKATO_SOLDIER = 20232; private static final int MARSH_STAKATO_DRONE = 20234; private static final int MARSH_SPIDER = 20233; private static final int ROAD_SCAVENGER = 20551; private static final int MANASHEN_GARGOYLE = 20563; private static final int LETO_LIZARDMAN = 20577; private static final int LETO_LIZARDMAN_ARCHER = 20578; private static final int LETO_LIZARDMAN_SOLDIER = 20579; private static final int LETO_LIZARDMAN_WARRIOR = 20580; private static final int LETO_LIZARDMAN_SHAMAN = 20581; private static final int LETO_LIZARDMAN_OVERLORD = 20582; private static final int SERPENT_DEMON_KADESH = 27090; public Q224_TestOfSagittarius() { super(224, "Test Of Sagittarius"); setItemsIds(BERNARD_INTRODUCTION, HAMIL_LETTER_1, HAMIL_LETTER_2, HAMIL_LETTER_3, HUNTER_RUNE_1, HUNTER_RUNE_2, TALISMAN_OF_KADESH, TALISMAN_OF_SNAKE, MITHRIL_CLIP, STAKATO_CHITIN, REINFORCED_BOWSTRING, MANASHEN_HORN, BLOOD_OF_LIZARDMAN, CRESCENT_MOON_BOW); addQuestStart(BERNARD); addTalkId(BERNARD, HAMIL, SIR_ARON_TANFORD, VOKIAN, GAUEN); addMyDying(ANT, ANT_CAPTAIN, ANT_OVERSEER, ANT_RECRUIT, ANT_PATROL, ANT_GUARD, NOBLE_ANT, NOBLE_ANT_LEADER, BREKA_ORC_SHAMAN, BREKA_ORC_OVERLORD, MARSH_STAKATO_WORKER, MARSH_STAKATO_SOLDIER, MARSH_STAKATO_DRONE, MARSH_SPIDER, ROAD_SCAVENGER, MANASHEN_GARGOYLE, LETO_LIZARDMAN, LETO_LIZARDMAN_ARCHER, LETO_LIZARDMAN_SOLDIER, LETO_LIZARDMAN_WARRIOR, LETO_LIZARDMAN_SHAMAN, LETO_LIZARDMAN_OVERLORD, SERPENT_DEMON_KADESH); } @Override public String onAdvEvent(String event, Npc npc, Player player) { String htmltext = event; QuestState st = player.getQuestList().getQuestState(QUEST_NAME); if (st == null) return htmltext; // BERNARD if (event.equalsIgnoreCase("30702-04.htm")) { st.setState(QuestStatus.STARTED); st.setCond(1); playSound(player, SOUND_ACCEPT); giveItems(player, BERNARD_INTRODUCTION, 1); if (giveDimensionalDiamonds39(player)) htmltext = "30702-04a.htm"; } // HAMIL else if (event.equalsIgnoreCase("30626-03.htm")) { st.setCond(2); playSound(player, SOUND_MIDDLE); takeItems(player, BERNARD_INTRODUCTION, 1); giveItems(player, HAMIL_LETTER_1, 1); } else if (event.equalsIgnoreCase("30626-07.htm")) { st.setCond(5); playSound(player, SOUND_MIDDLE); takeItems(player, HUNTER_RUNE_1, 10); giveItems(player, HAMIL_LETTER_2, 1); } // SIR_ARON_TANFORD else if (event.equalsIgnoreCase("30653-02.htm")) { st.setCond(3); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_1, 1); } // VOKIAN else if (event.equalsIgnoreCase("30514-02.htm")) { st.setCond(6); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_2, 1); } return htmltext; } @Override public String onTalk(Npc npc, Player player) { String htmltext = getNoQuestMsg(); QuestState st = player.getQuestList().getQuestState(QUEST_NAME); if (st == null) return htmltext; switch (st.getState()) { case CREATED: if (player.getClassId() != ClassId.ROGUE && player.getClassId() != ClassId.ELVEN_SCOUT && player.getClassId() != ClassId.ASSASSIN) htmltext = "30702-02.htm"; else if (player.getStatus().getLevel() < 39) htmltext = "30702-01.htm"; else htmltext = "30702-03.htm"; break; case STARTED: int cond = st.getCond(); switch (npc.getNpcId()) { case BERNARD: htmltext = "30702-05.htm"; break; case HAMIL: if (cond == 1) htmltext = "30626-01.htm"; else if (cond == 2 || cond == 3) htmltext = "30626-04.htm"; else if (cond == 4) htmltext = "30626-05.htm"; else if (cond > 4 && cond < 8) htmltext = "30626-08.htm"; else if (cond == 8) { htmltext = "30626-09.htm"; st.setCond(9); playSound(player, SOUND_MIDDLE); takeItems(player, HUNTER_RUNE_2, 10); giveItems(player, HAMIL_LETTER_3, 1); } else if (cond > 8 && cond < 12) htmltext = "30626-10.htm"; else if (cond == 12) { htmltext = "30626-11.htm"; st.setCond(13); playSound(player, SOUND_MIDDLE); } else if (cond == 13) htmltext = "30626-12.htm"; else if (cond == 14) { htmltext = "30626-13.htm"; takeItems(player, BLOOD_OF_LIZARDMAN, -1); takeItems(player, CRESCENT_MOON_BOW, 1); takeItems(player, TALISMAN_OF_KADESH, 1); giveItems(player, MARK_OF_SAGITTARIUS, 1); rewardExpAndSp(player, 54726, 20250); player.broadcastPacket(new SocialAction(player, 3)); playSound(player, SOUND_FINISH); st.exitQuest(false); } break; case SIR_ARON_TANFORD: if (cond == 2) htmltext = "30653-01.htm"; else if (cond > 2) htmltext = "30653-03.htm"; break; case VOKIAN: if (cond == 5) htmltext = "30514-01.htm"; else if (cond == 6) htmltext = "30514-03.htm"; else if (cond == 7) { htmltext = "30514-04.htm"; st.setCond(8); playSound(player, SOUND_MIDDLE); takeItems(player, TALISMAN_OF_SNAKE, 1); } else if (cond > 7) htmltext = "30514-05.htm"; break; case GAUEN: if (cond == 9) { htmltext = "30717-01.htm"; st.setCond(10); playSound(player, SOUND_MIDDLE); takeItems(player, HAMIL_LETTER_3, 1); } else if (cond == 10) htmltext = "30717-03.htm"; else if (cond == 11) { htmltext = "30717-02.htm"; st.setCond(12); playSound(player, SOUND_MIDDLE); takeItems(player, MANASHEN_HORN, 1); takeItems(player, MITHRIL_CLIP, 1); takeItems(player, REINFORCED_BOWSTRING, 1); takeItems(player, STAKATO_CHITIN, 1); giveItems(player, CRESCENT_MOON_BOW, 1); giveItems(player, WOODEN_ARROW, 10); } else if (cond > 11) htmltext = "30717-04.htm"; break; } break; case COMPLETED: htmltext = getAlreadyCompletedMsg(); break; } return htmltext; } @Override public void onMyDying(Npc npc, Creature killer) { final Player player = killer.getActingPlayer(); final QuestState st = checkPlayerState(player, npc, QuestStatus.STARTED); if (st == null) return; switch (npc.getNpcId()) { case ANT: case ANT_CAPTAIN: case ANT_OVERSEER: case ANT_RECRUIT: case ANT_PATROL: case ANT_GUARD: case NOBLE_ANT: case NOBLE_ANT_LEADER: if (st.getCond() == 3 && dropItems(player, HUNTER_RUNE_1, 1, 10, 500000)) st.setCond(4); break; case BREKA_ORC_SHAMAN: case BREKA_ORC_OVERLORD: if (st.getCond() == 6 && dropItems(player, HUNTER_RUNE_2, 1, 10, 500000)) { st.setCond(7); giveItems(player, TALISMAN_OF_SNAKE, 1); } break; case MARSH_STAKATO_WORKER: case MARSH_STAKATO_SOLDIER: case MARSH_STAKATO_DRONE: if (st.getCond() == 10 && dropItems(player, STAKATO_CHITIN, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, MITHRIL_CLIP, REINFORCED_BOWSTRING)) st.setCond(11); break; case MARSH_SPIDER: if (st.getCond() == 10 && dropItems(player, REINFORCED_BOWSTRING, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, MITHRIL_CLIP, STAKATO_CHITIN)) st.setCond(11); break; case ROAD_SCAVENGER: if (st.getCond() == 10 && dropItems(player, MITHRIL_CLIP, 1, 1, 100000) && player.getInventory().hasItems(MANASHEN_HORN, REINFORCED_BOWSTRING, STAKATO_CHITIN)) st.setCond(11); break; case MANASHEN_GARGOYLE: if (st.getCond() == 10 && dropItems(player, MANASHEN_HORN, 1, 1, 100000) && player.getInventory().hasItems(REINFORCED_BOWSTRING, MITHRIL_CLIP, STAKATO_CHITIN)) st.setCond(11); break; case LETO_LIZARDMAN: case LETO_LIZARDMAN_ARCHER: case LETO_LIZARDMAN_SOLDIER: case LETO_LIZARDMAN_WARRIOR: case LETO_LIZARDMAN_SHAMAN: case LETO_LIZARDMAN_OVERLORD: if (st.getCond() == 13) { if (((player.getInventory().getItemCount(BLOOD_OF_LIZARDMAN) - 120) * 5) > Rnd.get(100)) { playSound(player, SOUND_BEFORE_BATTLE); takeItems(player, BLOOD_OF_LIZARDMAN, -1); addSpawn(SERPENT_DEMON_KADESH, player, false, 300000, true); } else dropItemsAlways(player, BLOOD_OF_LIZARDMAN, 1, 0); } break; case SERPENT_DEMON_KADESH: if (st.getCond() == 13) { if (player.getInventory().getItemIdFrom(Paperdoll.RHAND) == CRESCENT_MOON_BOW) { st.setCond(14); playSound(player, SOUND_MIDDLE); giveItems(player, TALISMAN_OF_KADESH, 1); } else addSpawn(SERPENT_DEMON_KADESH, player, false, 300000, true); } break; } } }  
    • Trate de comparar Test Of Sagittarius entre L2jOrion y L2jProyectX y son exactamente iguales, excepto por el import sys que esta adaptado.
    • esse projeto ta usando frozen 1.5? ultima vez que testei, ate quest soulshot newbie tava com problema. se for python, voces podem ver na l2jorion, la o dev que desenvolveu, ele arrumou todas as quests, pelo menos quando usei em server 5x, nao tive problema relacionado a quests. certamente vai te que mudar somente imports e talvez copiar algum metodo novo de algumas quests a referente drop items
    • COD-157    224_TestOfSagittarius                        - Testado e Funcionando, mas con bug al comienzo de la mision, no avanzan subquest queda na inicial  
×
×
  • Criar Novo...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.