Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

[RELEASE] Quality of life gameserver mods

Newbie Spellweaver
Joined
Mar 19, 2018
Messages
28
Reaction score
24
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 /*

 @[I][B][URL="http://forum.ragezone.com/members/2000161204.html"]comman[/URL][/B][/I]dHandlerMethod
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 */

 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Adrenaline super skill progress multiplier", "Default: 1"})
 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(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 */

 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Final multiplier for damage done by monster to players", "Default: 1.0"})
 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(name = "AttackDamageMultiMonsterToPlayer", value = "1.0")
public static float ATTACK_DAMAGE_MULTI_MONSTER_TO_PLAYER;

 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Final multiplier for damage done by player to monsters and other players", "Default: 1.0"})
 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(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 */

 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Additional time in MILISECONDS that's added to all monsters re-spawn time.", "Default: 0"})
 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(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 */

 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Base WP regen per tick", "Default: 1.0"})
 @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(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:
Newbie Spellweaver
Joined
May 4, 2016
Messages
19
Reaction score
0
Hi Men ! thanx for sharing this awesome tweaks :)
 
Junior Spellweaver
Joined
Dec 21, 2016
Messages
142
Reaction score
248
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?
 
Newbie Spellweaver
Joined
May 4, 2016
Messages
19
Reaction score
0
Try to find some useless npc ids like villagers and traveling npcs who just stays in roads in spawn data XMLs and just delete
 
Newbie Spellweaver
Joined
Mar 19, 2018
Messages
28
Reaction score
24
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:
Newbie Spellweaver
Joined
Mar 19, 2018
Messages
28
Reaction score
24
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 */

    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"General drop count random multiplier range", "Default: 5, 15"})
    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(name = "rate.general.drop.multiplier", value = "5, 15")
    public static int[] GENERAL_DROP_MULTIPLIER;

    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Monster drop count random multiplier range", "Default: 5, 15"})
    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(name = "rate.monster.drop.multiplier", value = "5, 15")
    public static int[] MONSTER_DROP_MULTIPLIER;

    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Collection drop count random multiplayer range", "Default: 5, 15"})
    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(name = "rate.collection.drop.multiplier", value = "5, 15")
    public static int[] COLLECTION_DROP_MULTIPLIER;

    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Fishing drop count random multiplayer range", "Default: 5, 15"})
    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(name = "rate.fishing.drop.multiplier", value = "5, 15")
    public static int[] FISHING_DROP_MULTIPLIER;

    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Fishing drop count random multiplayer range", "Default: 5, 15"})
    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(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:
Experienced Elementalist
Joined
Apr 18, 2011
Messages
280
Reaction score
11
for attack multiplier, can you make a config separately for attack player to player and player to monster?
 
Newbie Spellweaver
Joined
Mar 19, 2018
Messages
28
Reaction score
24
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 */

    [USER=1333384110]Config[/USER]Comments(comment = {"Final multiplier for damage done by monster to players", "Default: 1.0"})
    [USER=1333384110]Config[/USER]Property(name = "AttackDamageMultiMonsterToPlayer", value = "1.0")
    public static float ATTACK_DAMAGE_MULTI_MONSTER_TO_PLAYER;

    [USER=1333384110]Config[/USER]Comments(comment = {"Final multiplier for damage done by player to monsters and other players", "Default: 1.0"})
    [USER=1333384110]Config[/USER]Property(name = "AttackDamageMultiPlayerToMonster", value = "1.0")
    public static float ATTACK_DAMAGE_MULTI_PLAYER_TO_MONSTER;

    [USER=1333384110]Config[/USER]Comments(comment = {"Final multiplier for damage done by player to players", "Default: 1.0"})
    [USER=1333384110]Config[/USER]Property(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 */

    [USER=1333384110]Config[/USER]Comments(comment = {"Should weather be enabled by default for all players?", "Default: true"})
    [USER=1333384110]Config[/USER]Property(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:

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!
 
Junior Spellweaver
Joined
Aug 8, 2014
Messages
164
Reaction score
26
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 */

    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Final multiplier for damage done by monster to players", "Default: 1.0"})
    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(name = "AttackDamageMultiMonsterToPlayer", value = "1.0")
    public static float ATTACK_DAMAGE_MULTI_MONSTER_TO_PLAYER;

    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Final multiplier for damage done by player to monsters and other players", "Default: 1.0"})
    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(name = "AttackDamageMultiPlayerToMonster", value = "1.0")
    public static float ATTACK_DAMAGE_MULTI_PLAYER_TO_MONSTER;

    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Final multiplier for damage done by player to players", "Default: 1.0"})
    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(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 */

    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Comments(comment = {"Should weather be enabled by default for all players?", "Default: true"})
    @[I][B][URL="http://forum.ragezone.com/members/1333384110.html"]Config[/URL][/B][/I]Property(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:

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 ^^
 
Junior Spellweaver
Joined
Aug 8, 2014
Messages
164
Reaction score
26
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
 
Newbie Spellweaver
Joined
Mar 19, 2018
Messages
28
Reaction score
24
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.
 
Newbie Spellweaver
Joined
May 4, 2016
Messages
19
Reaction score
0
gameserver.jar of the source updated by the DNC with all the mods applied, good profit...
Link updated with gameserver.jar fixed.
Link:

Thanks for ur help ! :)
 
Newbie Spellweaver
Joined
Mar 19, 2018
Messages
28
Reaction score
24
Update Full.
Files that I am currently using, all mods quoted here already implemented in the source updated by DNC ... To use these files just place the folder database. PS. does not have geodata. Anyone who continues to update these files, please post the updates here.
Link:

Does this uses same gameserver.jar that you posted before?
 
Newbie Spellweaver
Joined
Mar 28, 2018
Messages
29
Reaction score
2
Any way to make it not stack stuff like seeds when the drop multiplier triggers?


EDIT:After considering it more, I do like how it stacks them, is it safe to do so?
 
Last edited:
Back
Top