Jump to content

Recommended Posts

Posted

I don't really work on L2j anymore, but from time to time, I check up the forums just in case someone built something cool, and I stumbled upon this:

It's actually really easy to implement LLMs (both local, like gpt-oss, and online, like ChatGPT or Gemini) for any sort of action in L2.

Even without training a model explicitly, a good GPU and some basic LLM knowledge can take you very far. 

Here is an example of an auto play bot I made in 10 minutes that uses gpt-oss (which is mega overkill) locally with a 5090 to do some basic farming.
As you can see from the LM Studio responses, it is fairly fast (and uses reasoning too) to think about what's the best course of action for a given situation.
 

 

Basically just a quick proof of concept. If I had time, I would make something like this for auto-play/farm or bots, since LLMs would play really nicely with fake players that can actually think and are not completely pre-programmed. It's quite cool.

  • Like 4
Posted

Interesting. If I use one of those weaker LLMs locally that can even be connected to a VPS with a few GBs, will it also work?

If it is to do simple jobs

Posted
18 minutes ago, Litch said:

Interesting. If I use one of those weaker LLMs locally that can even be connected to a VPS with a few GBs, will it also work?

If it is to do simple jobs

You'll need to test it, but you need at least some decent GPU power for it to be reasonably fast. What you can also do is predictive actions, so send a single request that is bigger, let it take some time and then instruct the response to include a batch of 5-10 followup actions which can be processed on the client (the l2 server).

  • Like 1
Posted

AI hype from dumb AF devs at it's best.

The video shows a character doing the most predictable loop imaginable attack, loot, repeat. You don't need a "reasoning" LLM for that. A lightweight task scheduler or even a basic script can handle it with a fraction of the resources and zero GPU overhead.

 

Spinning up a big language model to decide "hit the mob and pick up the drop" isn’t clever, it is wasteful. It's like hiring a rocket scientist to flip a light switch: impressive hardware, pointless job.

  • Upvote 2
Posted (edited)
1 hour ago, Mobius said:

AI hype from dumb AF devs at it's best.

The video shows a character doing the most predictable loop imaginable attack, loot, repeat. You don't need a "reasoning" LLM for that. A lightweight task scheduler or even a basic script can handle it with a fraction of the resources and zero GPU overhead.

 

Spinning up a big language model to decide "hit the mob and pick up the drop" isn’t clever, it is wasteful. It's like hiring a rocket scientist to flip a light switch: impressive hardware, pointless job.

 

Ofc it does 🙂 . All it was trained on was farming for levelling. It's not about doing something unpredictable. It's about potential.

Feed it a bigger context and train it on class-specific fighting patterns, buffing, item values, trading, chatting in L2 lingo, reading trade chat, party-based farming, crafting goals, etc, and you have something that a normal deterministic bot would take a really long time coding to achieve.

 

Add that to all of the work being offloaded to a model instead of the gameserver, and you have a much better solution that feels way more natural. Ofc you can do pretty much everything with a state machine but you'd have to write insane amounts of code. It's a waste of time.

Don't be blindsided by your hate for AI. There is considerable potential here.

Edited by Elfo
  • Upvote 1
Posted

Don't get me wrong, I have no hate for AI. The potential for LLMs in gaming, especially for creating dynamic NPC dialogues or complex, adaptive game masters, is immense. The point of my previous post wasn't to dismiss AI as a whole, but to question its practical application for this specific, solved problem.
 

However, the example given (basic farming) is the worst possible use case to demonstrate this potential. It's the equivalent of using a fusion reactor to power a desk lamp. The overhead is astronomical compared to the task.


The core of my argument is about efficiency and the right tool for the job. For the predictable, loop-based behavior of auto-farming, a state machine is not just adequate; it is superior. It is lightweight, incredibly fast, reliable, and consumes negligible resources.
 

To prove it's not about the volume of code but the efficiency of execution,
here is the entirety of the auto-play logic for my server:
AutoPlayTaskManager 400 lines of code:
AutoUseTaskManager 470 lines of code:


This code provides full, retail-like auto-play support for all classes, including offline play.
It runs on any standard VPS without a dedicated GPU, using a tiny fraction of CPU cycles.


An LLM-based solution for this same task, even a "weaker" one, would:
-Introduce significant latency (response time) for each decision.
-Require expensive GPU hardware to run locally or incur API costs for cloud services.
-Add immense complexity for parsing natural language responses back into game actions.
-Be inherently less reliable than a simple "if mob dead -> loot" check.


So, while I agree the research is "quite cool" as a proof-of-concept, championing it as a practical solution for auto-farming is where the "AI hype" label fits. The real innovation would be applying that LLM power to a problem a state machine can't easily solve, not one it already solves perfectly.

Posted

Yeah, that's fair. I'll create a full AI-based fake player engine out of this to see how far it can go.

Posted (edited)

Fake players system is already in use 5-6 years know that i know for sure, before even ai come up. There is even whole system with automated players that can make any simple move, pvp, farm, or even answer you on chat and pm's. All this before ai, you can imagine now what we will see.

Edited by Atom
Posted
On 9/22/2025 at 11:12 AM, Mobius said:

Don't get me wrong, I have no hate for AI. The potential for LLMs in gaming, especially for creating dynamic NPC dialogues or complex, adaptive game masters, is immense. The point of my previous post wasn't to dismiss AI as a whole, but to question its practical application for this specific, solved problem.
 

However, the example given (basic farming) is the worst possible use case to demonstrate this potential. It's the equivalent of using a fusion reactor to power a desk lamp. The overhead is astronomical compared to the task.


The core of my argument is about efficiency and the right tool for the job. For the predictable, loop-based behavior of auto-farming, a state machine is not just adequate; it is superior. It is lightweight, incredibly fast, reliable, and consumes negligible resources.
 

To prove it's not about the volume of code but the efficiency of execution,
here is the entirety of the auto-play logic for my server:
AutoPlayTaskManager 400 lines of code:
AutoUseTaskManager 470 lines of code:


This code provides full, retail-like auto-play support for all classes, including offline play.
It runs on any standard VPS without a dedicated GPU, using a tiny fraction of CPU cycles.


An LLM-based solution for this same task, even a "weaker" one, would:
-Introduce significant latency (response time) for each decision.
-Require expensive GPU hardware to run locally or incur API costs for cloud services.
-Add immense complexity for parsing natural language responses back into game actions.
-Be inherently less reliable than a simple "if mob dead -> loot" check.


So, while I agree the research is "quite cool" as a proof-of-concept, championing it as a practical solution for auto-farming is where the "AI hype" label fits. The real innovation would be applying that LLM power to a problem a state machine can't easily solve, not one it already solves perfectly.

This was made with AI? I have tried to make my own custom gpt on chatgpt, I added all the server files in the knowledge base but again it is not consistent enough. If you people use it for your projects what is your workflow?

Posted
1 hour ago, aris96 said:

This was made with AI? I have tried to make my own custom gpt on chatgpt, I added all the server files in the knowledge base but again it is not consistent enough. If you people use it for your projects what is your workflow?

You have to treat him like a woman maybe, speak is not enought 😛

Posted

The idea of being able to create a "chatbot" with missions and quests, fully customized with LLM, is interesting, instead of an "auto-farm".

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