Jump to content

Recommended Posts

Posted (edited)
1 minute ago, verbrannt said:

It's already reverted.

 

Ah, ok :) How about boss_id - that shouldn't be global map ID or should it be?

Edited by eressea
Posted (edited)
11 minutes ago, eressea said:

 

Ah, ok :) How about boss_id - that shouldn't be global map ID or should it be?

Idk. I have only one occurrence of this variable in my ai.obj files, so can't tell.

 

Also I think boss_pch.txt should be renamed to gm_pch.txt. "Boss" prefix is misleading here.

Edited by verbrannt
Posted
5 hours ago, verbrannt said:

Idk. I have only one occurrence of this variable in my ai.obj files, so can't tell.

 

Something tells me it should be int - objectID/index of NPC who is boss for the group, but I'm really not sure about that

 

5 hours ago, verbrannt said:

Also I think boss_pch.txt should be renamed to gm_pch.txt. "Boss" prefix is misleading here.

 

+1 maybe globalmap_pch.txt... OR maybe parse all of them from manual_pch.txt - that would be the best way

Posted

Comments inside ai.obj like
 // -- test comment -- 

ect, causes the decompiler to throw errors like "Decompile default_npcPHP Fatal error:  Uncaught TypeError: Argument 1 passed to Parser::fixTypeCase() must be of the type string, null given, "

but if the comments are removed, it decompiles fine. If at all possible can support for these types of comments be added?, l2npc handles them fine

Posted

After adding C1 support, I've compared all ai.obj from original one, and after decompilation/compilation. There is bunch of classes (about 15 of them of 2200) with 2 significant differences.

 

Here is one example of 1 style of difference. Could you check, what's the problem here?

https://drive.google.com/open?id=1WZx4FGF_FrkAOkem3bC8Stdd3Y--ixUj

 

Most probably the same thing is in other chronicles, since looks like it's related with some nested if() conditions

Posted
7 minutes ago, MasterToma said:

After adding C1 support, I've compared all ai.obj from original one, and after decompilation/compilation. There is bunch of classes (about 15 of them of 2200) with 2 significant differences.

 

Here is one example of 1 style of difference. Could you check, what's the problem here?

https://drive.google.com/open?id=1WZx4FGF_FrkAOkem3bC8Stdd3Y--ixUj

 

Most probably the same thing is in other chronicles, since looks like it's related with some nested if() conditions

Looks like nothing serious, only one missing shift stack pointer command :D
I think is always at the end of the handlers?
Can you post second type of difference?

Posted (edited)
	push_reg_sp
	fetch_i

is missed in files from the link, which I posted. Also two jumps at the end

    jump L23975
    jump L23982
L23977
L23982
L23975
    shift_sp -1

 

I think, there is no "no op" operands, and those lines are simply missed from the decompiled/compiled code. Doesn't look good for me. Also, shift_sp -1 is called before exit_handler(). So, caller will receive not-shifted stack

 

I will post second difference, when find some smaller handler for it, right now there are about 30kb obj files

Edited by MasterToma
Posted
2 hours ago, MasterToma said:

	push_reg_sp
	fetch_i

is missed in files from the link, which I posted. Also two jumps at the end


    jump L23975
    jump L23982
L23977
L23982
L23975
    shift_sp -1

 

I think, there is no "no op" operands, and those lines are simply missed from the decompiled/compiled code. Doesn't look good for me. Also, shift_sp -1 is called before exit_handler(). So, caller will receive not-shifted stack

 

I will post second difference, when find some smaller handler for it, right now there are about 30kb obj files

 

I think last “if” in this class should be “select” with one case inside. Jumps looks like “break” inside that case.

I can’t test it today tho.

Posted
1 hour ago, jornik said:

@MasterToma can you please post whole hander code for the original and compiled ai.obj? Can you also share decompiled code?

Everything is inside archive under the link, which I posted. Here it is again: 

https://drive.google.com/file/d/1WZx4FGF_FrkAOkem3bC8Stdd3Y--ixUj/view

 

Decompiled code looks is

class guard_babenco : guard_fixed {
handler:
	EventHandler TALK_SELECTED(talker) {
		if (_from_choice == 0) {
			if (HaveMemo(talker, @path_to_elven_scout) == 1 && GetMemoState(talker, @path_to_elven_scout) == 1) {
				_choiceN = _choiceN + 1;
				_code = 0;
				AddChoice(0, "询问有关废墟的事");
			}

			if (_choiceN > 1) {
				ShowChoicePage(talker, 1);
				return;
			}
		}

		if (_from_choice || _choiceN == 1) {
			if (_code == 0) {
				if (_from_choice == 0 || HaveMemo(talker, @path_to_elven_scout) == 1 && GetMemoState(talker, @path_to_elven_scout) == 1) {
					ShowPage(talker, "guard_babenco_q0407_01.htm");
				}
			}

			return;
		}

		super;
	}
}

There is some mess with _from_choice. Tonight I will try to decompile it manually. 

 

Posted
1 hour ago, MasterToma said:

There is some mess with _from_choice. Tonight I will try to decompile it manually.

 

Replace

if (_code == 0) {
    if (_from_choice == 0 || HaveMemo(talker, @path_to_elven_scout) == 1 && GetMemoState(talker, @path_to_elven_scout) == 1) {
        ShowPage(talker, "guard_babenco_q0407_01.htm");
    }
}

with

select (_code) {
    case 0:
        if (_from_choice == 0 || HaveMemo(talker, @path_to_elven_scout) == 1 && GetMemoState(talker, @path_to_elven_scout) == 1) {
            ShowPage(talker, "guard_babenco_q0407_01.htm");
        }
        
        break;
}

& check compiled code

Posted

Ok, now it works. Another bug with operator precedence. For instance, look at blacksmith_duning (code is too large).

Here is how it should look like:

	fetch_i
	push_const 10
	mod
	mul
	greater_equal
			else if(reply == 6)
				{
					if (OwnItemCount(talker, @q_gold_wyvern) >= (4*(talker.param2 % 10)))
					{
						DeleteItem1(talker, @q_gold_wyvern, 4*(talker.param2 % 10));
						talker.param1 = talker.param1+((Rand(3)+1)*16);
					}
					else
						ShowPage(talker, "blacksmith_duning_q0336_10.htm");	
				}

Note about two points

1. (4*(talker.param2 % 10))

2. ((Rand(3)+1)*4)

 

Decompiler generates 

 

} else if (reply == 6) {
				if (OwnItemCount(talker, @q_gold_wyvern) >= 4 * talker.param2 % 10) {
					if (GetCurrentTick() - talker.quest_last_reward_time > 1) {
						DeleteItem1(talker, @q_gold_wyvern, 4 * talker.param2 % 10);
						talker.param1 = talker.param1 + (Rand(3) + 1) * 4;
						talker.param1 = talker.param1 + (Rand(3) + 1) * 16;
					}
				} else {
					ShowPage(talker, "blacksmith_duning_q0336_10.htm");
				}

1. 4 * talker.param2 % 10

2. (Rand(3) + 1) * 4

 

While point #2 in THIS case is not crucial (but in other cases it might be crucial), point #1 is for sure wrongly decompiled - extra () are missed and cause wrong calculation, which will be

 

	fetch_i
	mul
	push_const 10
	mod
	greater_equal

 

Posted

I've noticed the same with nested &&. Original pseudo-code

if (a && (c && d))

after decompilation will be 

if (a && c && d)

Which is OK. But some times not:

if (a && (c || d))

goes into

if (a && c || d)

 

Trying to find some nice example...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



  • Posts

    • what pack you use  send me on discord for it
    • package custom.events.RandomZoneEvent; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.ScheduledFuture; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.l2jmobius.commons.threads.ThreadPool; import org.l2jmobius.commons.time.SchedulingPattern; import org.l2jmobius.commons.time.TimeUtil; import org.l2jmobius.commons.util.IXmlReader; import org.l2jmobius.gameserver.managers.ZoneManager; import org.l2jmobius.gameserver.model.StatSet; import org.l2jmobius.gameserver.model.actor.Creature; import org.l2jmobius.gameserver.model.actor.Npc; import org.l2jmobius.gameserver.model.actor.Player; import org.l2jmobius.gameserver.model.quest.Event; import org.l2jmobius.gameserver.model.zone.ZoneId; import org.l2jmobius.gameserver.model.zone.ZoneType; import org.l2jmobius.gameserver.model.zone.type.RandomZone; import org.l2jmobius.gameserver.util.Broadcast; /** * Random Zone Event - Activates one random PvP zone temporarily. No modifica la clase de la zona: usa flags PvP en runtime. * @author Juan */ public class RandomZoneEvent extends Event { private static final String CONFIG_FILE = "data/scripts/custom/events/RandomZoneEvent/config.xml"; private static int EVENT_DURATION_MINUTES = 15; private static boolean _isActive = false; private ScheduledFuture<?> _eventTask = null; private final List<ZoneType> _availableZones = new ArrayList<>(); private ZoneType _activeZone = null; public RandomZoneEvent() { loadConfig(); loadZones(); registerZoneListeners(); } /** * Registra listeners a TODAS LAS ZONAS random */ private void registerZoneListeners() { for (ZoneType zone : _availableZones) { addEnterZoneId(zone.getId()); addExitZoneId(zone.getId()); LOGGER.info("[RandomZoneEvent] Registered listener for zone: " + zone.getName()); } } private void loadConfig() { new IXmlReader() { @Override public void load() { parseDatapackFile(CONFIG_FILE); } @Override public void parseDocument(Document doc, File file) { forEach(doc, "event", eventNode -> { final StatSet att = new StatSet(parseAttributes(eventNode)); final String name = att.getString("name"); for (Node node = eventNode.getFirstChild(); node != null; node = node.getNextSibling()) { if ("schedule".equals(node.getNodeName())) { final StatSet attributes = new StatSet(parseAttributes(node)); final String pattern = attributes.getString("pattern"); final SchedulingPattern schedulingPattern = new SchedulingPattern(pattern); final StatSet params = new StatSet(); params.set("Name", name); params.set("SchedulingPattern", pattern); final long delay = schedulingPattern.getDelayToNextFromNow(); getTimers().addTimer("Schedule_" + name, params, delay + 5000, null, null); LOGGER.info("[RandomZoneEvent] Event " + name + " scheduled at " + TimeUtil.getDateTimeString(System.currentTimeMillis() + delay)); } } }); } }.load(); } private void loadZones() { for (ZoneType zone : ZoneManager.getInstance().getAllZones(RandomZone.class)) { if ((zone.getName() != null) && zone.getName().toLowerCase().startsWith("random_zone")) { _availableZones.add(zone); LOGGER.info("[RandomZoneEvent] Loaded zone: " + zone.getName() + " (id=" + zone.getId() + ")"); } } LOGGER.info("[RandomZoneEvent] Total random zones loaded: " + _availableZones.size()); } @Override public void onTimerEvent(String event, StatSet params, Npc npc, Player player) { if (event.startsWith("Schedule_")) { eventStart(null); final SchedulingPattern schedulingPattern = new SchedulingPattern(params.getString("SchedulingPattern")); final long delay = schedulingPattern.getDelayToNextFromNow(); getTimers().addTimer(event, params, delay + 5000, null, null); LOGGER.info("[RandomZoneEvent] Rescheduled for " + TimeUtil.getDateTimeString(System.currentTimeMillis() + delay)); } } @Override public boolean eventStart(Player eventMaker) { if (_isActive) { if (eventMaker != null) { eventMaker.sendMessage("RandomZoneEvent already active."); } return false; } if (_availableZones.isEmpty()) { Broadcast.toAllOnlinePlayers("[RandomZoneEvent] No zones configured."); return false; } _isActive = true; Broadcast.toAllOnlinePlayers("⚔️ Random Zone Event has started!"); _eventTask = ThreadPool.schedule(this::activateRandomZone, 5_000); return true; } private void activateRandomZone() { _activeZone = _availableZones.get(new Random().nextInt(_availableZones.size())); _activeZone.setEnabled(true); Broadcast.toAllOnlinePlayers("🔥 Random Zone Event: " + _activeZone.getName() + " is now PvP for " + EVENT_DURATION_MINUTES + " minutes!"); _eventTask = ThreadPool.schedule(this::eventStop, EVENT_DURATION_MINUTES * 60 * 1000L); } @Override public boolean eventStop() { if (!_isActive) { return false; } _isActive = false; if (_eventTask != null) { _eventTask.cancel(true); _eventTask = null; } if (_activeZone != null) { _activeZone.setEnabled(false); Broadcast.toAllOnlinePlayers("🏁 Random Zone Event ended. " + _activeZone.getName() + " is back to normal."); _activeZone = null; } else { Broadcast.toAllOnlinePlayers("🏁 Random Zone Event ended."); } return true; } @Override public void onEnterZone(Creature creature, ZoneType zone) { if (!_isActive || (_activeZone == null)) { return; } if ((zone == _activeZone) && creature.isPlayable()) { creature.setInsideZone(ZoneId.PVP, true); if (creature.isPlayer()) { creature.sendMessage("Esta zona está en modo PvP temporalmente."); } } } @Override public void onExitZone(Creature creature, ZoneType zone) { if (!_isActive || (_activeZone == null)) { return; } if ((zone == _activeZone) && creature.isPlayable()) { creature.setInsideZone(ZoneId.PVP, false); if (creature.isPlayer()) { creature.sendMessage("Abandonaste la zona PvP temporal."); } } } @Override public boolean eventBypass(Player player, String bypass) { return true; } @Override public String onEvent(String event, Npc npc, Player player) { return super.onEvent(event, npc, player); } @Override public String onFirstTalk(Npc npc, Player player) { return null; } public static void main(String[] args) { new RandomZoneEvent(); } } i have this but its not working
    • ZonePvPSpawnBossRadio=0 ZonePvPSpawnBossBarakiel=0 at the Customs.ini in L2Server folder. Im prety sure this is it because i had the same problem with you in cruma 1 floor for example and i couldn't fix it but i fixed it finally by changing these 2 lines
    • Siege Reward Start PM Msg Rework Config root BossDieAnnounce and BossDieSound in the L24Team.properties and Config.java files for global raid boss death notifications and sounds. Adds a new reward_list table to the DB.sql file to track castle rewards. Improves character creation logic for thread safety and validation. Adds extensive state checks to the RequestEnchantItem method to prevent enchantments during inappropriate player states. Fixed auto-attack animation bug (there was no attack animation, only damage animation) Clean Code Other fixes I forgot to list! Java 14 Fixed issue where deleting a character would prevent it from leaving the screen or being removed, or even after a delete CD (it would only exit when re-logging in or creating a new character). Added Premium System from the other C2 project (Needs testing and improvement). Added the "Improved" Community Board (incomplete).
  • Topics

×
×
  • Create New...

AdBlock Extension Detected!

Our website is made possible by displaying online advertisements to our members.

Please disable AdBlock browser extension first, to be able to use our community.

I've Disabled AdBlock