Jump to content

Recommended Posts

Posted
23 minutes ago, eressea said:

Sorry for doublepost, one more question, I keep getting av_quest0 instead of myself.av_quest0, any idea what can be wrong?


Was bug in NASC generator. Fix in master.

 

46 minutes ago, eressea said:

I'm using tree structure with UTF-8 files and when I build the AI, I go through the directory structure (so I know which is the correct class order) and join all the files into one big UTF-16LE file, then I let it compile and then I split it again to directory structure

 

Sounds convenient. I'll make it default behaviour.

Posted

Thanks a lot :)

 

I've found another problem, in some cases, I get results like this:

if (5 == 100 || Rand(100) < 5) {
	if (35003 == 35001) {
		select (11) {
...

Class + data: http://download.l2shrine.com/decompiler-problem1.zip

 

Posted (edited)
14 minutes ago, eressea said:

Thanks a lot :)

 

I've found another problem, in some cases, I get results like this:


if (5 == 100 || Rand(100) < 5) {
	if (35003 == 35001) {
		select (11) {
...

Class + data: http://download.l2shrine.com/decompiler-problem1.zip

 

 

Seems like code generated correctly, but looks suspicious.

	...
	push_const 5			//unary->INTEGER_CONST
	push_const 100			//unary->INTEGER_CONST
	equal
	...
	push_const 35002			//unary->INTEGER_CONST
	push_const 35001			//unary->INTEGER_CONST
	equal
	...

Stack machine in my head generates same code as decompiler :)

 

BTW: Can I push your h5 data folder to my repository? Also the '@' prefixes in enums.json now not needed (because of generators to another languages), & type P_STATE renamed to PSTATE.

Edited by verbrannt
Posted

Oh, I didn't notice that, well, that's really strange... Also my compiler complains somewhere there: "Stack underflow may be occurred by unary constant" - maybe the select (11)?

Posted
2 minutes ago, eressea said:

Oh, I didn't notice that, well, that's really strange... Also my compiler complains somewhere there: "Stack underflow may be occurred by unary constant" - maybe the select (11)?

Yeah, this warning because of constants in statements like select/if/while.
I think NCSoft uses some sort of preprocessor for AI scripts, that generates such strange code.

Posted
12 minutes ago, verbrannt said:

Yeah, this warning because of constants in statements like select/if/while.
I think NCSoft uses some sort of preprocessor for AI scripts, that generates such strange code.

 

For me it seems the ai.obj I'm trying to decompile has already been decompiled (but wrong) and recompiled... So I'll probably have to fix these manually...

 

Great job, the decompiler works nice :)

Posted (edited)

Updated h5 definitions http://download.l2shrine.com/h5.zip

 

EDIT: Found one more new problem, if I have 'star_buster_rsk.focus' in precompiled headers, it generates @star_buster_rsk.focus which fails to compile (needs to be quoted like this @"star_buster_rsk.focus")

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

Updated h5 definitions http://download.l2shrine.com/h5.zip

 

EDIT: Found one more new problem, if I have 'star_buster_rsk.focus' in precompiled headers, it generates @star_buster_rsk.focus which fails to compile (needs to be quoted like this @"star_buster_rsk.focus")

Thx for h5 defs!

As for precompiled headers issue, I didn't knew such syntax is possible (dots in these constants). I've added simple check for dot, and if dot exists, constant will be quoted. Checkout the master branch.

 

Quote

For me it seems the ai.obj I'm trying to decompile has already been decompiled (but wrong) and recompiled... So I'll probably have to fix these manually...

 

Idk. Found similar code in the leaked GF AI. Class ssq_npc_priest for example:
 

if (2 == 2) {
    ShowSystemMessage(talker, 1273);
} else if (2 == 1) {
    ShowSystemMessage(talker, 1274);
}

select (1) {
case 1:
    ShowSystemMessage(talker, 1275);
    break;
case 2:
    ShowSystemMessage(talker, 1276);
    break;
case 3:
    ShowSystemMessage(talker, 1277);
    break;
}

 

Edited by verbrannt
Posted

Great, now it works fine :)

 

Another problem, I get this:

Say("판정식 : " + myself.i_ai6 + " - " + FloatToInt(myself.sm.hp) + " = " + myself.i_ai6 - FloatToInt(myself.sm.hp));

which is wrong (won't compile) because there's no minus operation for strings. It should be parenthesised:

Say("판정식 : " + myself.i_ai6 + " - " + FloatToInt(myself.sm.hp) + " = " + (myself.i_ai6 - FloatToInt(myself.sm.hp)));

It's a minor bug (it's just once in whole ai) but it's bit annoying to have to fix it manually ;)

Posted
25 minutes ago, eressea said:

Great, now it works fine :)

 

Another problem, I get this:


Say("판정식 : " + myself.i_ai6 + " - " + FloatToInt(myself.sm.hp) + " = " + myself.i_ai6 - FloatToInt(myself.sm.hp));

which is wrong (won't compile) because there's no minus operation for strings. It should be parenthesised:


Say("판정식 : " + myself.i_ai6 + " - " + FloatToInt(myself.sm.hp) + " = " + (myself.i_ai6 - FloatToInt(myself.sm.hp)));

It's a minor bug (it's just once in whole ai) but it's bit annoying to have to fix it manually ;)

 

Fixed.

Posted (edited)

Thanks :)

 

Found another problem that needs to be handled in order to work with H5+ AI correctly. NCsoft apparently moved FString stuff to client side, so now there's

		{1120131; -111092; 232173; -3448; 0; 0 }

instead of

		{"Discarded Guardian (lv20)"; -111092; 232173; -3448; 0; 0 }

in the ai.obj. It should decompile to

		{1120131; -111092; 232173; -3448; 0; 0};

and not to

		{"1120131"; -111092; 232173; -3448; 0; 0};

when NASCVersion is 60+

 

EDIT: Already fixed in my h5 compiler branch

 

EDIT2: Also I've removed fstring lookup on 3 different places so it probably won't be just TelPosList but maybe another 1-2 things...

 

Edited by eressea
Posted
21 minutes ago, eressea said:

Thanks :)

 

Found another problem that needs to be handled in order to work with H5+ AI correctly. NCsoft apparently moved FString stuff to client side, so now there's


		{1120131; -111092; 232173; -3448; 0; 0 }

instead of


		{"Discarded Guardian (lv20)"; -111092; 232173; -3448; 0; 0 }

in the ai.obj. It should decompile to


		{1120131; -111092; 232173; -3448; 0; 0};

and not to


		{"1120131"; -111092; 232173; -3448; 0; 0};

when NASCVersion is 60+

 

EDIT: Already fixed in my h5 compiler branch

 

EDIT2: Also I've removed fstring lookup on 3 different places so it probably won't be just TelPosList but maybe another 1-2 things...

 

 

Can you make a PR or patch?

Posted
Just now, verbrannt said:

 

Can you make a PR or patch?

 

I'm not sure how propagate NASC version to parser.php, if it was there, the fix would be easy:

 

        if (is_numeric($row[0])) {
            $row[0] = '"' . $this->data->getString($row[0]) . '"';
        }

should be called only if $nascVersion >= 60

Posted

Also, when speaking about NASC versions, the right data directory could be chosen automatically according to the version:
gf = 2, freya = 56, h5 = 60, gd = 73

Posted
5 minutes ago, eressea said:

 

I'm not sure how propagate NASC version to parser.php, if it was there, the fix would be easy:

 


        if (is_numeric($row[0])) {
            $row[0] = '"' . $this->data->getString($row[0]) . '"';
        }

should be called only if $nascVersion >= 60

 

So FString lookup should be removed from all places, no need to check NASC version. Anyway getString method not working now.

 

3 minutes ago, eressea said:

Also, when speaking about NASC versions, the right data directory could be chosen automatically according to the version:
gf = 2, freya = 56, h5 = 60, gd = 73

 

Yeah, I thought about it.

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