[RELEASE] Quality of life gameserver mods

Page 1 of 4 1234 LastLast
Results 1 to 15 of 48
  1. #1
    Enthusiast feanturi is offline
    MemberRank
    Mar 2018 Join Date
    PolandLocation
    28Posts

    [RELEASE] Quality of life gameserver mods

    Hi,
    Hope BDO is treating you all well ^^

    So I decided to learn a bit about the server and while I don’t really have anything groundbreaking to share, I figured that someone can find those thingies at least useful. Or funny. It’s a collection of little quality-of-life changes – mostly additional configuration options.

    Be advised, those are based on DevilSpeak’s server repack, but I expect it to be compatible with whatever gameserver.jar file you’re using. As always when editing any files, be caution and keep backups ;)

    At the end of the post you’ll find a link to archive with all modified files compiled into .class files. Please, before replacing any parts of your gameserver.jar read entire post and ensure that you’re replacing all required files, since some files contain more than one change. Don’t forget - you’ll also have to manually change required .properties files.

    Now, I’m sure that implementation of some of those may be far from ideal, so if you know better ways and you feel like sharing your methods, I’ll be more than grateful.

    One last note – line numbers may not be precise. Just try to look a bit around the spot to search for same-ish looking code.

    1. /server sync
    This is a new chat command I added as workaround for disappearing NPCs. In a nutshell, it asks server to re-sent list of Creatures that should be visible for you in your current location. This re-spawns all alive Creatures on clients. Now, to be clear – this is NOT a fix for the problem, but using chat command is just faster and more convenient than re-logging.

    Implementation:

    WorldMap.java (line 203):
    Code:
    /* change method’s accessor from private to public */
    
    public void notifyEnter(final Creature creature, final GameSector newSector, final boolean isNewSpawn, final boolean isRespawn) {}
    ServerCommandHandler.java:
    Code:
    /* add method /*
    
     @commandHandlerMethod
    public static Object[] sync(final Player player, final String... params){
        WorldMap worldMap = World.getInstance().getWorldMap();
        worldMap.notifyEnter(player, worldMap.getGameSectorByCoords(player.getLocation().getX(), player.getLocation().getY()), false, false);
        return new Object[]{EChatResponseType.Accepted, "Server synchronised."};
    }
    2. Adrenaline multiplier
    This allows to set a multiplier for adrenaline gain. From level 35 you’ll be getting a 1% of adrenaline for each kill. This configuration option lets you multiply this by an INTEGER value. You can change it go gain 2, 3, 10 or whatever value up to 100 per kill. You can put 0 to stop adrenaline gain, too. What you can’t do is to put a fraction in there, so 0.5 to just slow down adrenaline gain will not work.

    Implementation:

    BattleOptionConfig.java:
    Code:
    /* add entry */
    
     @ConfigComments(comment = {"Adrenaline super skill progress multiplier", "Default: 1"})
     @ConfigProperty(name = "AdrenalineMultiplier", value = "1")
    public static int ADRENALIN_SUPER_SKILL_MULTIPLIER;
    AttackResult.java (line 600):
    Code:
    /* multiply (or replace) value in addAdrenaline() */
    
    if (player.getLevel() >= BattleOptionConfig.ADRENALIN_SUPER_SKILL_MIN_LEVEL && target.isDead() && dmg > 0.0)
        player.getGameStats().getAdrenalin().addAdrenalin(1 * BattleOptionConfig.ADRENALIN_SUPER_SKILL_MULTIPLIER, false);
    Battleoption.properties:
    Code:
    # add entry
    
    # Adrenaline super skill progress multiplier
    # Default: 1
    AdrenalineMultiplier = 2
    3. Attack damage multiplier
    Let’s you modify the damage you do to monsters and other player and how much will monsters do to you. This adds a multiplier that influences the (more-or-less) final damage number that is later passed to the target to lower their health. I added it to tweak the combat into more hard-core PvE experience and use it with re-spawn delay described below.

    Implementation:

    BattleOptionConfig.java:
    Code:
    /* add entries */
    
     @ConfigComments(comment = {"Final multiplier for damage done by monster to players", "Default: 1.0"})
     @ConfigProperty(name = "AttackDamageMultiMonsterToPlayer", value = "1.0")
    public static float ATTACK_DAMAGE_MULTI_MONSTER_TO_PLAYER;
    
     @ConfigComments(comment = {"Final multiplier for damage done by player to monsters and other players", "Default: 1.0"})
     @ConfigProperty(name = "AttackDamageMultiPlayerToMonster", value = "1.0")
    public static float ATTACK_DAMAGE_MULTI_PLAYER_TO_MONSTER;
    AttackResult.java (line 576):
    Code:
    /* you need to add ‘Final multiplier assignment’ section between ‘Block calculation’ and ‘Health updates’. I include both those section in the snippet just to help with orientation. */
    
    //////////////////////////////// Blocks Calculation
    if (isFrontSideAttack && target.getActionStorage().getActionChartActionT().getGuardType().isDefence()) {
        // If update is success, then deflect the damage.
        if (target.getGameStats().getStunGauge().updateStunGauge(-dmg)) {
            dmgType = EDmgType.Block;
            dmg = 1;
        }
    }
    
    //////////////////////////////// Final multiplier assignment
    if (!isAttackerPlayerOrSummon() && target.isPlayer()) { // monster vs player
        dmg = dmg * BattleOptionConfig.ATTACK_DAMAGE_MULTI_MONSTER_TO_PLAYER;
    }else{ // player vs player, player vs monster
        dmg = dmg * BattleOptionConfig.ATTACK_DAMAGE_MULTI_PLAYER_TO_MONSTER;
    }
    
    //////////////////////////////// Health updates
    if (!Double.isNaN(dmg) && !Double.isInfinite(dmg)) {
        if (dmg > 0)
            target.getGameStats().getHp().updateHp(-dmg, attacker, true);
    } else {
        dmg = 0;
        dmgType = EDmgType.Evasion;
        return true;
    }
    Battleoption.properties:
    Code:
    # add entries
    
    # Final multiplier for damage done by monster to players
    # Default: 1.0
    AttackDamageMultiMonsterToPlayer = 2.0
    
    # Final multiplier for damage done by player to monsters and other players
    # Default: 1.0
    AttackDamageMultiPlayerToMonster = 0.05
    4. Spawn delay
    Allows for controlling respawn times of monsters. When you start the server all monsters are spawned, and when you kill them they will re-spawn after normal time PLUS value of this property. This is not a multiplier – this adds time (in milliseconds) to re-spawn timers.

    Implementation:

    BattleOptionConfig.java:
    Code:
    /* add entry */
    
     @ConfigComments(comment = {"Additional time in MILISECONDS that's added to all monsters re-spawn time.", "Default: 0"})
     @ConfigProperty(name = "AdditionalSpawnDelay", value = "0")
    public static int ADDITIONAL_SPAWN_DELAY;
    RespawnService.java (lines 40 and 47):
    Code:
    /* add the entry at the end of calculation lines. For clarity, I’m adding entire code to the snippet */
    
    public void putBody(final DeadBody deadBody) {
        if (deadBody.canRespawn()) {
            final CreatureTemplate template = deadBody.getTemplate();
            deadBody.setRespawnTime(System.currentTimeMillis() + template.getSpawnDelayTime() + Rnd.get(0, template.getSpawnVariableTime()) + BattleOptionConfig.ADDITIONAL_SPAWN_DELAY);
            this.map.put(deadBody.getGameObjectId(), deadBody);
        }
    }
    
    public void putCollect(final Collect collect) {
        final CollectTemplate template = collect.getCollectTemplate();
        collect.setRespawnTime(System.currentTimeMillis() + template.getSpawnDelayTime() + Rnd.get(0, template.getSpawnVariableTime()) + BattleOptionConfig.ADDITIONAL_SPAWN_DELAY);
        this.map.put(collect.getGameObjectId(), collect);
    }
    battleoption.properties:
    Code:
    # add entry
    
    # Additional time in MILISECONDS that's added to all monsters re-spawn time.
    # Default: 0
    # 18000000 = 5 hours
    AdditionalSpawnDelay = 18000000
    5. Energy regen
    This let’s you set the amount of energy regenerated per tick.

    Implementation:

    EtcOptionConfig.java:
    Code:
    /* add entry */
    
     @ConfigComments(comment = {"Base WP regen per tick", "Default: 1.0"})
     @ConfigProperty(name = "BaseWPRegen", value = "1.0")
    public static float BASE_WP_REGEN;
    PlayerStatTemplate.java (line 55):
    Code:
    /* change value in BaseElement constructor */
    
    this.baseContainer.put(StatEnum.WPRegen, new BaseElement(EtcOptionConfig.BASE_WP_REGEN));
    etcoption.properties:
    Code:
    # add entry
    
    # Base WP regen per tick
    # Default: 1.0
    BaseWPRegen = 1000.0
    6. Drop quantity multiplier
    Removed. New, fixed implementation was posted below.

    If you have any question, ask away. Just keep in mind that I’m new to this, so please, be extra careful if you’ll try to implement any of those mods.
    So… have fun :)
    Last edited by feanturi; 12-04-18 at 06:17 PM. Reason: Removed outdated download link


  2. #2
    Apprentice meymeygila is offline
    MemberRank
    Apr 2018 Join Date
    8Posts

    Re: [RELEASE] Quality of life gameserver mods

    Awesome release, thanks.

  3. #3
    Apprentice momz is offline
    MemberRank
    May 2016 Join Date
    22Posts

    Re: [RELEASE] Quality of life gameserver mods

    Hi Men ! thanx for sharing this awesome tweaks :)

  4. #4
    Valued Member gorkn is offline
    MemberRank
    Dec 2016 Join Date
    102Posts

    Re: [RELEASE] Quality of life gameserver mods

    Nice job on the mods. Will it ever be possible to mod how the server handles NPC spawns and patrolling so it isn't so resource hungry?

  5. #5
    Apprentice momz is offline
    MemberRank
    May 2016 Join Date
    22Posts

    Re: [RELEASE] Quality of life gameserver mods

    Try to find some useless npc ids like villagers and traveling npcs who just stays in roads in spawn data XMLs and just delete

  6. #6
    Enthusiast feanturi is offline
    MemberRank
    Mar 2018 Join Date
    PolandLocation
    28Posts

    Re: [RELEASE] Quality of life gameserver mods

    Hey!
    So, bad news - looks like Drop quantity multiplier have a bug, which cause a crash of a client... if you harvest without any tool equipped? Wow, kinda random :D
    In any case, hope to have a fix for that soon.

    EDIT:
    Ok, turns out it was my IDE that was being silly and figured it don't need to compile files, messing up my own gameserver.jar in the process. All code snippets are fine. Can't be sure about the .class files in the archive, though. If anyone have any troubles with them just tell me so I upload new set. I may do that anyways with any new fixes, too.

    Oh, by the way, I noticed that point 4 "Spawn delay" was missing .properties file section so at least that's fixed now.
    Last edited by feanturi; 06-04-18 at 08:54 PM.

  7. #7
    Enthusiast feanturi is offline
    MemberRank
    Mar 2018 Join Date
    PolandLocation
    28Posts

    Re: [RELEASE] Quality of life gameserver mods

    And that's why I told you guys to always keep backups... The Drop quantity multiplier mod was kinda messy and didn't worked as intended. I removed it from first post and below you'll find fixed and expanded version.

    6. Drop quantity multiplier
    This config allows to change the quantity of stacks that drop from monsters and while gathering. This is a bit complicated, though. Since I didn’t like to always pick up exactly same number of items in the stack this multiplier is actually randomized. You can provide a range and the code will select a number from that range and multiply the stack quantity by that number. In config file you set low end of the range and high end of the range separated by a comma.

    How the math works is as follows - when you're about to pick up any kind of random loot the game will set the default quantity. Then this will be MULTIPLIED by General Drop Multiplier. In next step a handler for different type of loot will take over - gathering, fishing, stealing, moster drop - you name it. In there it will by MULTIPLIED again by proper multiplier.

    Example:

    Assume you'll set following values:
    Code:
    rate.general.drop.multiplier = 5, 15
    rate.collection.drop.multiplier = 7, 13
    While cutting a tree you would by default get 2 logs. Server will pick a random multiplier from <5,15> range (let's say 7) and calculate then number of logs as 14. Then it will sent those 14 logs to collection handler, which will select its own random multiplier from <7,13> range (let's say 10) and calculate number of logs as 140 (2 * 7 * 10). This number of logs will be sent to the client.

    In a nutshell, rate.general.drop.multiplier is used to bump drop across the entire game and then all other settings can additionally rise drop in specific type of loot. It's a bit convoluted, but I hope I explained it well enough.

    Implementation:

    RateConfig.java:
    Code:
    /* add following entries */
    
        @ConfigComments(comment = {"General drop count random multiplier range", "Default: 5, 15"})
        @ConfigProperty(name = "rate.general.drop.multiplier", value = "5, 15")
        public static int[] GENERAL_DROP_MULTIPLIER;
    
        @ConfigComments(comment = {"Monster drop count random multiplier range", "Default: 5, 15"})
        @ConfigProperty(name = "rate.monster.drop.multiplier", value = "5, 15")
        public static int[] MONSTER_DROP_MULTIPLIER;
    
        @ConfigComments(comment = {"Collection drop count random multiplayer range", "Default: 5, 15"})
        @ConfigProperty(name = "rate.collection.drop.multiplier", value = "5, 15")
        public static int[] COLLECTION_DROP_MULTIPLIER;
    
        @ConfigComments(comment = {"Fishing drop count random multiplayer range", "Default: 5, 15"})
        @ConfigProperty(name = "rate.fishing.drop.multiplier", value = "5, 15")
        public static int[] FISHING_DROP_MULTIPLIER;
    
        @ConfigComments(comment = {"Fishing drop count random multiplayer range", "Default: 5, 15"})
        @ConfigProperty(name = "rate.steal.drop.multiplier", value = "5, 15")
        public static int[] STEAL_DROP_MULTIPLIER;
    ItemMainGroupService.java (line 81):
    Code:
    /* you need to replace existing if() statement. In the snippet you’ll find the original code in // comments and the code to replace it with is below that */
    
    //if (itemTemplate.isStack() && Rnd.getChance(killer.getGameStats().getDoubleDropItemLuck().getIntValue() / 10000)) {
                //    itemCount *= 2;
                //}
    
    if (itemTemplate.isStack()){
                    itemCount *= ThreadLocalRandom.current ().nextInt(RateConfig.GENERAL_DROP_MULTIPLIER[0], RateConfig.GENERAL_DROP_MULTIPLIER[1] + 1);
                    if(Rnd.getChance(killer.getGameStats().getDoubleDropItemLuck().getIntValue() / 10000)){
                        itemCount *= 2;
                    }
                }
    DeadBody.java (lines 53 and 87):
    Code:
    /* you need to add a loop to iterate through all items in created drop bag and, if item is stackable, apply multiplier */
    
    /* line 53 */
    this.dropBag = ItemMainGroupService.getDropBag(dropId, (Player) killer, this.getGameObjectId(), this.getCreatureId(), EDropBagType.DeadBody, RateConfig.MONSTER_DROP_RATE);
                    if(this.dropBag != null) {
                        for (final Item droppedItem : this.dropBag.getDropMap().values()) {
                            if(droppedItem.getTemplate().isStack()) {
                                droppedItem.setCount(droppedItem.getCount() * ThreadLocalRandom.current ().nextInt(RateConfig.MONSTER_DROP_MULTIPLIER[0], RateConfig.MONSTER_DROP_MULTIPLIER[1] + 1));
                            }
                        }
                    }
                    this.winnerGameObjId = aggroInfo.getKillerSession();
    
    /* line 87 */
    this.dropBag = ItemMainGroupService.getDropBag(dropId, (Player) killer, this.getGameObjectId(), this.getCreatureId(), EDropBagType.DeadBody, RateConfig.MONSTER_DROP_RATE);
                    if(this.dropBag != null) {
                        for (final Item droppedItem : this.dropBag.getDropMap().values()) {
                            if(droppedItem.getTemplate().isStack()) {
                                droppedItem.setCount(droppedItem.getCount() * ThreadLocalRandom.current ().nextInt(RateConfig.MONSTER_DROP_MULTIPLIER[0], RateConfig.MONSTER_DROP_MULTIPLIER[1] + 1));
                            }
                        }
                    }
                    this.winnerGameObjId = aggroInfo.getKillerSession();
    FrameEventCollect.java (line 66):
    Code:
    /* you need to add the item.setCount() line. For clarity I’m adding entire for loop in the snippet */
    
    for (final Item item : dropBag.getDropMap().values()) {
                    item.setCount(item.getCount() * ThreadLocalRandom.current ().nextInt(RateConfig.COLLECTION_DROP_MULTIPLIER[0], RateConfig.COLLECTION_DROP_MULTIPLIER[1] + 1));
                    LifeActionEXPData.getInstance().reward(player, item.getItemId(), (dropBagType == EDropBagType.CollectTentInstallation) ? ELifeExpType.Farming : ELifeExpType.Gather);
                    player.getObserveController().notifyObserver(EObserveType.gatherItem, item.getItemId(), item.getEnchantLevel(), item.getCount(), player.getObjectId());
                }
    AFishingAction.java (line 110):
    Code:
    /* apply multiplier just before sending drop bag to player */
    
    dropBag.setValidityTime(startTime);
                for (final Item droppedItem : dropBag.getDropMap().values()) {
                    if (droppedItem.getTemplate().isStack()) {
                        droppedItem.setCount(droppedItem.getCount() * ThreadLocalRandom.current ().nextInt(RateConfig.FISHING_DROP_MULTIPLIER[0], RateConfig.FISHING_DROP_MULTIPLIER[1] + 1));
                    }
                }
                player.getPlayerBag().setDropBag(dropBag);
    FrameEventSteal.java (line 71):
    Code:
    /* apply multiplier just before sending drop bag to player */
    
    if (dropBag != null) {
                for (final Item droppedItem : dropBag.getDropMap().values()) {
                    if(droppedItem.getTemplate().isStack()) {
                        droppedItem.setCount(droppedItem.getCount() * ThreadLocalRandom.current ().nextInt(RateConfig.STEAL_DROP_MULTIPLIER[0], RateConfig.STEAL_DROP_MULTIPLIER[1] + 1));
                    }
                }
                player.getPlayerBag().setDropBag(dropBag);
                player.sendPacket(new SMGetDroppedItems(npcGameObjId, dropBag));
            } else {
    rate.properties:
    Code:
    # add entries. To disable particular multiplier set its value to "1, 1" (without quotation marks)
    
    # General drop count random multiplier range
    # Default: 5, 15
    rate.general.drop.multiplier = 5, 15
    
    # Monster drop count random multiplier range
    # Default: 5, 15
    rate.monster.drop.multiplier = 5, 15
    
    # Collection drop count random multiplayer range
    # Default: 5, 15
    rate.collection.drop.multiplier = 5, 15
    
    # Fishing drop count random multiplayer range
    # Default: 5, 15
    rate.fishing.drop.multiplier = 5, 15
    
    # Fishing drop count random multiplayer range
    # Default: 5, 15
    rate.steal.drop.multiplier = 5, 15
    There... Now it should work :)
    Last edited by feanturi; 12-04-18 at 06:16 PM. Reason: Removed outdated download link

  8. #8
    Account Upgraded | Title Enabled! cintapw is online now
    MemberRank
    Apr 2011 Join Date
    279Posts

    Re: [RELEASE] Quality of life gameserver mods

    for attack multiplier, can you make a config separately for attack player to player and player to monster?

  9. #9
    Enthusiast feanturi is offline
    MemberRank
    Mar 2018 Join Date
    PolandLocation
    28Posts

    Re: [RELEASE] Quality of life gameserver mods

    Quote Originally Posted by cintapw View Post
    for attack multiplier, can you make a config separately for attack player to player and player to monster?
    Sure. I'll post it today or tomorrow.

  10. #10
    Enthusiast feanturi is offline
    MemberRank
    Mar 2018 Join Date
    PolandLocation
    28Posts

    Re: [RELEASE] Quality of life gameserver mods

    Below you will find an expanded attack multiplier mod along with some new weather system configuration.

    7. Attack damage multiplier (v.2)
    Let’s you modify the damage you do to monsters and other player and how much will monsters do to you. This adds a multiplier that influences the (more-or-less) final damage number that is later passed to the target to lower their health. I added it to tweak the combat into more hard-core PvE experience and use it with re-spawn delay described above.

    Implementation:

    BattleOptionConfig.java:
    Code:
    /* add entries */
    
        @ConfigComments(comment = {"Final multiplier for damage done by monster to players", "Default: 1.0"})
        @ConfigProperty(name = "AttackDamageMultiMonsterToPlayer", value = "1.0")
        public static float ATTACK_DAMAGE_MULTI_MONSTER_TO_PLAYER;
    
        @ConfigComments(comment = {"Final multiplier for damage done by player to monsters and other players", "Default: 1.0"})
        @ConfigProperty(name = "AttackDamageMultiPlayerToMonster", value = "1.0")
        public static float ATTACK_DAMAGE_MULTI_PLAYER_TO_MONSTER;
    
        @ConfigComments(comment = {"Final multiplier for damage done by player to players", "Default: 1.0"})
        @ConfigProperty(name = "AttackDamageMultiPlayerToPlayer", value = "1.0")
        public static float ATTACK_DAMAGE_MULTI_PLAYER_TO_PLAYER;
    AttackResult.java (line 567):
    Code:
    /* insert Final multiplier assignment section between Blocks Calculation and Health updates. For clarity, both section included in the snippet */
    
            //////////////////////////////// Blocks Calculation
            if (isFrontSideAttack && target.getActionStorage().getActionChartActionT().getGuardType().isDefence()) {
                // If update is success, then deflect the damage.
                if (target.getGameStats().getStunGauge().updateStunGauge(-dmg)) {
                    dmgType = EDmgType.Block;
                    dmg = 1;
                }
            }
    
            //////////////////////////////// Final multiplier assignment
            if(isAttackerPlayerOrSummon()){ // player attacks...
                if(target.isPlayer()) { // ...another player
                    dmg = dmg * BattleOptionConfig.ATTACK_DAMAGE_MULTI_PLAYER_TO_PLAYER;
                }else { // ... a monster
                    dmg = dmg * BattleOptionConfig.ATTACK_DAMAGE_MULTI_PLAYER_TO_MONSTER;
                }
            }else{ // monster vs player
                dmg = dmg * BattleOptionConfig.ATTACK_DAMAGE_MULTI_MONSTER_TO_PLAYER;
            }
    
            //////////////////////////////// Health updates
            if (!Double.isNaN(dmg) && !Double.isInfinite(dmg)) {
                if (dmg > 0)
                    target.getGameStats().getHp().updateHp(-dmg, attacker, true);
            } else {
                dmg = 0;
                dmgType = EDmgType.Evasion;
                return true;
            }
    battleoption.properties:
    Code:
    # add entries
    
    # Final multiplier for damage done by monster to players
    # Default: 1.0
    AttackDamageMultiMonsterToPlayer = 2.0
    
    # Final multiplier for damage done by player to monsters and other players
    # Default: 1.0
    AttackDamageMultiPlayerToMonster = 0.1
    
    # Final multiplier for damage done by player to players
    # Default: 1.0
    AttackDamageMultiPlayerToPlayer = 1.0
    8. Enable Weather Service by default
    If you're sick of typing /weather every time you log in... ;)
    Be warned - this is not a fix for any problems weather service may have. There are reports about it being a serious drain on resources for some people, so use that on your own discretion.

    Implementation:

    EtcOptionConfig.java:
    Code:
    /* add entry */
    
        @ConfigComments(comment = {"Should weather be enabled by default for all players?", "Default: true"})
        @ConfigProperty(name = "EnableWeatherOnStart", value = "true")
        public static boolean ENABLE_WEATHER_ON_START;
    WeatherService.java (lines 43 and 78):
    Code:
    /* at line 43 replace private WeatherService() constructor */
    
        private WeatherService() {
            super(30L, TimeUnit.SECONDS);
            _lastWeatherUpdate = GameTimeService.getServerTimeInMillis();
            _weatherData = new ArrayList<>();
    
            _weatherData.add(new float[]{
                    0.3f + ThreadLocalRandom.current().nextInt(1, 1000001) / 250000000.0f, 		// Rain Rate
                    0.035f + ThreadLocalRandom.current().nextInt(1, 101) / 100000.0f, 				// Cloud Rate
                    ThreadLocalRandom.current().nextInt(0, 30) / 100f 	                            // Rain Amount
            });
        }
    
    /* at line 78 replace public void onLogin() method */
    
        public void onLogin(final Player player) {
            if(EtcOptionConfig.ENABLE_WEATHER_ON_START) {
                player.sendPacketNoFlush(new SMInitializeRegionWeatherData());
                final ListSplitter<float[]> splitter = new ListSplitter<>(_weatherData, SMInitializeWeatherData.MAXIMUM);
                while (splitter.hasNext())
                    player.sendPacketNoFlush(new SMInitializeWeatherData(this._lastWeatherUpdate, splitter.getNext()));
                player.sendPacketNoFlush(new SMChangeWeathers(0L, 0L));
                player.sendPacketNoFlush(new SMUpdateWeatherManager());
    
                final SMUpdateWeatherManager packet = new SMUpdateWeatherManager();
                player.sendPacket(packet);
                log.info("Weather Service enabled for player " + player.getName());
            }
        }
    etcoption.properties:
    Code:
    # add entry
    
    # Should weather be enabled by default for all players?
    # Default: true
    EnableWeatherOnStart = true
    And the last thing - since people were asking, you can download a complied gameserver.jar with all mods implemented from here:
    https://drive.google.com/uc?export=d...YFCdVgh5r-hYCx
    Mandatory disclaimer - you're downloading a file from random dude over the internet. It can contain viruses, malware, backdoors, warez and nude pics of your mum ;) I removed all older links, too. Just to avoid confusion.

    You need to add all entries to .properties files on your own, though. Have fun :D
    If you just want particular .class file extract it from the .jar archive.

    That's it for now.
    Cheers!

  11. #11
    Account Upgraded | Title Enabled! cintapw is online now
    MemberRank
    Apr 2011 Join Date
    279Posts

    Re: [RELEASE] Quality of life gameserver mods

    thank you sir, you are awesome!

  12. #12
    Proficient Member sabracx is offline
    MemberRank
    Aug 2014 Join Date
    Santo Domingo,Location
    161Posts

    Re: [RELEASE] Quality of life gameserver mods

    Quote Originally Posted by feanturi View Post
    Below you will find an expanded attack multiplier mod along with some new weather system configuration.

    7. Attack damage multiplier (v.2)
    Let’s you modify the damage you do to monsters and other player and how much will monsters do to you. This adds a multiplier that influences the (more-or-less) final damage number that is later passed to the target to lower their health. I added it to tweak the combat into more hard-core PvE experience and use it with re-spawn delay described above.

    Implementation:

    BattleOptionConfig.java:
    Code:
    /* add entries */
    
        @ConfigComments(comment = {"Final multiplier for damage done by monster to players", "Default: 1.0"})
        @ConfigProperty(name = "AttackDamageMultiMonsterToPlayer", value = "1.0")
        public static float ATTACK_DAMAGE_MULTI_MONSTER_TO_PLAYER;
    
        @ConfigComments(comment = {"Final multiplier for damage done by player to monsters and other players", "Default: 1.0"})
        @ConfigProperty(name = "AttackDamageMultiPlayerToMonster", value = "1.0")
        public static float ATTACK_DAMAGE_MULTI_PLAYER_TO_MONSTER;
    
        @ConfigComments(comment = {"Final multiplier for damage done by player to players", "Default: 1.0"})
        @ConfigProperty(name = "AttackDamageMultiPlayerToPlayer", value = "1.0")
        public static float ATTACK_DAMAGE_MULTI_PLAYER_TO_PLAYER;
    AttackResult.java (line 567):
    Code:
    /* insert Final multiplier assignment section between Blocks Calculation and Health updates. For clarity, both section included in the snippet */
    
            //////////////////////////////// Blocks Calculation
            if (isFrontSideAttack && target.getActionStorage().getActionChartActionT().getGuardType().isDefence()) {
                // If update is success, then deflect the damage.
                if (target.getGameStats().getStunGauge().updateStunGauge(-dmg)) {
                    dmgType = EDmgType.Block;
                    dmg = 1;
                }
            }
    
            //////////////////////////////// Final multiplier assignment
            if(isAttackerPlayerOrSummon()){ // player attacks...
                if(target.isPlayer()) { // ...another player
                    dmg = dmg * BattleOptionConfig.ATTACK_DAMAGE_MULTI_PLAYER_TO_PLAYER;
                }else { // ... a monster
                    dmg = dmg * BattleOptionConfig.ATTACK_DAMAGE_MULTI_PLAYER_TO_MONSTER;
                }
            }else{ // monster vs player
                dmg = dmg * BattleOptionConfig.ATTACK_DAMAGE_MULTI_MONSTER_TO_PLAYER;
            }
    
            //////////////////////////////// Health updates
            if (!Double.isNaN(dmg) && !Double.isInfinite(dmg)) {
                if (dmg > 0)
                    target.getGameStats().getHp().updateHp(-dmg, attacker, true);
            } else {
                dmg = 0;
                dmgType = EDmgType.Evasion;
                return true;
            }
    battleoption.properties:
    Code:
    # add entries
    
    # Final multiplier for damage done by monster to players
    # Default: 1.0
    AttackDamageMultiMonsterToPlayer = 2.0
    
    # Final multiplier for damage done by player to monsters and other players
    # Default: 1.0
    AttackDamageMultiPlayerToMonster = 0.1
    
    # Final multiplier for damage done by player to players
    # Default: 1.0
    AttackDamageMultiPlayerToPlayer = 1.0
    8. Enable Weather Service by default
    If you're sick of typing /weather every time you log in... ;)
    Be warned - this is not a fix for any problems weather service may have. There are reports about it being a serious drain on resources for some people, so use that on your own discretion.

    Implementation:

    EtcOptionConfig.java:
    Code:
    /* add entry */
    
        @ConfigComments(comment = {"Should weather be enabled by default for all players?", "Default: true"})
        @ConfigProperty(name = "EnableWeatherOnStart", value = "true")
        public static boolean ENABLE_WEATHER_ON_START;
    WeatherService.java (lines 43 and 78):
    Code:
    /* at line 43 replace private WeatherService() constructor */
    
        private WeatherService() {
            super(30L, TimeUnit.SECONDS);
            _lastWeatherUpdate = GameTimeService.getServerTimeInMillis();
            _weatherData = new ArrayList<>();
    
            _weatherData.add(new float[]{
                    0.3f + ThreadLocalRandom.current().nextInt(1, 1000001) / 250000000.0f,         // Rain Rate
                    0.035f + ThreadLocalRandom.current().nextInt(1, 101) / 100000.0f,                 // Cloud Rate
                    ThreadLocalRandom.current().nextInt(0, 30) / 100f                                 // Rain Amount
            });
        }
    
    /* at line 78 replace public void onLogin() method */
    
        public void onLogin(final Player player) {
            if(EtcOptionConfig.ENABLE_WEATHER_ON_START) {
                player.sendPacketNoFlush(new SMInitializeRegionWeatherData());
                final ListSplitter<float[]> splitter = new ListSplitter<>(_weatherData, SMInitializeWeatherData.MAXIMUM);
                while (splitter.hasNext())
                    player.sendPacketNoFlush(new SMInitializeWeatherData(this._lastWeatherUpdate, splitter.getNext()));
                player.sendPacketNoFlush(new SMChangeWeathers(0L, 0L));
                player.sendPacketNoFlush(new SMUpdateWeatherManager());
    
                final SMUpdateWeatherManager packet = new SMUpdateWeatherManager();
                player.sendPacket(packet);
                log.info("Weather Service enabled for player " + player.getName());
            }
        }
    etcoption.properties:
    Code:
    # add entry
    
    # Should weather be enabled by default for all players?
    # Default: true
    EnableWeatherOnStart = true
    And the last thing - since people were asking, you can download a complied gameserver.jar with all mods implemented from here:
    https://drive.google.com/uc?export=d...YFCdVgh5r-hYCx
    Mandatory disclaimer - you're downloading a file from random dude over the internet. It can contain viruses, malware, backdoors, warez and nude pics of your mum ;) I removed all older links, too. Just to avoid confusion.

    You need to add all entries to .properties files on your own, though. Have fun :D
    If you just want particular .class file extract it from the .jar archive.

    That's it for now.
    Cheers!
    with your files the striker quest has problems with aw, thanks for the file ^^

  13. #13
    Enthusiast feanturi is offline
    MemberRank
    Mar 2018 Join Date
    PolandLocation
    28Posts

    Re: [RELEASE] Quality of life gameserver mods

    Quote Originally Posted by sabracx View Post
    with your files the striker quest has problems with aw, thanks for the file ^^
    Could you explain what the problems are? Maybe I'll be able to fix it.

  14. #14
    Proficient Member sabracx is offline
    MemberRank
    Aug 2014 Join Date
    Santo Domingo,Location
    161Posts

    Re: [RELEASE] Quality of life gameserver mods

    Quote Originally Posted by feanturi View Post
    Could you explain what the problems are? Maybe I'll be able to fix it.
    when you use the scroll of the quest the monster does not go through the whole invocation process but nothing comes out and even though the changes do not leave the monks with the striker. same thanks good contribution

  15. #15
    Enthusiast feanturi is offline
    MemberRank
    Mar 2018 Join Date
    PolandLocation
    28Posts

    Re: [RELEASE] Quality of life gameserver mods

    Quote Originally Posted by sabracx View Post
    when you use the scroll of the quest the monster does not go through the whole invocation process but nothing comes out and even though the changes do not leave the monks with the striker. same thanks good contribution
    Do you mean summon scrolls that you get as part of main quest? In those summoning animation is bugged, true. Boss just pop into existence while camera stays locked as if proper animation was playing. This keeps you locked in place, giving boss few free hits on you. Boss exit animation plays correctly, though, and since from my experience the fight itself plays out correctly, I don't think this animation bug is much of an urgent issue.



Page 1 of 4 1234 LastLast

Advertisement