Keenan

[FINAL] Stat Gain Mod

Recommended Posts

This is a quick and dirty stat gain mod. It's designed to try and keep overall stats in line with the lower skills, and it pulls from the SkillGainMod you set on your server. This may not be the best fix, but I found it to be fairly even, even at 10x skill gain. 

 

Before:

[22:22:57] Miscellaneous items increased by 0.171 to 2.182
[22:22:57] Shovel increased by 0.297 to 3.515
[22:22:57] Body increased by 0.000032 to 20.000175
[22:22:57] Body strength increased by 0.000383 to 20.00161
[22:22:57] Body increased by 0.000032 to 20.000208
[22:22:57] Body stamina increased by 0.000383 to 20.00199
[22:22:57] Digging increased by 0.504 to 4.852

 
After:

[22:29:55] Mind logic increased by 0.00271 to 25.0041
[22:29:55] Miscellaneous items increased by 0.158 to 2.340
[22:29:55] Shovel increased by 0.271 to 3.785
[22:29:55] Body increased by 0.000319 to 20.00053
[22:29:55] Body stamina increased by 0.00383 to 20.0058
[22:29:55] Digging increased by 0.446 to 5.298

 

Class file can be found here: https://www.dropbox.com/s/k7665zxw8h2o8dj/skills.zip?dl=0

 

  1.  
  2. Extract the two class files from that zip.
  3.  
  4. As with other mods, you need to open your server.jar with a utility such as 7-zip. 
  5.  
  6. Drag those two files into com / wurmonline / server / skills
  7.  
  8. Close and enjoy
  9.  

Disclaimer: I offer no support for this mod. It's fairly simple, but I'm not responsible if you break things. 

 

The meat and potatoes of this mod, if you'd just like to modify the code is below. I made a new double "newSkillDivider" and modify it based on the skill gain rate mod. What this is essentially doing is lowering the penalty imposed on statistic gains. The skill gain rate was always applied, it's just that these stats have their gain rate divided by huge amounts. 

                if (useNewSystem) {                    double maxSkillRate = 40.0;                    double rateMod = 1.0;                    double newSkillDivider = skillDivider;                    final short sType = SkillSystem.getTypeFor(this.number);                    if (sType == 1 || sType == 0) {                        maxSkillRate = 60.0;                        rateMod = 1.2;                        newSkillDivider = skillDivider / Servers.localServer.getSkillGainRate();                    }                    final double skillRate = Math.min(maxSkillRate, newSkillDivider * (1.0 + this.knowledge / (100.0 - 90.0 * (this.knowledge / 110.0))) * rateMod);                    this.knowledge = Math.max(1.0, this.knowledge + Math.min(1.0, advanceMultiplicator * this.knowledge / skillRate));                }

// // Decompiled by Procyon v0.5.30// package com.wurmonline.server.skills;import com.wurmonline.server.players.Titles;import javax.annotation.Nullable;import com.wurmonline.server.players.Player;import com.wurmonline.server.Players;import com.wurmonline.server.items.Item;import com.wurmonline.server.creatures.Creature;import com.wurmonline.server.creatures.NoSuchCreatureException;import com.wurmonline.server.NoSuchPlayerException;import com.wurmonline.server.Server;import java.util.Iterator;import java.util.HashSet;import java.io.IOException;import com.wurmonline.shared.exceptions.WurmServerException;import java.util.logging.Level;import com.wurmonline.server.WurmId;import com.wurmonline.server.Servers;import java.util.Random;import com.wurmonline.server.modifiers.DoubleValueModifier;import java.util.Set;import java.util.logging.Logger;import com.wurmonline.server.TimeConstants;import com.wurmonline.server.CounterTypes;import com.wurmonline.server.MiscConstants;public abstract class Skill implements MiscConstants, CounterTypes, TimeConstants, Comparable<Skill>{    public long lastUsed;    public double knowledge;    private static final double regainMultiplicator = 3.0;    public double minimum;    boolean joat;    int number;    private static final double maxBonus = 70.0;    Skills parent;    private static Logger logger;    public int affinity;    private static final float affinityMultiplier = 0.1f;    public long id;    private Set<DoubleValueModifier> modifiers;    private byte saveCounter;    private static Random random;    private static final byte[][] chances;    private static final double skillMod;    private static final double maxSkillGain = 1.0;    private boolean basicPersonal;    private boolean noCurve;    protected static final boolean isChallenge = true;        static {        Skill.logger = Logger.getLogger(Skill.class.getName());        Skill.random = new Random();        chances = calculateChances();        skillMod = (Servers.localServer.EPIC ? 3.0f : 1.5f);    }        Skill(final int aNumber, final double startValue, final Skills aParent) {        this.knowledge = 1.0;        this.joat = false;        this.affinity = 0;        this.id = -10L;        this.modifiers = null;        this.saveCounter = 0;        this.basicPersonal = false;        this.noCurve = false;        this.number = aNumber;        this.knowledge = Math.max(1.0, startValue);        this.minimum = startValue;        this.parent = aParent;        if (aParent.isPersonal()) {            if (WurmId.getType(aParent.getId()) == 0) {                this.id = WurmId.getNextPlayerSkillId();                if (SkillSystem.getTypeFor(aNumber) == 0 || SkillSystem.getTypeFor(this.number) == 1) {                    this.knowledge = Math.max(1.0, startValue);                    this.minimum = this.knowledge;                    this.basicPersonal = true;                    this.noCurve = true;                }            }            else {                this.id = WurmId.getNextCreatureId();            }            if (this.number == 10076) {                this.noCurve = true;            }        }    }        Skill(final long _id, final int _number, final double _knowledge, final double _minimum, final long _lastused) {        this.knowledge = 1.0;        this.joat = false;        this.affinity = 0;        this.id = -10L;        this.modifiers = null;        this.saveCounter = 0;        this.basicPersonal = false;        this.noCurve = false;        this.id = _id;        this.number = _number;        this.knowledge = _knowledge;        this.minimum = _minimum;        this.lastUsed = _lastused;    }        public boolean isDirty() {        return this.saveCounter > 0;    }        Skill(final long _id, final Skills _parent, final int _number, final double _knowledge, final double _minimum, final long _lastused) {        this.knowledge = 1.0;        this.joat = false;        this.affinity = 0;        this.id = -10L;        this.modifiers = null;        this.saveCounter = 0;        this.basicPersonal = false;        this.noCurve = false;        this.id = _id;        this.parent = _parent;        this.number = _number;        this.knowledge = _knowledge;        this.minimum = _minimum;        this.lastUsed = _lastused;        if (WurmId.getType(this.parent.getId()) == 0) {            if (SkillSystem.getTypeFor(this.number) == 0 || SkillSystem.getTypeFor(this.number) == 1) {                this.basicPersonal = true;                this.noCurve = true;            }            if (this.number == 10076) {                this.noCurve = true;            }        }    }        @Override    public int compareTo(final Skill otherSkill) {        return this.getName().compareTo(otherSkill.getName());    }        private static final byte[][] calculateChances() {        Skill.logger.log(Level.INFO, "Calculating skill chances...");        final long start = System.nanoTime();        byte[][] toReturn = null;        try {            toReturn = DbSkill.loadSkillChances();            if (toReturn == null) {                throw new WurmServerException("Load failed. Creating chances.");            }            Skill.logger.log(Level.INFO, "Loaded skill chances succeeded.");        }        catch (Exception ex) {            toReturn = new byte[101][101];            for (int x = 0; x < 101; ++x) {                for (int y = 0; y < 101; ++y) {                    if (x == 0) {                        toReturn[x][y] = 0;                    }                    else if (y == 0) {                        toReturn[x][y] = 99;                    }                    else {                        float succeed = 0.0f;                        for (int t = 0; t < 1000; ++t) {                            if (rollGaussian(x, y, 0L, "test") > 0.0f) {                                ++succeed;                            }                        }                        succeed /= 10.0f;                        toReturn[x][y] = (byte)succeed;                    }                }            }            final Thread t2 = new Thread() {                @Override                public void run() {                    Skill.logger.log(Level.INFO, "Starting to slowly build up statistics.");                    final byte[][] toSave = new byte[101][101];                    for (int x = 0; x < 101; ++x) {                        for (int y = 0; y < 101; ++y) {                            if (x == 0) {                                toSave[x][y] = 0;                            }                            else if (y == 0) {                                toSave[x][y] = 99;                            }                            else {                                float succeed = 0.0f;                                for (int t2 = 0; t2 < 30000; ++t2) {                                    if (Skill.rollGaussian(x, y, 0L, "test") > 0.0f) {                                        ++succeed;                                    }                                }                                succeed /= 300.0f;                                toSave[x][y] = (byte)succeed;                            }                        }                    }                    try {                        Skill.logger.log(Level.INFO, "Saving skill chances.");                        DbSkill.saveSkillChances(toSave);                    }                    catch (Exception ex2) {                        Skill.logger.log(Level.WARNING, "Saving failed.", ex2);                    }                }            };            t2.setPriority(3);            t2.start();            return toReturn;        }        finally {            final float lElapsedTime = (System.nanoTime() - start) / 1000000.0f;            Skill.logger.info("Done. Loading/Calculating skill chances from the database took " + lElapsedTime + " millis.");        }        final float lElapsedTime = (System.nanoTime() - start) / 1000000.0f;        Skill.logger.info("Done. Loading/Calculating skill chances from the database took " + lElapsedTime + " millis.");        return toReturn;    }        Skill(final long aId, final Skills aParent) throws IOException {        this.knowledge = 1.0;        this.joat = false;        this.affinity = 0;        this.id = -10L;        this.modifiers = null;        this.saveCounter = 0;        this.basicPersonal = false;        this.noCurve = false;        this.id = aId;        this.parent = aParent;        this.load();    }        public void addModifier(final DoubleValueModifier modifier) {        if (this.modifiers == null) {            this.modifiers = new HashSet<DoubleValueModifier>();        }        this.modifiers.add(modifier);    }        public void removeModifier(final DoubleValueModifier modifier) {        if (this.modifiers != null) {            this.modifiers.remove(modifier);        }    }        private boolean ignoresEnemy() {        return SkillSystem.ignoresEnemies(this.number);    }        public double getModifierValues() {        double toReturn = 0.0;        if (this.modifiers != null) {            final Iterator<DoubleValueModifier> it = this.modifiers.iterator();            while (it.hasNext()) {                toReturn += it.next().getModifier();            }        }        return toReturn;    }        void setParent(final Skills skills) {        this.parent = skills;    }        public String getName() {        return SkillSystem.getNameFor(this.number);    }        public int getNumber() {        return this.number;    }        public long getId() {        return this.id;    }        public double getKnowledge() {        return this.knowledge;    }        public double getKnowledge(double bonus) {        if (bonus > 70.0) {            bonus = 70.0;        }        double bonusKnowledge = this.knowledge;        if (this.number == 102) {            final long parentId = this.parent.getId();            if (parentId != -10L) {                try {                    final Creature holder = Server.getInstance().getCreature(parentId);                    final float hs = holder.getBonusForSpellEffect((byte)40);                    if (hs > 0.0f) {                        bonusKnowledge += this.knowledge * hs / 100.0;                    }                    else {                        final float x = holder.getBonusForSpellEffect((byte)25);                        if (x > 0.0f && this.knowledge < 40.0) {                            final double diff = 40.0 - this.knowledge;                            bonusKnowledge += diff * x / 100.0;                        }                    }                    final float ws = holder.getBonusForSpellEffect((byte)41);                    if (ws > 0.0f) {                        bonusKnowledge *= 0.800000011920929;                    }                }                catch (NoSuchPlayerException ex) {}                catch (NoSuchCreatureException ex2) {}            }        }        if (bonus != 0.0) {            final double linearMax = (100.0 + bonusKnowledge) / 2.0;            final double diffToMaxChange = Math.min(bonusKnowledge, linearMax - bonusKnowledge);            final double newBon = diffToMaxChange * bonus / 100.0;            bonusKnowledge += newBon;        }        bonusKnowledge = Math.max(1.0, bonusKnowledge * (1.0 + this.getModifierValues()));        if (!this.parent.paying) {            return Math.min(bonusKnowledge, 20.0);        }        if (this.noCurve) {            return bonusKnowledge;        }        return Server.getModifiedPercentageEffect(bonusKnowledge);    }        public double getKnowledge(final Item item, double bonus) {        if (item == null || item.isBodyPart()) {            return this.getKnowledge(bonus);        }        if (this.number == 1023) {            try {                final int primweaponskill = item.getPrimarySkill();                Skill pw = null;                try {                    pw = this.parent.getSkill(primweaponskill);                    bonus += pw.getKnowledge(item, 0.0);                }                catch (NoSuchSkillException nss) {                    pw = this.parent.learn(primweaponskill, 1.0f);                    bonus += pw.getKnowledge(item, 0.0);                }            }            catch (NoSuchSkillException ex) {}        }        double bonusKnowledge = 0.0;        final double ql = item.getCurrentQualityLevel();        if (bonus > 70.0) {            bonus = 70.0;        }        if (ql <= this.knowledge) {            bonusKnowledge = (this.knowledge + ql) / 2.0;        }        else {            final double diff = ql - this.knowledge;            bonusKnowledge = this.knowledge + this.knowledge * diff / 100.0;        }        if (this.number == 102) {            final long parentId = this.parent.getId();            if (parentId != -10L) {                try {                    final Creature holder = Server.getInstance().getCreature(parentId);                    final float hs = holder.getBonusForSpellEffect((byte)40);                    if (hs > 0.0f) {                        bonusKnowledge += this.knowledge * hs / 100.0;                    }                    else {                        final float x = holder.getBonusForSpellEffect((byte)25);                        if (x > 0.0f && this.knowledge < 40.0) {                            final double diff2 = 40.0 - this.knowledge;                            bonusKnowledge += diff2 * x / 100.0;                        }                    }                    final float ws = holder.getBonusForSpellEffect((byte)41);                    if (ws > 0.0f) {                        bonusKnowledge *= 0.800000011920929;                    }                }                catch (NoSuchPlayerException nsp) {                    Skill.logger.log(Level.WARNING, nsp.getMessage(), (Throwable)nsp);                }                catch (NoSuchCreatureException ex2) {}            }        }        if (bonus != 0.0) {            final double linearMax = (100.0 + bonusKnowledge) / 2.0;            final double diffToMaxChange = Math.min(bonusKnowledge, linearMax - bonusKnowledge);            final double newBon = diffToMaxChange * bonus / 100.0;            bonusKnowledge += newBon;        }        bonusKnowledge = Math.max(1.0, bonusKnowledge * (1.0 + this.getModifierValues()));        if (!this.parent.paying) {            return Math.min(bonusKnowledge, 20.0);        }        if (this.basicPersonal) {            return bonusKnowledge;        }        return Server.getModifiedPercentageEffect(bonusKnowledge);    }        public final double getRealKnowledge() {        if (this.parent.paying) {            return this.knowledge;        }        return Math.min(this.knowledge, 20.0);    }        public void setKnowledge(final double aKnowledge, final boolean load) {        this.setKnowledge(aKnowledge, load, false);    }        public void setKnowledge(final double aKnowledge, final boolean load, final boolean setMinimum) {        if (aKnowledge < 100.0) {            this.knowledge = Math.max(Math.min(aKnowledge, 100.0), 1.0);            this.checkTitleChange(aKnowledge, aKnowledge);            if (!load) {                if (setMinimum) {                    this.minimum = this.knowledge;                }                try {                    this.save();                }                catch (IOException iox) {                    Skill.logger.log(Level.INFO, "Failed to save skill " + this.id, iox);                }                final long parentId = this.parent.getId();                if (parentId != -10L && WurmId.getType(parentId) == 0) {                    try {                        final Player holder = Players.getInstance().getPlayer(parentId);                        double bonusKnowledge = this.knowledge;                        if (this.number == 102) {                            final float hs = holder.getBonusForSpellEffect((byte)40);                            if (hs > 0.0f) {                                bonusKnowledge = this.knowledge + this.knowledge * hs / 100.0;                            }                            else {                                final float x = holder.getBonusForSpellEffect((byte)25);                                if (x > 0.0f && this.knowledge < 40.0) {                                    final double diff = 40.0 - this.knowledge;                                    bonusKnowledge = this.knowledge + diff * x / 100.0;                                }                            }                            final float ws = holder.getBonusForSpellEffect((byte)41);                            if (ws > 0.0f) {                                bonusKnowledge *= 0.800000011920929;                            }                        }                        if (!this.parent.paying) {                            bonusKnowledge = Math.min(20.0, bonusKnowledge);                        }                        holder.getCommunicator().sendUpdateSkill(this.number, (float)bonusKnowledge, this.isTemporary() ? 0 : this.affinity);                    }                    catch (NoSuchPlayerException nsp) {                        Skill.logger.log(Level.WARNING, nsp.getMessage(), (Throwable)nsp);                    }                }            }        }    }        public double getMinimumValue() {        return this.minimum;    }        public int[] getDependencies() {        return SkillSystem.getDependenciesFor(this.number);    }        public int[] getUniqueDependencies() {        final int[] fDeps = this.getDependencies();        final Set<Integer> lst = new HashSet<Integer>();        for (int i = 0; i < fDeps.length; ++i) {            final Integer val = fDeps[i];            if (!lst.contains(val)) {                lst.add(val);            }        }        final int[] deps = new int[lst.size()];        int ind = 0;        for (final Integer j : lst) {            deps[ind] = j;            ++ind;        }        return deps;    }        public double getDifficulty(final boolean checkPriest) {        return SkillSystem.getDifficultyFor(this.number, checkPriest);    }        public short getType() {        return SkillSystem.getTypeFor(this.number);    }        public double skillCheck(final double check, final double bonus, final boolean test, final float times, final boolean useNewSystem, final double skillDivider) {        return this.skillCheck(check, bonus, test, times, useNewSystem, skillDivider, null, null);    }        public double skillCheck(final double check, final double bonus, final boolean test, final float times) {        return this.skillCheck(check, bonus, test, 10.0f, true, 2.0);    }        public double skillCheck(final double check, final double bonus, final boolean test, final float times, @Nullable final Creature skillowner, @Nullable final Creature opponent) {        return this.skillCheck(check, bonus, test, 10.0f, true, 2.0, skillowner, opponent);    }        public double skillCheck(final double check, final double bonus, final boolean test, final float times, final boolean useNewSystem, final double skillDivider, @Nullable final Creature skillowner, @Nullable final Creature opponent) {        if (skillowner == null || opponent == null || this.number == 10055 || this.number != 10053) {}        this.touch();        final double power = this.checkAdvance(check, null, bonus, test, times, useNewSystem, skillDivider);        if (WurmId.getType(this.parent.getId()) == 0) {            try {                this.save();            }            catch (IOException ex) {}        }        return power;    }        public double skillCheck(final double check, final Item item, final double bonus, final boolean test, final float times, @Nullable final Creature skillowner, @Nullable final Creature opponent) {        return this.skillCheck(check, item, bonus, test, 10.0f, true, 2.0, skillowner, opponent);    }        public double skillCheck(final double check, final Item item, final double bonus, final boolean test, final float times, final boolean useNewSystem, final double skillDivider, @Nullable final Creature skillowner, @Nullable final Creature opponent) {        if (skillowner != null) {}        this.touch();        final double power = this.checkAdvance(check, item, bonus, test, times, useNewSystem, skillDivider);        if (WurmId.getType(this.parent.getId()) == 0) {            try {                this.save();            }            catch (IOException ex) {}        }        return power;    }        public double skillCheck(final double check, final Item item, final double bonus, final boolean test, final float times, final boolean useNewSystem, final double skillDivider) {        return this.skillCheck(check, item, bonus, test, times, useNewSystem, skillDivider, null, null);    }        public double skillCheck(final double check, final Item item, final double bonus, final boolean test, final float times) {        return this.skillCheck(check, item, bonus, test, 10.0f, true, 2.0, null, null);    }        public long getDecayTime() {        return SkillSystem.getDecayTimeFor(this.number);    }        public void touch() {        if (SkillSystem.getTickTimeFor(this.getNumber()) <= 0L) {            this.lastUsed = System.currentTimeMillis();        }    }        long getLastUsed() {        return this.lastUsed;    }        boolean mayUpdateTimedSkill() {        return System.currentTimeMillis() - this.lastUsed < SkillSystem.getTickTimeFor(this.getNumber());    }        void checkDecay() {    }        private void decay(final boolean saved) {        float decrease = 0.0f;        if (this.getType() == 1) {            this.alterSkill(-(100.0 - this.knowledge) / (this.getDifficulty(false) * this.knowledge), true, 1.0f);        }        else if (this.getType() == 0) {            decrease = -0.1f;            if (this.affinity > 0) {                decrease = -0.1f + 0.05f * this.affinity;            }            if (saved) {                this.alterSkill(decrease / 2.0f, true, 1.0f);            }            else {                this.alterSkill(decrease, true, 1.0f);            }        }        else {            decrease = -0.25f;            if (this.affinity > 0) {                decrease = -0.25f + 0.025f * this.affinity;            }            if (saved) {                this.alterSkill(decrease / 2.0f, true, 1.0f);            }            else {                this.alterSkill(decrease, true, 1.0f);            }        }    }        public double getParentBonus() {        double bonus = 0.0;        final int[] dep = this.getDependencies();        for (int x = 0; x < dep.length; ++x) {            final short sType = SkillSystem.getTypeFor(dep[x]);            if (sType == 2) {                try {                    final Skill enhancer = this.parent.getSkill(dep[x]);                    final double ebonus = enhancer.getKnowledge(0.0);                    bonus += ebonus;                }                catch (NoSuchSkillException ex) {                    Skill.logger.log(Level.WARNING, "Skill.checkAdvance(): Skillsystem bad. Skill '" + this.getName() + "' has no enhance parent with number " + dep[x] + ". Learning!", (Throwable)ex);                    this.parent.learn(dep[x], 1.0f);                }            }        }        return bonus;    }        public double getChance(double check, @Nullable final Item item, double bonus) {        bonus += this.getParentBonus();        double skill = this.knowledge;        if (bonus != 0.0 || item != null) {            if (item == null) {                skill = this.getKnowledge(bonus);            }            else {                skill = this.getKnowledge(item, bonus);            }        }        if (skill < 1.0) {            skill = 1.0;        }        if (check < 1.0) {            check = 1.0;        }        return getGaussianChance(skill, check);    }        public static final double getGaussianChance(final double skill, final double difficulty) {        if (skill > 99.0 || difficulty > 99.0) {            return Math.max(0.0, Math.min(100.0, ((skill * skill * skill - difficulty * difficulty * difficulty) / 50000.0 + (skill - difficulty)) / 2.0 + 50.0 + 0.5 * (skill - difficulty)));        }        return Skill.chances[(int)skill][(int)difficulty];    }        public static final float rollGaussian(final float skill, final float difficulty, final long parentId, final String name) {        final float slide = (skill * skill * skill - difficulty * difficulty * difficulty) / 50000.0f + (skill - difficulty);        final float w = 30.0f - Math.abs(skill - difficulty) / 4.0f;        int attempts = 0;        float result = 0.0f;        do {            result = (float)Skill.random.nextGaussian() * (w + Math.abs(slide) / 6.0f) + slide;            final float rejectCutoff = (float)Skill.random.nextGaussian() * (w - Math.abs(slide) / 6.0f) + slide;            if (slide > 0.0f) {                if (result > rejectCutoff + Math.max(100.0f - slide, 0.0f)) {                    result = -1000.0f;                }            }            else if (result < rejectCutoff - Math.max(100.0f + slide, 0.0f)) {                result = -1000.0f;            }            if (++attempts == 100) {                if (result > 100.0f) {                    return 90.0f + Server.rand.nextFloat() * 5.0f;                }                if (result < -100.0f) {                    return -90.0f - Server.rand.nextFloat() * 5.0f;                }                continue;            }        } while (result < -100.0f || result > 100.0f);        return result;    }        private double checkAdvance(double check, @Nullable final Item item, double bonus, boolean dryRun, final float times, final boolean useNewSystem, final double skillDivider) {        if (!dryRun) {            dryRun = this.mayUpdateTimedSkill();        }        check = Math.max(1.0, check);        final short skillType = SkillSystem.getTypeFor(this.number);        final int[] dep = this.getUniqueDependencies();        for (int x = 0; x < dep.length; ++x) {            final short sType = SkillSystem.getTypeFor(dep[x]);            if (sType == 2) {                try {                    final Skill enhancer = this.parent.getSkill(dep[x]);                    final double ebonus = Math.max(0.0, enhancer.skillCheck(check, 0.0, dryRun, times, useNewSystem, skillDivider) / 10.0);                    bonus += ebonus;                }                catch (NoSuchSkillException ex) {                    Creature cret = null;                    try {                        cret = Server.getInstance().getCreature(this.parent.getId());                    }                    catch (NoSuchCreatureException ex2) {}                    catch (NoSuchPlayerException ex3) {}                    String name = "Unknown creature";                    if (cret != null) {                        name = cret.getName();                    }                    Skill.logger.log(Level.WARNING, String.valueOf(name) + " - Skill.checkAdvance(): Skillsystem bad. Skill '" + this.getName() + "' has no enhance parent with number " + dep[x], (Throwable)ex);                    this.parent.learn(dep[x], 1.0f);                }            }            else {                try {                    final Skill par = this.parent.getSkill(dep[x]);                    if (par.getNumber() != 1023) {                        par.skillCheck(check, 0.0, dryRun, times, useNewSystem, skillDivider);                    }                }                catch (NoSuchSkillException ex) {                    Creature cret = null;                    try {                        cret = Server.getInstance().getCreature(this.parent.getId());                    }                    catch (NoSuchCreatureException ex4) {}                    catch (NoSuchPlayerException ex5) {}                    String name = "Unknown creature";                    if (cret != null) {                        name = cret.getName();                    }                    Skill.logger.log(Level.WARNING, String.valueOf(name) + ": Skill.checkAdvance(): Skillsystem bad. Skill '" + this.getName() + "' has no limiting parent with number " + dep[x], (Throwable)ex);                    this.parent.learn(dep[x], 1.0f);                }            }        }        bonus = Math.min(70.0, bonus);        double skill = this.knowledge;        double learnMod = 1.0;        if (item == null) {            skill = this.getKnowledge(bonus);        }        else {            skill = this.getKnowledge(item, bonus);            if (item.getSpellSkillBonus() > 0.0f) {                learnMod += item.getSpellSkillBonus() / 100.0f;            }        }        final double power = rollGaussian((float)skill, (float)check, this.parent.getId(), this.getName());        if (!dryRun) {            if (useNewSystem) {                double divs = skillDivider;                if (skillType == 1) {                    if (this.knowledge > 20.0) {                        divs = 40.0;                    }                    else {                        divs = 20.0;                    }                }                else if (skillType == 0) {                    if (this.knowledge < 31.0) {                        divs = 5.0;                    }                    else {                        divs = 45.0;                    }                }                this.doSkillGainNew(check, power, learnMod, times, divs);            }            else {                this.doSkillGainOld(power, learnMod, times);            }        }        return power;    }        private final void doSkillGainNew(final double check, final double power, final double learnMod, final float times, final double skillDivider) {        double bonus = 1.0;        final double diff = Math.abs(check - this.knowledge);        final short sType = SkillSystem.getTypeFor(this.number);        boolean awardBonus = true;        if (sType == 1 || sType == 0) {            awardBonus = false;        }        if (diff <= 15.0 && awardBonus) {            bonus = 1.0 + 0.10000000149011612 * (diff / 15.0);        }        if (power < 0.0) {            if (this.knowledge < 20.0) {                this.alterSkill((100.0 - this.knowledge) / (this.getDifficulty(this.parent.priest) * this.knowledge * this.knowledge) * learnMod * bonus, false, times, true, skillDivider);            }        }        else {            this.alterSkill((100.0 - this.knowledge) / (this.getDifficulty(this.parent.priest) * this.knowledge * this.knowledge) * learnMod * bonus, false, times, true, skillDivider);        }    }        private final void doSkillGainOld(final double power, final double learnMod, final float times) {        if (power >= 0.0) {            if (this.knowledge < 20.0) {                this.alterSkill((100.0 - this.knowledge) / (this.getDifficulty(this.parent.priest) * this.knowledge * this.knowledge) * learnMod, false, times);            }            else if (power > 0.0 && power < 40.0) {                this.alterSkill((100.0 - this.knowledge) / (this.getDifficulty(this.parent.priest) * this.knowledge * this.knowledge) * learnMod, false, times);            }            else if (this.number == 10055 || this.number == 10053 || this.number == 10054) {                Creature cret = null;                try {                    cret = Server.getInstance().getCreature(this.parent.getId());                    if (cret.loggerCreature1 > 0L) {                        Skill.logger.log(Level.INFO, String.valueOf(cret.getName()) + " POWER=" + power);                    }                }                catch (NoSuchCreatureException ex) {}                catch (NoSuchPlayerException ex2) {}            }        }    }        protected void alterSkill(final double advanceMultiplicator, final boolean decay, final float times) {        this.alterSkill(advanceMultiplicator, decay, times, false, 1.0);    }        protected void alterSkill(double advanceMultiplicator, final boolean decay, float times, final boolean useNewSystem, final double skillDivider) {        if (this.parent.hasSkillGain) {            times = Math.min((SkillSystem.getTickTimeFor(this.getNumber()) > 0L) ? 100 : 30, times);            advanceMultiplicator *= times * Servers.localServer.getSkillGainRate();            this.lastUsed = System.currentTimeMillis();            boolean isplayer = false;            final long pid = this.parent.getId();            if (WurmId.getType(pid) == 0) {                isplayer = true;            }            final double oldknowledge = this.knowledge;            if (decay) {                if (isplayer) {                    if (this.knowledge <= 70.0) {                        return;                    }                    double villageMod = 1.0;                    try {                        final Player player = Players.getInstance().getPlayer(pid);                        villageMod = player.getVillageSkillModifier();                    }                    catch (NoSuchPlayerException nsp) {                        Skill.logger.log(Level.WARNING, "Player with id " + this.id + " is decaying skills while not online?", (Throwable)nsp);                    }                    this.knowledge = Math.max(1.0, this.knowledge + advanceMultiplicator * villageMod);                }                else {                    this.knowledge = Math.max(1.0, this.knowledge + advanceMultiplicator);                }            }            else {                advanceMultiplicator *= Skill.skillMod;                if (this.number == 10086 && Servers.localServer.isChallengeOrEpicServer() && !Server.getInstance().isPS()) {                    advanceMultiplicator *= 0.5;                }                if (isplayer) {                    try {                        final Player player2 = Players.getInstance().getPlayer(pid);                        final int currstam = player2.getStatus().getStamina();                        float staminaMod = 1.0f;                        if (currstam <= 400) {                            staminaMod = 0.1f;                        }                        if (player2.getCultist() != null && player2.getCultist().levelElevenSkillgain()) {                            staminaMod *= 1.25f;                        }                        if (player2.getDeity() != null) {                            if (player2.mustChangeTerritory() && !player2.isFighting()) {                                staminaMod = 0.1f;                                if (Server.rand.nextInt(100) == 0) {                                    player2.getCommunicator().sendAlertServerMessage("You sense a lack of energy. Rumours have it that " + player2.getDeity().name + " wants " + player2.getDeity().getHisHerItsString() + " champions to move between kingdoms and seek out the enemy.");                                }                            }                            if (player2.getDeity().learner) {                                if (player2.getFaith() > 20.0f && player2.getFavor() >= 10.0f) {                                    staminaMod += 0.1f;                                }                            }                            else if (player2.getDeity().warrior && player2.getFaith() > 20.0f && player2.getFavor() >= 20.0f && this.isFightingSkill()) {                                staminaMod += 0.25f;                            }                        }                        staminaMod += player2.getStatus().getNutritionlevel() / 10.0f - 0.05f;                        if (player2.isFighting() && currstam <= 400) {                            staminaMod = 0.0f;                        }                        advanceMultiplicator *= staminaMod;                        if (player2.getEnemyPresense() > Player.minEnemyPresence && !this.ignoresEnemy()) {                            advanceMultiplicator *= 0.800000011920929;                        }                        if (this.knowledge < this.minimum || (this.basicPersonal && this.knowledge < 20.0)) {                            advanceMultiplicator *= 3.0;                        }                        if (player2.hasSleepBonus()) {                            advanceMultiplicator *= 2.0;                        }                        advanceMultiplicator *= 1.0f + this.affinity * 0.1f;                        if (player2.getMovementScheme().samePosCounts > 20) {                            advanceMultiplicator = 0.0;                        }                        if (!player2.isPaying() && this.knowledge >= 20.0) {                            advanceMultiplicator = 0.0;                            if (!player2.isPlayerAssistant() && Server.rand.nextInt(500) == 0) {                                player2.getCommunicator().sendNormalServerMessage("You may only gain skill beyond level 20 if you have a premium account.");                            }                        }                        if ((this.number == 10055 || this.number == 10053 || this.number == 10054) && player2.loggerCreature1 > 0L) {                            Skill.logger.log(Level.INFO, String.valueOf(player2.getName()) + " advancing " + Math.min(1.0, advanceMultiplicator * this.knowledge / skillDivider) + "!");                        }                    }                    catch (NoSuchPlayerException nsp2) {                        advanceMultiplicator = 0.0;                        Skill.logger.log(Level.WARNING, "Player with id " + this.id + " is learning skills while not online?", (Throwable)nsp2);                    }                }                if (useNewSystem) {                    double maxSkillRate = 40.0;                    double rateMod = 1.0;                    double newSkillDivider = skillDivider;                    final short sType = SkillSystem.getTypeFor(this.number);                    if (sType == 1 || sType == 0) {                        maxSkillRate = 60.0;                        rateMod = 1.2;                        newSkillDivider = skillDivider / Servers.localServer.getSkillGainRate();                    }                    final double skillRate = Math.min(maxSkillRate, newSkillDivider * (1.0 + this.knowledge / (100.0 - 90.0 * (this.knowledge / 110.0))) * rateMod);                    this.knowledge = Math.max(1.0, this.knowledge + Math.min(1.0, advanceMultiplicator * this.knowledge / skillRate));                }                else {                    this.knowledge = Math.max(1.0, this.knowledge + Math.min(1.0, advanceMultiplicator * this.knowledge));                }                if (this.minimum < this.knowledge) {                    this.minimum = this.knowledge;                }                this.checkTitleChange(oldknowledge, this.knowledge);            }            try {                if ((oldknowledge != this.knowledge && (this.saveCounter == 0 || this.knowledge > 50.0)) || decay) {                    this.saveValue(isplayer);                }                ++this.saveCounter;                if (this.saveCounter == 10) {                    this.saveCounter = 0;                }            }            catch (IOException ex) {                Skill.logger.log(Level.WARNING, "Failed to save skill " + this.getName() + "(" + this.getNumber() + ") for creature " + this.parent.getId(), ex);            }            if (pid != -10L && isplayer) {                try {                    final Player holder = Players.getInstance().getPlayer(pid);                    float weakMod = 1.0f;                    double bonusKnowledge = this.knowledge;                    final float ws = holder.getBonusForSpellEffect((byte)41);                    if (ws > 0.0f) {                        weakMod = 0.8f;                    }                    if (this.number == 102 && this.knowledge < 40.0) {                        final float x = holder.getBonusForSpellEffect((byte)25);                        if (x > 0.0f) {                            final double diff = 40.0 - this.knowledge;                            bonusKnowledge = this.knowledge + diff * x / 100.0;                        }                        else {                            final float hs = holder.getBonusForSpellEffect((byte)40);                            if (hs > 0.0f) {                                bonusKnowledge = this.knowledge + this.knowledge * hs / 100.0;                            }                        }                    }                    else if (this.number == 102) {                        final float hs2 = holder.getBonusForSpellEffect((byte)40);                        if (hs2 > 0.0f) {                            bonusKnowledge = this.knowledge + this.knowledge * hs2 / 100.0;                        }                    }                    bonusKnowledge *= weakMod;                    if (isplayer) {                        final int diff2 = (int)this.knowledge - (int)oldknowledge;                        if (diff2 > 0) {                            holder.achievement(371, diff2);                        }                    }                    if (!this.parent.paying) {                        bonusKnowledge = Math.min(20.0, bonusKnowledge);                    }                    holder.getCommunicator().sendUpdateSkill(this.number, (float)bonusKnowledge, this.isTemporary() ? 0 : this.affinity);                }                catch (NoSuchPlayerException nsp2) {                    Skill.logger.log(Level.WARNING, String.valueOf(pid) + ":" + nsp2.getMessage(), (Throwable)nsp2);                }            }        }    }        public boolean isTemporary() {        return false;    }        public boolean isFightingSkill() {        return SkillSystem.isFightingSkill(this.number);    }        public void checkInitialTitle() {        if (this.knowledge >= 50.0) {            final long pid = this.parent.getId();            if (WurmId.getType(pid) == 0) {                final Titles.Title title = Titles.Title.getTitle(this.number, Titles.TitleType.NORMAL);                if (title != null) {                    try {                        Players.getInstance().getPlayer(pid).addTitle(title);                    }                    catch (NoSuchPlayerException nsp) {                        Skill.logger.log(Level.WARNING, String.valueOf(pid) + ":" + nsp.getMessage(), (Throwable)nsp);                    }                }            }        }        if (this.knowledge >= 70.0) {            final long pid = this.parent.getId();            if (WurmId.getType(pid) == 0) {                final Titles.Title title = Titles.Title.getTitle(this.number, Titles.TitleType.MINOR);                if (title != null) {                    try {                        Players.getInstance().getPlayer(pid).addTitle(title);                    }                    catch (NoSuchPlayerException nsp) {                        Skill.logger.log(Level.WARNING, String.valueOf(pid) + ":" + nsp.getMessage(), (Throwable)nsp);                    }                }            }        }        if (this.knowledge >= 90.0) {            final long pid = this.parent.getId();            if (WurmId.getType(pid) == 0) {                final Titles.Title title = Titles.Title.getTitle(this.number, Titles.TitleType.MASTER);                if (title != null) {                    try {                        Players.getInstance().getPlayer(pid).addTitle(title);                    }                    catch (NoSuchPlayerException nsp) {                        Skill.logger.log(Level.WARNING, String.valueOf(pid) + ":" + nsp.getMessage(), (Throwable)nsp);                    }                }            }        }        if (this.knowledge >= 99.99999615) {            final long pid = this.parent.getId();            if (WurmId.getType(pid) == 0) {                final Titles.Title title = Titles.Title.getTitle(this.number, Servers.localServer.isChallengeOrEpicServer() ? Titles.TitleType.EPIC : Titles.TitleType.LEGENDARY);                if (title != null) {                    try {                        Players.getInstance().getPlayer(pid).addTitle(title);                    }                    catch (NoSuchPlayerException nsp) {                        Skill.logger.log(Level.WARNING, String.valueOf(pid) + ":" + nsp.getMessage(), (Throwable)nsp);                    }                }            }        }    }        void checkTitleChange(final double oldknowledge, final double newknowledge) {        if (oldknowledge < 50.0 && newknowledge >= 50.0) {            final long pid = this.parent.getId();            if (WurmId.getType(pid) == 0) {                final Titles.Title title = Titles.Title.getTitle(this.number, Titles.TitleType.NORMAL);                if (title != null) {                    try {                        Players.getInstance().getPlayer(pid).addTitle(title);                    }                    catch (NoSuchPlayerException nsp) {                        Skill.logger.log(Level.WARNING, String.valueOf(pid) + ":" + nsp.getMessage(), (Throwable)nsp);                    }                }            }        }        if (oldknowledge < 70.0 && newknowledge >= 70.0) {            final long pid = this.parent.getId();            if (WurmId.getType(pid) == 0) {                final Titles.Title title = Titles.Title.getTitle(this.number, Titles.TitleType.MINOR);                if (title != null) {                    try {                        Players.getInstance().getPlayer(pid).addTitle(title);                    }                    catch (NoSuchPlayerException nsp) {                        Skill.logger.log(Level.WARNING, String.valueOf(pid) + ":" + nsp.getMessage(), (Throwable)nsp);                    }                }            }        }        if (oldknowledge < 90.0 && newknowledge >= 90.0) {            final long pid = this.parent.getId();            if (WurmId.getType(pid) == 0) {                final Titles.Title title = Titles.Title.getTitle(this.number, Titles.TitleType.MASTER);                if (title != null) {                    try {                        Players.getInstance().getPlayer(pid).addTitle(title);                    }                    catch (NoSuchPlayerException nsp) {                        Skill.logger.log(Level.WARNING, String.valueOf(pid) + ":" + nsp.getMessage(), (Throwable)nsp);                    }                }            }        }    }        public void setAffinity(final int aff) {        this.affinity = aff;        final long pid = this.parent.getId();        if (WurmId.getType(pid) == 0 && !this.isTemporary()) {            try {                final Player holder = Players.getInstance().getPlayer(pid);                float weakMod = 1.0f;                double bonusKnowledge = this.knowledge;                final float ws = holder.getBonusForSpellEffect((byte)41);                if (ws > 0.0f) {                    weakMod = 0.8f;                }                if (this.number == 102 && this.knowledge < 40.0) {                    final float x = holder.getBonusForSpellEffect((byte)25);                    if (x > 0.0f) {                        final double diff = 40.0 - this.knowledge;                        bonusKnowledge = this.knowledge + diff * x / 100.0;                    }                    else {                        final float hs = holder.getBonusForSpellEffect((byte)40);                        if (hs > 0.0f) {                            bonusKnowledge = this.knowledge + this.knowledge * hs / 100.0;                        }                    }                }                else if (this.number == 102) {                    final float hs2 = holder.getBonusForSpellEffect((byte)40);                    if (hs2 > 0.0f) {                        bonusKnowledge = this.knowledge + this.knowledge * hs2 / 100.0;                    }                }                bonusKnowledge *= weakMod;                if (!this.parent.paying) {                    bonusKnowledge = Math.min(20.0, bonusKnowledge);                }                holder.getCommunicator().sendUpdateSkill(this.number, (float)bonusKnowledge, this.affinity);            }            catch (NoSuchPlayerException nsp) {                Skill.logger.log(Level.WARNING, nsp.getMessage(), (Throwable)nsp);            }        }    }        abstract void save() throws IOException;        abstract void load() throws IOException;        abstract void saveValue(final boolean p0) throws IOException;        public abstract void setJoat(final boolean p0) throws IOException;        public abstract void setNumber(final int p0) throws IOException;} 

Edited by Keenan

Share this post


Link to post
Share on other sites

+1000

Share this post


Link to post
Share on other sites

I've heard reports that this mod isn't working on some servers. 


 


I know I said I offer no support, but if you're having issues - do post. Let me know what your modifier is. This was meant to be a quick and dirty fix until something more solid comes about, but if it needs more polish... :P


Share this post


Link to post
Share on other sites

Can you fix meditation too? As far as i noticed the skillgain seems exactly like in WO even with a 5x gain, plus 3x (because apparently skills under 20 are 3x faster) so i'm supposed to be gaining it 15x faster than WO but that doesn't seem to be the case.


 


Share this post


Link to post
Share on other sites

Can you fix meditation too? As far as i noticed the skillgain seems exactly like in WO even with a 5x gain, plus 3x (because apparently skills under 20 are 3x faster) so i'm supposed to be gaining it 15x faster than WO but that doesn't seem to be the case.

 

It also seems as if fighting, faith, HFC, and animal husbandry are unaffected.

Edited by Huntar

Share this post


Link to post
Share on other sites

low skill modifiers ends up making the skillDivider large.


 


Assuming this sets code the skillDivider, its in checkAdvance() method. skillType 1 is parent characteristics, type 0 are child characteristics.



double divs = skillDivider;
if(skillType == 1) {
if(this.knowledge > 20.0D) {
divs = 40.0D;
} else {
divs = 20.0D;
}
} else if(skillType == 0) {
if(this.knowledge < 31.0D) {
divs = 5.0D;
} else {
divs = 45.0D;
}
}

At first the skillDivider is going to be that that 5. If you got your skill gain bonus set to 1, well 5 /1 is 5. For a skill gain bonus of 10, 5 / 10 is 0.5.


I ended up doing the following. The gain numbers posted in the OP seem good for what I've see in WO. I'd almost say they need to be much higher for a skill modifier of 10X. Given that I play on gain modifier of 1, I just set it to 0.5.



if(var271 == 1 || var271 == 0) {
var25 = 60.0D;
var30 = 1.2D;
skillDivider = 0.5D;
}

Share this post


Link to post
Share on other sites

Like I said, it was quick and dirty. I wanted to tie it to the modifier somehow, but I might use Ago's mod loader and do something better soon.


 


Also I do believe all of those skills mentioned are singled out in alterSkill() - I know meditation is. 


Share this post


Link to post
Share on other sites

Thanks fort making this. I figured something was out of whack when I had many skills up to 40 and beyond but none of my characteristics budged past 20.


Share this post


Link to post
Share on other sites

Is anyone working on a cleaner/better version of this? Also, does this JUST need to go into the server, or does it require installation on the client side as well?


Share this post


Link to post
Share on other sites

Is anyone working on a cleaner/better version of this? Also, does this JUST need to go into the server, or does it require installation on the client side as well?

 

Just the server, and I might work my way back to this soon. Working on a rather big mod though. Post for that soon.

Share this post


Link to post
Share on other sites

So is the body mind and spirit part broke and this fixes it??


Share this post


Link to post
Share on other sites

So is the body mind and spirit part broke and this fixes it??

They're not broke, they're just not affected by the increased skill gain rates proportionally. So you're going to have high end skills and low end characteristics without this mod or something like it.

Share this post


Link to post
Share on other sites

Ok well with this mod body and mind skills are moving much better...

Share this post


Link to post
Share on other sites

Ok well with this mod body and mind skills are moving much better...

Yes, more in-line with the modified skill improvement speeds. I wouldn't be surprised if this mod or some other version of it was included in an official patch.

Share this post


Link to post
Share on other sites

Alrighty! I went ahead and applied the mod to my server... seems to be running just fine so far. :D


Share this post


Link to post
Share on other sites

It also seems as if fighting, faith, HFC, and animal husbandry are unaffected.

So, inexplicably, some arbitrary stats are *completely* off the skill gain curve in the server settings....WTF?!

 

if your server was set to 20x skillgain the characteristics, fighting, faith, hfc, etc...would be set to standard 1.0x WO...are you kidding me?

 

Patch, anyone? Buehler? Buehler?.......Buehler? Ferris Patch Buehler?

Share this post


Link to post
Share on other sites

So, inexplicably, some arbitrary stats are *completely* off the skill gain curve in the server settings....WTF?!

 

if your server was set to 20x skillgain the characteristics, fighting, faith, hfc, etc...would be set to standard 1.0x WO...are you kidding me?

 

Patch, anyone? Buehler? Buehler?.......Buehler? Ferris Patch Buehler?

 

From what I've seen, there are some skills which, like in WO, aren't boosted by a modifier. Think of this like sleep bonus. You're effectively setting a default "sleep bonus" state on your server (though it adds to sleep bonus, not replaces).

 

So yes, there are some skills where it isn't doing anything, but for the most part it *does* modify the skill... just some have hard-coded limits and/or "nerfs" that make it less proportional.

 

This patch doesn't touch the other skills, just the stats. It was a quick hack after taking a few hours to understand how skill gains actually work. ;) Because of how popular of an issue it is, I'm thinking I might come back to this sooner than I thought and put some of those impacted skills as options in the properties file for Ago's mod loader. That way server admins will have more control over how things progress.

 

Right now my focus is completely on the Portals mod though, but after some real life stuff today, I should be pretty close to releasing that (as an alpha) and I can look back at this. (Or someone else can give it a shot. I'm not trying to complete. :P)

Share this post


Link to post
Share on other sites

Hmmm addd this mod to my server and my characteristics are still only going up by like .000006 each time. I'm running .35 skill mod + 2x action timer, so I'm not sure if that matters, but the overall amount gained per action has stayed the same.


Share this post


Link to post
Share on other sites

You would be better off not having it. Essentially what you're doing by having < 1.0 modifier is increasing the difficulty of the characteristics gain.


Share this post


Link to post
Share on other sites

OK, I figured this would put the characteristics up to about where they are on WO since they're still abysmally small comparatively. My other skills go up about on par w/ WO, but not characteristics. Guess there's some math stuffs that prevent this from working properly with a skillmod less than 1.0?


Share this post


Link to post
Share on other sites

Yep, right now it's doing a straight `( divisor / modifier )` which will result in a larger divisor rather than a smaller one.


Share this post


Link to post
Share on other sites

Yep, right now it's doing a straight `( divisor / modifier )` which will result in a larger divisor rather than a smaller one.

 

Yeah, I wasn't intending on this being used for anyone looking to make skill progression slower, which is what a modifier less than 1 will do.

 

All I was trying to accomplish was to still keep stats "slower" since they are raised by a number of different actions, yet faster than the default :)

Share this post


Link to post
Share on other sites

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