WyvernMods Configurable Phase 2
This commit is contained in:
@@ -12,7 +12,7 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'org.gotti.wurmunlimited:server-modlauncher:0.43'
|
compile 'org.gotti.wurmunlimited:server-modlauncher:0.43'
|
||||||
compile 'com.github.Sindusk:sindusklibrary:v2.2'
|
compile 'com.github.Sindusk:sindusklibrary:v2.3'
|
||||||
compile 'com.github.bdew-wurm:bdew_server_mod_tools:v1.0.0'
|
compile 'com.github.bdew-wurm:bdew_server_mod_tools:v1.0.0'
|
||||||
compile 'com.github.Sindusk:DiscordRelay:v1.2'
|
compile 'com.github.Sindusk:DiscordRelay:v1.2'
|
||||||
compile 'com.github.Sindusk:DUSKombat:v1.0'
|
compile 'com.github.Sindusk:DUSKombat:v1.0'
|
||||||
|
|||||||
@@ -515,6 +515,254 @@ regenerateStaminaOnVehicleAnySlope=true
|
|||||||
|
|
||||||
## >> END QUALITY OF LIFE MODULE << ##
|
## >> END QUALITY OF LIFE MODULE << ##
|
||||||
|
|
||||||
|
## >> COMBAT MODULE << ##
|
||||||
|
## The Combat Module offers options that affect the combat aspects of the game.
|
||||||
|
## This isn't restricted to simply the actual combat itself. It also includes some options to change combat-oriented spells and other mechanics.
|
||||||
|
enableCombatModule=true
|
||||||
|
|
||||||
|
# > COMBAT RATING ADJUSTMENTS < #
|
||||||
|
# Combat Rating Adjustments involve some tweaks to how combat rating is calculated.
|
||||||
|
# There are two components: additive and multiplicative combat rating adjustments.
|
||||||
|
# Additive modifiers are always applied first. This creates a "base" combat rating that is then modified.
|
||||||
|
# Multiplicative modifiers apply after all additive combat rating adjustments, including vanilla ones.
|
||||||
|
enableCombatRatingAdjustments=true
|
||||||
|
#royalExecutionerBonus: Additive - Adds +2 CR against PvE targets while holding Royal Executioner kingdom title.
|
||||||
|
# The vanilla royal executioner bonus only applies to PvP combat. This option is meant to give it a PvE bonus as well.
|
||||||
|
royalExecutionerBonus=true
|
||||||
|
#TODO: Make this option a value instead and allow configuration of how much CR to grant.
|
||||||
|
#petSoulDepthScaling: Multiplicative - Scales the CR of pets with the Soul Depth of the owner/dominator.
|
||||||
|
# Applies a multiplier of Soul Depth * 0.02 to the pet's CR. This grants 40% CR at 20 Soul Depth and 200% CR at 100 Soul Depth.
|
||||||
|
# At 50 Soul Depth this modifier equates to 100%, resulting in no change to the pet's CR.
|
||||||
|
petSoulDepthScaling=true
|
||||||
|
#TODO: Make this option a value instead and allow configuration of the CR multiplier per soul depth.
|
||||||
|
#vehicleCombatRatingPenalty: Multiplicative - Reduces the CR of players on a vehicle by 25%.
|
||||||
|
# There is no significant offensive penalty for being the commander of a vehicle while in combat.
|
||||||
|
# This option is meant to encourage players to avoid fighting while on a vehicle.
|
||||||
|
vehicleCombatRatingPenalty=true
|
||||||
|
#TODO: Make this option a value instead and allow configuration of the CR multiplier while on a vehicle.
|
||||||
|
# > END COMBAT RATING ADJUSTMENTS < #
|
||||||
|
|
||||||
|
#fixMagranonDamageStacking: In vanilla combat, Magranon/warrior damage bonus (+15% damage from deity) does not stack correctly.
|
||||||
|
# This applies only in aggressive stance, where the aggressive fighting skill calculations will adjust if the player has warrior bonus.
|
||||||
|
# When this occurs, it results in a loss of damage from the bonus, making the warrior passive effectively ~10-12% instead of the full 15%.
|
||||||
|
# This option adjusts the fight skill calculations and forces it to accurately apply the 15% damage bonus regardless of other factors.
|
||||||
|
fixMagranonDamageStacking=true
|
||||||
|
#adjustCombatRatingSpellPower: Adjusts the combat rating bonus from Truehit and Excel to 50% of their vanilla values.
|
||||||
|
adjustCombatRatingSpellPower=true
|
||||||
|
#TODO: Make this option a multiplier instead of a boolean.
|
||||||
|
#disableLegendaryRegeneration: Disables the natural healing/regeneration of legendary creatures (uniques).
|
||||||
|
disableLegendaryRegeneration=true
|
||||||
|
#useStaticLegendaryRegeneration: Applies a static healing over time to legendary creatures (uniques).
|
||||||
|
# This option is meant to be used in conjunction with the previous one to make legendaries able to be taken slowly.
|
||||||
|
# Instead of requiring their defeat in 10 minutes (where they would outheal their attackers), it now regenerates at a set rate.
|
||||||
|
# This allows players to take their time with uniques and use strategy, so long as the damage inflicted outpaces the natural static regeneration.
|
||||||
|
# The regeneration is set to 75 health per second (~0.1% maximim health per second). Requires ~874 seconds (14.5 minutes) to heal a full health bar.
|
||||||
|
useStaticLegendaryRegeneration=true
|
||||||
|
#TODO: Allow configuration of health regeneration per second.
|
||||||
|
|
||||||
|
## >> END COMBAT MODULE << ##
|
||||||
|
|
||||||
|
## >> MASTERCRAFT MODULE << ##
|
||||||
|
## The Mastercraft Module is a new series of systems designed to encourage players to explore end-game crafting further.
|
||||||
|
## Vanilla settings generally don't encourage players to skill past 90 or improve items past 90.
|
||||||
|
## The goals of this system, and the settings involved here, are to encourage players to strive for perfection instead of settling at "good enough."
|
||||||
|
enableMastercraftModule=true
|
||||||
|
|
||||||
|
# > DIFFICULTY ADJUSTMENTS < #
|
||||||
|
# Difficulty Adjustments modify the difficulty when a skill check occurs based on the factors set here.
|
||||||
|
# This affects almost all systems in the game, from combat to improvement to creation chance to spell power.
|
||||||
|
# These configurations are aimed at increasing the ways a player can improve their results for any given action.
|
||||||
|
# By putting time and effort into one's craft, they can more easily improve items to higher levels or be more successful in their activities.
|
||||||
|
enableDifficultyAdjustments=true
|
||||||
|
#affinityDifficultyBonus: Reduces the difficulty of actions by 1 per affinity in the skill.
|
||||||
|
affinityDifficultyBonus=true
|
||||||
|
#TODO: Make this configuration able to be set to any amount of difficulty reduction.
|
||||||
|
#legendDifficultyBonus: Grants a reduction to difficulty for all skill over 99.
|
||||||
|
# Begins at 99.00 skill with no difficulty change, then maxes out at 100.00 skill granting -2 difficulty.
|
||||||
|
legendDifficultyBonus=true
|
||||||
|
#masterDifficultyBonus: Grants a reduction to difficulty for all skill over 90.
|
||||||
|
# Begins at 90.00 skill with no difficulty change, then maxes out at 100.00 skill granting -2 difficulty.
|
||||||
|
masterDifficultyBonus=true
|
||||||
|
#TODO: Make the skill scaling a multi-configuration where multiple thresholds can be set for a variety of scaling difficulty changes.
|
||||||
|
#itemRarityDifficultyBonus: Reduces the difficulty of an action depending on the rarity of the tool being used.
|
||||||
|
# Normal: No bonus, Rare: -1 difficulty, Supreme: -2 difficulty, Fantastic: -3 difficulty
|
||||||
|
itemRarityDifficultyBonus=true
|
||||||
|
#legendItemDifficultyBonus: Reduces the difficulty of an action for all quality over 99 of the tool being used.
|
||||||
|
# Begins at 99.00 QL with no difficulty change, then maxes out at 100.00 QL granting -1 difficulty.
|
||||||
|
legendItemDifficultyBonus=true
|
||||||
|
#masterItemDifficultyBonus: Reduces the difficulty of an action for all quality over 90 of the tool being used.
|
||||||
|
# Begins at 90.00 QL with no difficulty change, then maxes out at 100.00 QL granting -1 difficulty.
|
||||||
|
masterItemDifficultyBonus=true
|
||||||
|
#TODO: Allow further customization of the configurations for difficulty adjustments regarding items.
|
||||||
|
|
||||||
|
# > END DIFFICULTY ADJUSTMENTS < #
|
||||||
|
|
||||||
|
#empoweredChannelers: Empowers players with up to double the power on their casts based on their channeling skill and affinities.
|
||||||
|
# This grants +2 power to casts per affinity in channeling.
|
||||||
|
# Furthermore, it also rolls 4 times up to the value of their channeling skill. It then takes the lowest value and adds it to their cast power.
|
||||||
|
# !!! Be warned that enabling this option will allow players to perform natural casts of enchants up to roughly 200 power !!!
|
||||||
|
empoweredChannelers=true
|
||||||
|
#TODO: Expand on this option and enable more configuration of how the enchant power addition is calculated.
|
||||||
|
#channelSkillFavorReduction: Reduces the favor costs of spells based on channeling skill.
|
||||||
|
# Reduces favor cost by 2% per channeling affinity.
|
||||||
|
# Reduces favor cost by 10% per skill over 99. No bonus at 99.00, scaling to 10% at 100.00 channeling.
|
||||||
|
# Reduces favor cost by 1% per skill over 90. No bonus at 90.00, scaling to 10% at 100.00 channeling.
|
||||||
|
channelSkillFavorReduction=true
|
||||||
|
#TODO: Split up the favor cost reductions, then expand into a multi-configuration style to allow further customization.
|
||||||
|
#TODO: Also, the code that executes these configurations is old and should be updated with new priest rework code to make it cleaner.
|
||||||
|
|
||||||
|
## >> END MASTERCRAFT MODULE << ##
|
||||||
|
|
||||||
|
## >> SKILL MODULE << ##
|
||||||
|
## The Skill Module allows control over the components of skills, including skill gain adjustments.
|
||||||
|
enableSkillModule=true
|
||||||
|
|
||||||
|
# > HYBRID SKILL GAIN < #
|
||||||
|
# Hybrid Skill Gain is the system which combines the vanilla Wurm Unlimited skill gain system with the classic Wurm Online model.
|
||||||
|
# In Wurm Unlimited, players gain skill for any successful action whether the result is 0.1 or 100. The skill tick size is the same every action.
|
||||||
|
# In Wurm Online, players gain skill for any successful action within the range 0 - 40. The skill tick size is based on the duration of the action.
|
||||||
|
# This new hybrid system makes it so players gain skill for any action, including mild failures (about -20), up to 100.
|
||||||
|
# However, the system also rewards more skill gain for actions with results closer to zero (if configured that way).
|
||||||
|
# This was done in order to discourage the "spam creation" skilling method. It is still effective, but improvement is now competitive.
|
||||||
|
# Visual graph that represents what this skill gain system looks like: https://i.imgur.com/9ykw5dJ.png
|
||||||
|
# Here is the formula which handles the multiplier for the new skill gain:
|
||||||
|
# valueAtOneHundred*Math.pow(valueAtZero/valueAtOneHundred, (2-Math.pow(100/(100+Math.max(-99,power)), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate));
|
||||||
|
# If you can't read/don't understand that, don't worry! Not many people can! However, if you can read or understand the function,
|
||||||
|
# you should be able to plug in a formula into Google Sheets, Wolfram Alpha, or Excel and create your own graph where you
|
||||||
|
# can adjust the following options and give the proper result that you're looking for.
|
||||||
|
# The default values listed here result in the visual graph represented above.
|
||||||
|
enableHybridSkillGain=true
|
||||||
|
#hybridNegativeDecayRate: [Limit: > 0] How fast the function decays past zero going negative.
|
||||||
|
# Higher values will cause the "midpoint" to move in a positive direction. It will also increase the sharpness of decline after the midpoint.
|
||||||
|
# Lower values will cause the "midpoint" to move in a negative direction. It will also decrease the sharpness of the decline after the midpoint, resulting a smoother curve.
|
||||||
|
hybridNegativeDecayRate=5
|
||||||
|
#hybridPositiveDecayRate: [Limit: > 0] How quickly the function will decay past zero going positive.
|
||||||
|
# Higher values will result in a sharper curve to the 1.0 multiplier in values greater than zero.
|
||||||
|
# Lower values will result in a less sharp curve towards the 1.0 multiplier in values greater than zero.
|
||||||
|
hybridPositiveDecayRate=3
|
||||||
|
#hybridValueAtZero: [Limit: > 0, must be greater than hybridValueAtOneHundred] What the multiplier should be be when an action results in zero.
|
||||||
|
hybridValueAtZero=3.74
|
||||||
|
#hybridValueAtOneHundred: [Limit: > 0, must be less than hybridValueAtZero] What the multiplier should be when an action results in one hundred.
|
||||||
|
hybridValueAtOneHundred=0.9
|
||||||
|
|
||||||
|
# > END HYBRID SKILL GAIN < #
|
||||||
|
|
||||||
|
#skillName-#: Changes the name of a skill. Format: skillName-#:skill,newName
|
||||||
|
# skill = Either the internal ID of a skill or the name of a skill (case insensitive). Example: 1008, mining, MINING, Mining, MiNiNg
|
||||||
|
# newName = The new name for the skill. Should be allowed to have spaces and other characters, but needs additional testing.
|
||||||
|
# - Case will carry to the in-game display, so keep that in mind. Making the new name fully lower case might make it look out of place among other skills.
|
||||||
|
# Set name of Preaching to Gem Augmentation
|
||||||
|
skillName-1:Preaching,Gem augmentation
|
||||||
|
# Set name of Stealing to Soulstealing
|
||||||
|
skillName-2:Stealing,Soulstealing
|
||||||
|
|
||||||
|
#skillDifficulty-#: Changes the internal difficulty of a skill. Format: skillDifficulty-#:skill,difficulty
|
||||||
|
# skill = Either the internal ID of a skill or the name of a skill (case insensitive). Example: 1008, mining, MINING, Mining, MiNiNg
|
||||||
|
# difficulty = The new difficulty to set for the skill. Most skills default to 4000. This difficulty will affect the skill gain for that skill.
|
||||||
|
# - In the example of a 4000 difficulty skill: 2000 would double skill gain. 8000 would halve skill gain. 6000 would make it 1.5x slower.
|
||||||
|
# - For a full list of difficulty for each skill... I don't have one. Nevermind.
|
||||||
|
# Set mining to 3000 difficulty. Default is 8000. Makes it 2.66x higher skill gain.
|
||||||
|
skillDifficulty-1:Mining,3000
|
||||||
|
# Set lockpicking to 700 difficulty. Default is 2000. Makes it 2.85x higher skill gain.
|
||||||
|
skillDifficulty-2:Lock Picking,700
|
||||||
|
# Set meditating difficulty to 300. Default is 2000. Makes it 6.66x higher skill gain. Meditating is evil just like the increase.
|
||||||
|
skillDifficulty-3:Meditating,300
|
||||||
|
|
||||||
|
#skillTickTime-#: Changes the tick timer for skill gain on a skill. Format: skillTickTime-#:skill,tickTime
|
||||||
|
# skill = Either the internal ID of a skill or the name of a skill (case insensitive). Example: 1008, mining, MINING, Mining, MiNiNg
|
||||||
|
# tickTime = The interval (in milliseconds) before players can gain a skill tick for a skill.
|
||||||
|
# - Example: Lock picking has a default of 600000, or 600 seconds, for it's tick time.
|
||||||
|
# - This prevents players from being able to gain another skill tick of Lock picking until 600 seconds have passed (10 minutes).
|
||||||
|
# Set tick time of stealing to zero to remove the 10 minute interval. This is useful for Soulstealing.
|
||||||
|
skillTickTime-1:Stealing,0
|
||||||
|
# Set tick time of meditating to 3600 seconds (1 hour).
|
||||||
|
skillTickTime-2:Meditating,3600000
|
||||||
|
|
||||||
|
#changePreachingLocation: Changes the dependencies of Preaching so that it moves under Masonry.
|
||||||
|
# Recommended to set to false. Option is here temporarily until further work can be done to customize dependencies.
|
||||||
|
changePreachingLocation=true
|
||||||
|
#TODO: Add multiple configuration settings to change the dependencies of skills and remove this hold-over option.
|
||||||
|
|
||||||
|
## >> END SKILL MODULE << ##
|
||||||
|
|
||||||
|
## >> MEDITATION MODULE << ##
|
||||||
|
## The Meditation Module enables adjustments to the meditation system of Wurm.
|
||||||
|
## It includes additions that make meditation perks more reasonable at lower levels and scale better as it increases.
|
||||||
|
enableMeditationModule=true
|
||||||
|
|
||||||
|
#simplifyMeditationTerrain: Simplifies the terrain where players can meditate for a question.
|
||||||
|
# Instead of having to find specific tiles, any tile of the proper type will grant a question:
|
||||||
|
# - Insanity: Any cave tile
|
||||||
|
# - Love: Any grass, bush, or tree
|
||||||
|
# - Hate: Any mycelium, mycelium bush, or infected tree
|
||||||
|
# - Knowledge: Any sand
|
||||||
|
# - Power: Any rock or cliff tile (above ground).
|
||||||
|
simplifyMeditationTerrain=true
|
||||||
|
#removeInsanitySotG: Removes the Shield of the Gone bonus from Insanity. The buff will still show, but the effect will be gone.
|
||||||
|
removeInsanitySotG=true
|
||||||
|
#removeHateWarBonus: Removes the active effect to deal increased damage in combat from Path of Hate. Does not remove the structure damage version.
|
||||||
|
removeHateWarBonus=true
|
||||||
|
#insanitySpeedBonus: Adds new effect to Path of Insanity which grants 2% increased action speed per level starting at 7.
|
||||||
|
# At Insanity level 13, this bonus equates to 12% increased action speed. Does not affect weapon swing speed.
|
||||||
|
insanitySpeedBonus=true
|
||||||
|
#TODO: Allow configuration of the speed bonus and level it starts at.
|
||||||
|
#hateMovementBonus: Adds a new effect to Path of Hate which grants 1% increased movement speed (walking only) per level starting at 3.
|
||||||
|
# At Hate level 13, this bonus equates to 10% increased movement speed. Does not affect mounted or vehicle movement speed.
|
||||||
|
hateMovementBonus=true
|
||||||
|
#TODO: Allow configuration of the movement bonus and level it starts at.
|
||||||
|
#scalingPowerStaminaBonus: Scales the Path of Power stamina bonus from 30 at level 11 to start at 7 and increase with each level.
|
||||||
|
# Grants 5 bonus stamina at level 7, and adds 5 additional stamina per level afterwards.
|
||||||
|
# At Power level 13, this bonus equates to 30 additional Body Stamina.
|
||||||
|
scalingPowerStaminaBonus=true
|
||||||
|
#TODO: Allow configuration of the stamina bonus and level it starts at.
|
||||||
|
#scalingKnowledgeSkillGain: Scales the Path of Knowledge skill gain bonus from 25% at level 11 to start at 7 and increase with each level.
|
||||||
|
# Grants 5% increased skill gain at level 7, and adds 5% additional skill gain per level afterwards.
|
||||||
|
# At Knowledge level 13, this bonus grants 30% increased skill gain.
|
||||||
|
scalingKnowledgeSkillGain=true
|
||||||
|
#TODO: Allow configuration of the skill gain bonus and level it starts at.
|
||||||
|
#removeMeditationTickTimer: Removes the vanilla meditation tick timer which is not attached to the skill.
|
||||||
|
# This tick timer is coded differently from the skill system. It has to be removed like this in order to make the skill system version work.
|
||||||
|
# Enabling this option will allow you to configure the meditation tick timer using the Skills module.
|
||||||
|
# Without this enabled, this will override any settings from the Skills module and prevent skill gain unless the meditation system allows it.
|
||||||
|
removeMeditationTickTimer=true
|
||||||
|
#newMeditationBuffs: This option is meant to adjust the buff icons for meditation to coincide with all the options above.
|
||||||
|
# It's recommended to only allow this if all (or at least most) of the options above are enabled.
|
||||||
|
# Otherwise it probably wont display buffs correctly for some paths.
|
||||||
|
newMeditationBuffs=true
|
||||||
|
#TODO: Recode this to make it adjust properly to the configurations set throughout the rest of the module.
|
||||||
|
|
||||||
|
# > MEDITATION ABILITY COOLDOWNS < #
|
||||||
|
# Meditation Ability Cooldowns allow you to set all of the cooldowns for meditation abilities.
|
||||||
|
# All cooldowns are set using milliseconds. A setting of 1000 means 1 second in this configuration.
|
||||||
|
enableMeditationAbilityCooldowns=true
|
||||||
|
#loveRefreshCooldown: Cooldown for Path of Love's Refresh ability. (Default: 64800000 [18 hours])
|
||||||
|
loveRefreshCooldown=28800000
|
||||||
|
#loveEnchantNatureCooldown: Cooldown for Path of Love's Enchant Nature ability. (Default: 64800000 [18 hours])
|
||||||
|
loveEnchantNatureCooldown=28800000
|
||||||
|
#loveLoveEffectCooldown: Cooldown for Path of Love's Love Effect ability. (Default: 64800000 [18 hours])
|
||||||
|
loveLoveEffectCooldown=14400000
|
||||||
|
#hateWarDamageCooldown: Cooldown for Path of Hate's War Damage ability. (Default: 64800000 [18 hours])
|
||||||
|
hateWarDamageCooldown=21600000
|
||||||
|
#hateStructureDamageCooldown: Cooldown for Path of Hate's Structure Damage ability. (Default: 64800000 [18 hours])
|
||||||
|
hateStructureDamageCooldown=14400000
|
||||||
|
#hateFearCooldown: Cooldown for Path of Hate's Fear ability. (Default: 64800000 [18 hours])
|
||||||
|
hateFearCooldown=21600000
|
||||||
|
#powerElementalImmunityCooldown: Cooldown of Path of Power's Elemental Immunity ability. (Default: 64800000 [18 hours])
|
||||||
|
powerElementalImmunityCooldown=21600000
|
||||||
|
#powerEruptFreezeCooldown: Cooldown of Path of Power's Erupt/Freeze abilities. (Default: 64800000 [18 hours])
|
||||||
|
powerEruptFreezeCooldown=28800000
|
||||||
|
#powerIgnoreTrapsCooldown: Cooldown of Path of Power's Ignore Traps ability. (Default: 64800000 [18 hours])
|
||||||
|
powerIgnoreTrapsCooldown=14400000
|
||||||
|
#knowledgeInfoCreatureCooldown: Cooldown of Path of Knowledge's Get Info (Creature) ability. (Default: 64800000 [18 hours])
|
||||||
|
knowledgeInfoCreatureCooldown=14400000
|
||||||
|
#knowledgeInfoTileCooldown: Cooldown of Path of Knowledge's Get Info (Tile) ability. (Default: 64800000 [18 hours])
|
||||||
|
knowledgeInfoTileCooldown=14400000
|
||||||
|
#TODO: Add the rest of the meditation abilites as configurable options.
|
||||||
|
|
||||||
|
# > END MEDITATION ABILITY COOLDOWNS < #
|
||||||
|
|
||||||
|
## >> END MEDITATION MODULE << ##
|
||||||
|
|
||||||
## >> TREASURE CHEST LOOT MODULE << ##
|
## >> TREASURE CHEST LOOT MODULE << ##
|
||||||
## The Treasure Chest Loot Module affects the vanilla treasure chests.
|
## The Treasure Chest Loot Module affects the vanilla treasure chests.
|
||||||
## By default, treasure chests can spawn randomly in the wild. This module reconfigures the loot that spawns in them.
|
## By default, treasure chests can spawn randomly in the wild. This module reconfigures the loot that spawns in them.
|
||||||
|
|||||||
@@ -24,23 +24,12 @@ import java.util.logging.Logger;
|
|||||||
public class CombatChanges {
|
public class CombatChanges {
|
||||||
public static Logger logger = Logger.getLogger(CombatChanges.class.getName());
|
public static Logger logger = Logger.getLogger(CombatChanges.class.getName());
|
||||||
|
|
||||||
// Added to CombatHandled
|
|
||||||
public static int getWeaponType(Item weapon){
|
|
||||||
if(weapon.enchantment == Enchants.ACID_DAM){
|
|
||||||
return Wound.TYPE_ACID;
|
|
||||||
}else if(weapon.enchantment == Enchants.FROST_DAM){
|
|
||||||
return Wound.TYPE_COLD;
|
|
||||||
}else if(weapon.enchantment == Enchants.FIRE_DAM){
|
|
||||||
return Wound.TYPE_BURN;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float combatRatingAdditive(float combatRating, Creature cret, Creature opponent){
|
public static float combatRatingAdditive(float combatRating, Creature cret, Creature opponent){
|
||||||
//logger.info("Checking additive ("+cret.getName()+" vs "+opponent.getName()+"), combatRating = "+combatRating);
|
//logger.info("Checking additive ("+cret.getName()+" vs "+opponent.getName()+"), combatRating = "+combatRating);
|
||||||
float add = 0.0f;
|
float add = 0.0f;
|
||||||
if(cret != null && cret.isPlayer() && (opponent != null && !opponent.isPlayer())){
|
if(cret != null && cret.isPlayer() && (opponent != null && !opponent.isPlayer())){
|
||||||
if(cret.isRoyalExecutioner()){
|
// 2 CR against non-players for Royal Executioner kingdom title.
|
||||||
|
if(WyvernMods.royalExecutionerBonus && cret.isRoyalExecutioner()){
|
||||||
add += 2.0f;
|
add += 2.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +40,7 @@ public class CombatChanges {
|
|||||||
float mult = 1.0f;
|
float mult = 1.0f;
|
||||||
if(cret != null){
|
if(cret != null){
|
||||||
//logger.info("Cret is a pet.");
|
//logger.info("Cret is a pet.");
|
||||||
if(cret.isDominated() && cret.getDominator() != null) {
|
if(WyvernMods.petSoulDepthScaling && cret.isDominated() && cret.getDominator() != null) {
|
||||||
if (cret.getDominator() instanceof Player) {
|
if (cret.getDominator() instanceof Player) {
|
||||||
Player owner = (Player) cret.getDominator();
|
Player owner = (Player) cret.getDominator();
|
||||||
double depth = owner.getSoulDepth().getKnowledge();
|
double depth = owner.getSoulDepth().getKnowledge();
|
||||||
@@ -61,7 +50,7 @@ public class CombatChanges {
|
|||||||
logger.info("Somehow a pet is dominated by a non-player? (" + cret.getDominator().getName() + ")");
|
logger.info("Somehow a pet is dominated by a non-player? (" + cret.getDominator().getName() + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(QualityOfLife.getVehicleSafe(cret) != null){
|
if(WyvernMods.vehicleCombatRatingPenalty && QualityOfLife.getVehicleSafe(cret) != null){
|
||||||
mult *= 0.75f;
|
mult *= 0.75f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,17 +87,6 @@ public class CombatChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Added (kind of) to CombatHandled
|
|
||||||
public static float getAdjustedOakshell(Creature defender, Item armour, float armourMod){
|
|
||||||
if(defender != null && armour == null){
|
|
||||||
float oakshellPower = defender.getBonusForSpellEffect(Enchants.CRET_OAKSHELL);
|
|
||||||
if(oakshellPower > 0f){
|
|
||||||
return (float) (1-(0.8f*Math.pow((oakshellPower/(oakshellPower+80)), 0.5d)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return armourMod; // Returns previous armourMod if the target has armour.
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static ArrayList<Creature> uniques = new ArrayList<>();
|
protected static ArrayList<Creature> uniques = new ArrayList<>();
|
||||||
public static void pollUniqueCollection(){
|
public static void pollUniqueCollection(){
|
||||||
for(Creature cret : Creatures.getInstance().getCreatures()){
|
for(Creature cret : Creatures.getInstance().getCreatures()){
|
||||||
@@ -151,114 +129,6 @@ public class CombatChanges {
|
|||||||
return damage > 1D;
|
return damage > 1D;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disabled as of WU 1.9 - No longer necessary and no longer functions.
|
|
||||||
|
|
||||||
static void patchCombatDamageCheckCombatEngine(ClassPool classPool) throws NotFoundException, BadBytecode {
|
|
||||||
CtClass cls = classPool.getCtClass("com.wurmonline.server.combat.CombatEngine");
|
|
||||||
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
|
|
||||||
CtClass ctString = classPool.get("java.lang.String");
|
|
||||||
CtClass ctBattle = classPool.get("com.wurmonline.server.combat.Battle");
|
|
||||||
CtClass ctCombatEngine = classPool.get("com.wurmonline.server.combat.CombatEngine");
|
|
||||||
// @Nullable Creature performer, Creature defender, byte type, int pos, double damage, float armourMod,
|
|
||||||
// String attString, @Nullable Battle battle, float infection, float poison, boolean archery, boolean alreadyCalculatedResist
|
|
||||||
CtClass[] params1 = {
|
|
||||||
ctCreature,
|
|
||||||
ctCreature,
|
|
||||||
CtClass.byteType,
|
|
||||||
CtClass.intType,
|
|
||||||
CtClass.doubleType,
|
|
||||||
CtClass.floatType,
|
|
||||||
ctString,
|
|
||||||
ctBattle,
|
|
||||||
CtClass.floatType,
|
|
||||||
CtClass.floatType,
|
|
||||||
CtClass.booleanType,
|
|
||||||
CtClass.booleanType
|
|
||||||
};
|
|
||||||
String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1);
|
|
||||||
CtMethod method = cls.getMethod("addWound", desc1);
|
|
||||||
//CtMethod method = cls.getMethod("setDamage", "(Lcom/wurmonline/server/creatures/Creature;Lcom/wurmonline/server/items/Item;DBB)Z");
|
|
||||||
MethodInfo methodInfo = method.getMethodInfo();
|
|
||||||
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
|
|
||||||
ConstPool constPool = codeAttribute.getConstPool();
|
|
||||||
CodeIterator codeIterator = codeAttribute.iterator();
|
|
||||||
|
|
||||||
// Scan through all the bytecode - look for a multiplication followed by comparing
|
|
||||||
while (codeIterator.hasNext()) {
|
|
||||||
int pos = codeIterator.next();
|
|
||||||
int op = codeIterator.byteAt(pos);
|
|
||||||
if (op != CodeIterator.DMUL) continue; // not multiplication - continue
|
|
||||||
op = codeIterator.byteAt(++pos);
|
|
||||||
if (op == CodeIterator.LDC2_W && codeIterator.byteAt(pos + 3) == CodeIterator.DCMPL) {
|
|
||||||
// found the pattern, check the value it's comparing to
|
|
||||||
int ref = codeIterator.u16bitAt(pos + 1);
|
|
||||||
double val = constPool.getDoubleInfo(ref);
|
|
||||||
if (val == 500.0) {
|
|
||||||
// here it is, generate new code to insert
|
|
||||||
// We'll be calling canDoDamage, the first parameter (damage) is already on the stack, prepare the rest
|
|
||||||
Bytecode newCode = new Bytecode(constPool);
|
|
||||||
|
|
||||||
newCode.add(Bytecode.ALOAD_0); // performer - first parameter of addWound
|
|
||||||
newCode.add(Bytecode.ALOAD_1); // defender - first parameter of addWound
|
|
||||||
|
|
||||||
// call our methor, result is left on the stack
|
|
||||||
newCode.addInvokestatic(
|
|
||||||
CombatChanges.class.getName(), "canDoDamage",
|
|
||||||
"(DLcom/wurmonline/server/creatures/Creature;Lcom/wurmonline/server/creatures/Creature;)Z");
|
|
||||||
|
|
||||||
// The code we're replacing is 4 bytes - LDC2_W, 2byte reference and DCMPL
|
|
||||||
// Insert a gap for to match the size of the new code
|
|
||||||
codeIterator.insertGap(pos, newCode.getSize() - 4);
|
|
||||||
|
|
||||||
// And put the new code
|
|
||||||
codeIterator.write(newCode.get(), pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*static void patchCombatDamageCheckCombatHandler(ClassPool classPool) throws NotFoundException, BadBytecode {
|
|
||||||
CtClass cls = classPool.getCtClass("com.wurmonline.server.creatures.CombatHandler");
|
|
||||||
CtMethod method = cls.getMethod("setDamage", "(Lcom/wurmonline/server/creatures/Creature;Lcom/wurmonline/server/items/Item;DBB)Z");
|
|
||||||
MethodInfo methodInfo = method.getMethodInfo();
|
|
||||||
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
|
|
||||||
ConstPool constPool = codeAttribute.getConstPool();
|
|
||||||
CodeIterator codeIterator = codeAttribute.iterator();
|
|
||||||
|
|
||||||
// Scan through all the bytecode - look for a multiplication followed by comparing
|
|
||||||
while (codeIterator.hasNext()) {
|
|
||||||
int pos = codeIterator.next();
|
|
||||||
int op = codeIterator.byteAt(pos);
|
|
||||||
if (op != CodeIterator.DMUL) continue; // not multiplication - continue
|
|
||||||
op = codeIterator.byteAt(++pos);
|
|
||||||
if (op == CodeIterator.LDC2_W && codeIterator.byteAt(pos + 3) == CodeIterator.DCMPL) {
|
|
||||||
// found the pattern, check the value it's comparing to
|
|
||||||
int ref = codeIterator.u16bitAt(pos + 1);
|
|
||||||
double val = constPool.getDoubleInfo(ref);
|
|
||||||
if (val == 500.0) {
|
|
||||||
// here it is, generate new code to insert
|
|
||||||
// We'll be calling canDoDamage, the first parameter (damage) is already on the stack, prepare the rest
|
|
||||||
Bytecode newCode = new Bytecode(constPool);
|
|
||||||
newCode.add(Bytecode.ALOAD_0); // this
|
|
||||||
newCode.addGetfield(cls, "creature", "Lcom/wurmonline/server/creatures/Creature;"); // this.creature
|
|
||||||
newCode.add(Bytecode.ALOAD_1); // defender - first parameter of setDamage
|
|
||||||
|
|
||||||
// call our methor, result is left on the stack
|
|
||||||
newCode.addInvokestatic(
|
|
||||||
CombatChanges.class.getName(), "canDoDamage",
|
|
||||||
"(DLcom/wurmonline/server/creatures/Creature;Lcom/wurmonline/server/creatures/Creature;)Z");
|
|
||||||
|
|
||||||
// The code we're replacing is 4 bytes - LDC2_W, 2byte reference and DCMPL
|
|
||||||
// Insert a gap for to match the size of the new code
|
|
||||||
codeIterator.insertGap(pos, newCode.getSize() - 4);
|
|
||||||
|
|
||||||
// And put the new code
|
|
||||||
codeIterator.write(newCode.get(), pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// Added to CombatHandled
|
// Added to CombatHandled
|
||||||
public static void pollCreatureActionStacks(){
|
public static void pollCreatureActionStacks(){
|
||||||
for(Creature c : Creatures.getInstance().getCreatures()){
|
for(Creature c : Creatures.getInstance().getCreatures()){
|
||||||
@@ -278,119 +148,73 @@ public class CombatChanges {
|
|||||||
final Class<CombatChanges> thisClass = CombatChanges.class;
|
final Class<CombatChanges> thisClass = CombatChanges.class;
|
||||||
String replace;
|
String replace;
|
||||||
|
|
||||||
Util.setReason("Make custom combat rating changes.");
|
|
||||||
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
|
CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler");
|
||||||
replace = "combatRating += "+CombatChanges.class.getName()+".combatRatingAdditive(combatRating, this.creature, $1);" +
|
|
||||||
"crmod *= "+CombatChanges.class.getName()+".combatRatingMultiplicative(combatRating, this.creature, $1);" +
|
|
||||||
"$_ = $proceed($$);";
|
|
||||||
Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getFlankingModifier", replace);
|
|
||||||
|
|
||||||
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
|
CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature");
|
||||||
|
|
||||||
/* Disabled in Wurm Unlimited 1.9 - No longer necessary while using DUSKombat.
|
|
||||||
|
|
||||||
Util.setReason("Increase unique damage to pets.");
|
|
||||||
CtClass ctString = classPool.get("java.lang.String");
|
|
||||||
CtClass ctBattle = classPool.get("com.wurmonline.server.combat.Battle");
|
|
||||||
CtClass ctCombatEngine = classPool.get("com.wurmonline.server.combat.CombatEngine");
|
|
||||||
// @Nullable Creature performer, Creature defender, byte type, int pos, double damage, float armourMod,
|
|
||||||
// String attString, @Nullable Battle battle, float infection, float poison, boolean archery, boolean alreadyCalculatedResist
|
|
||||||
CtClass[] params1 = {
|
|
||||||
ctCreature,
|
|
||||||
ctCreature,
|
|
||||||
CtClass.byteType,
|
|
||||||
CtClass.intType,
|
|
||||||
CtClass.doubleType,
|
|
||||||
CtClass.floatType,
|
|
||||||
ctString,
|
|
||||||
ctBattle,
|
|
||||||
CtClass.floatType,
|
|
||||||
CtClass.floatType,
|
|
||||||
CtClass.booleanType,
|
|
||||||
CtClass.booleanType
|
|
||||||
};
|
|
||||||
String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1);
|
|
||||||
replace = "if($2.isDominated() && $1 != null && $1.isUnique()){" +
|
|
||||||
//" logger.info(\"Detected unique hit on a pet. Adding damage.\");" +
|
|
||||||
" $5 = $5 * 2d;" +
|
|
||||||
"}" +
|
|
||||||
"if($2.isUnique() && $1 != null && $1.isDominated()){" +
|
|
||||||
" logger.info(\"Detected pet hit on a unique. Reducing damage.\");" +
|
|
||||||
" $5 = $5 * 0.5d;" +
|
|
||||||
"}";
|
|
||||||
Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc1, replace);*/
|
|
||||||
|
|
||||||
Util.setReason("Adjust weapon damage type based on the potion/salve applied.");
|
|
||||||
replace = "int wt = "+CombatChanges.class.getName()+".getWeaponType($1);"
|
|
||||||
+ "if(wt != -1){"
|
|
||||||
+ " type = wt;"
|
|
||||||
+ " return wt;"
|
|
||||||
+ "}";
|
|
||||||
Util.insertBeforeDeclared(thisClass, ctCombatHandler, "getType", replace);
|
|
||||||
|
|
||||||
CtClass ctItem = classPool.get("com.wurmonline.server.items.Item");
|
CtClass ctItem = classPool.get("com.wurmonline.server.items.Item");
|
||||||
CtClass[] params2 = {
|
|
||||||
ctCreature,
|
|
||||||
ctItem,
|
|
||||||
ctCreature
|
|
||||||
};
|
|
||||||
String desc2 = Descriptor.ofMethod(CtClass.doubleType, params2);
|
|
||||||
|
|
||||||
/* Disabled in Wurm Unlimited 1.9 - Priest Rework adjusted Bloodthirst in an identical way.
|
|
||||||
|
|
||||||
Util.setReason("Adjust bloodthirst to epic settings.");
|
|
||||||
replace = "$_ = true;";
|
|
||||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "isThisAnEpicOrChallengeServer", replace);*/
|
|
||||||
|
|
||||||
Util.setReason("Fix magranon damage bonus stacking.");
|
|
||||||
replace = "if(mildStack){" +
|
|
||||||
" $_ = $proceed($$) * 8 / 5;" +
|
|
||||||
"}else{" +
|
|
||||||
" $_ = $proceed($$);" +
|
|
||||||
"}";
|
|
||||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "getModifiedFloatEffect", replace);
|
|
||||||
|
|
||||||
CtClass ctAttackAction = classPool.get("com.wurmonline.server.creatures.AttackAction");
|
CtClass ctAttackAction = classPool.get("com.wurmonline.server.creatures.AttackAction");
|
||||||
CtClass[] params3 = {
|
|
||||||
ctCreature,
|
|
||||||
ctAttackAction,
|
|
||||||
ctCreature
|
|
||||||
};
|
|
||||||
String desc3 = Descriptor.ofMethod(CtClass.doubleType, params3);
|
|
||||||
|
|
||||||
/* Disabled in Wurm Unlimited 1.9 - Priest Rework adjusted Bloodthirst in an identical way.
|
if (WyvernMods.enableCombatRatingAdjustments) {
|
||||||
|
Util.setReason("Make custom combat rating changes.");
|
||||||
|
replace = "combatRating += " + CombatChanges.class.getName() + ".combatRatingAdditive(combatRating, this.creature, $1);" +
|
||||||
|
"crmod *= " + CombatChanges.class.getName() + ".combatRatingMultiplicative(combatRating, this.creature, $1);" +
|
||||||
|
"$_ = $proceed($$);";
|
||||||
|
Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getFlankingModifier", replace);
|
||||||
|
}
|
||||||
|
|
||||||
Util.setReason("Adjust bloodthirst to epic settings.");
|
if (WyvernMods.fixMagranonDamageStacking) {
|
||||||
replace = "$_ = true;";
|
// Normal combat version
|
||||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "isThisAnEpicOrChallengeServer", replace);*/
|
CtClass[] params2 = {
|
||||||
|
ctCreature,
|
||||||
|
ctItem,
|
||||||
|
ctCreature
|
||||||
|
};
|
||||||
|
String desc2 = Descriptor.ofMethod(CtClass.doubleType, params2);
|
||||||
|
|
||||||
Util.setReason("Fix magranon damage bonus stacking.");
|
Util.setReason("Fix magranon damage bonus stacking.");
|
||||||
replace = "if(mildStack){" +
|
replace = "if(mildStack){" +
|
||||||
" $_ = $proceed($$) * 8 / 5;" +
|
" $_ = $proceed($$) * 8 / 5;" +
|
||||||
"}else{" +
|
"}else{" +
|
||||||
" $_ = $proceed($$);" +
|
" $_ = $proceed($$);" +
|
||||||
"}";
|
"}";
|
||||||
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "getModifiedFloatEffect", replace);
|
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc2, "getModifiedFloatEffect", replace);
|
||||||
|
|
||||||
Util.setReason("Nerf truehit/excel.");
|
// AttackAction version
|
||||||
replace = "$_ = $proceed($$) * 0.5f;";
|
CtClass[] params3 = {
|
||||||
Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getBonusForSpellEffect", replace);
|
ctCreature,
|
||||||
|
ctAttackAction,
|
||||||
|
ctCreature
|
||||||
|
};
|
||||||
|
String desc3 = Descriptor.ofMethod(CtClass.doubleType, params3);
|
||||||
|
|
||||||
Util.setReason("Nerf oakshell.");
|
Util.setReason("Fix magranon damage bonus stacking.");
|
||||||
replace = "if(defender.isPlayer() && defender.getBonusForSpellEffect((byte)22) > 0f){" +
|
replace = "if(mildStack){" +
|
||||||
" armourMod = "+CombatChanges.class.getName()+".getAdjustedOakshell(defender, armour, armourMod);" +
|
" $_ = $proceed($$) * 8 / 5;" +
|
||||||
"}" +
|
"}else{" +
|
||||||
"$_ = $proceed($$);";
|
" $_ = $proceed($$);" +
|
||||||
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "getDamReductionBonusFor", replace);
|
"}";
|
||||||
|
Util.instrumentDescribed(thisClass, ctCombatHandler, "getDamage", desc3, "getModifiedFloatEffect", replace);
|
||||||
|
}
|
||||||
|
|
||||||
Util.setReason("Disable natural regeneration on uniques.");
|
if (WyvernMods.adjustCombatRatingSpellPower) {
|
||||||
CtClass ctWound = classPool.get("com.wurmonline.server.bodys.Wound");
|
Util.setReason("Nerf truehit/excel.");
|
||||||
replace = "if(!this.creature.isUnique()){"
|
replace = "$_ = $proceed($$) * 0.5f;";
|
||||||
+ " $_ = $proceed($$);"
|
Util.instrumentDeclared(thisClass, ctCombatHandler, "getCombatRating", "getBonusForSpellEffect", replace);
|
||||||
+ "}";
|
}
|
||||||
Util.instrumentDeclared(thisClass, ctWound, "poll", "modifySeverity", replace);
|
|
||||||
Util.instrumentDeclared(thisClass, ctWound, "poll", "checkInfection", replace);
|
if (WyvernMods.disableLegendaryRegeneration) {
|
||||||
Util.instrumentDeclared(thisClass, ctWound, "poll", "checkPoison", replace);
|
Util.setReason("Disable natural regeneration on legendary creatures.");
|
||||||
|
CtClass ctWound = classPool.get("com.wurmonline.server.bodys.Wound");
|
||||||
|
replace = "if(!this.creature.isUnique()){"
|
||||||
|
+ " $_ = $proceed($$);"
|
||||||
|
+ "}";
|
||||||
|
Util.instrumentDeclared(thisClass, ctWound, "poll", "modifySeverity", replace);
|
||||||
|
Util.setReason("Disable natural regeneration on legendary creatures.");
|
||||||
|
Util.instrumentDeclared(thisClass, ctWound, "poll", "checkInfection", replace);
|
||||||
|
Util.setReason("Disable natural regeneration on legendary creatures.");
|
||||||
|
Util.instrumentDeclared(thisClass, ctWound, "poll", "checkPoison", replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disabled for now until it can be fixed for new Priest Update adjustments.
|
||||||
|
|
||||||
Util.setReason("Allow Life Transfer to stack with Rotting Touch (Mechanics-Wise).");
|
Util.setReason("Allow Life Transfer to stack with Rotting Touch (Mechanics-Wise).");
|
||||||
replace = CombatChanges.class.getName()+".doLifeTransfer(this.creature, defender, attWeapon, defdamage, armourMod);"
|
replace = CombatChanges.class.getName()+".doLifeTransfer(this.creature, defender, attWeapon, defdamage, armourMod);"
|
||||||
@@ -403,15 +227,7 @@ public class CombatChanges {
|
|||||||
|
|
||||||
Util.setReason("Reduce Life Transfer healing amount for certain wounds.");
|
Util.setReason("Reduce Life Transfer healing amount for certain wounds.");
|
||||||
replace = "$_ = $proceed("+CombatChanges.class.getName()+".getLifeTransferAmountModifier($0, $1));";
|
replace = "$_ = $proceed("+CombatChanges.class.getName()+".getLifeTransferAmountModifier($0, $1));";
|
||||||
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "modifySeverity", replace);
|
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "modifySeverity", replace);*/
|
||||||
|
|
||||||
Util.setReason("Make AOSP not disgustingly broken.");
|
|
||||||
replace = "if(!this.creature.isPlayer()){" +
|
|
||||||
" $_ = $proceed($$)*this.creature.addSpellResistance((short) 278);" +
|
|
||||||
"}else{" +
|
|
||||||
" $_ = $proceed($$);" +
|
|
||||||
"}";
|
|
||||||
Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "getSpellPainShare", replace);
|
|
||||||
|
|
||||||
/*Util.setReason("Debug attack method");
|
/*Util.setReason("Debug attack method");
|
||||||
CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action");
|
CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action");
|
||||||
|
|||||||
126
src/main/java/mod/sin/wyvern/Mastercraft.java
Normal file
126
src/main/java/mod/sin/wyvern/Mastercraft.java
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package mod.sin.wyvern;
|
||||||
|
|
||||||
|
import com.wurmonline.server.Server;
|
||||||
|
import com.wurmonline.server.items.Item;
|
||||||
|
import com.wurmonline.server.players.Titles;
|
||||||
|
import com.wurmonline.server.skills.Skill;
|
||||||
|
import javassist.*;
|
||||||
|
import javassist.expr.ExprEditor;
|
||||||
|
import javassist.expr.MethodCall;
|
||||||
|
import mod.sin.lib.Util;
|
||||||
|
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
|
||||||
|
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class Mastercraft {
|
||||||
|
private static Logger logger = Logger.getLogger(Mastercraft.class.getName());
|
||||||
|
public static double getNewDifficulty(Skill skill, double diff, Item item){
|
||||||
|
if(WyvernMods.affinityDifficultyBonus && skill.affinity > 0){
|
||||||
|
diff -= skill.affinity;
|
||||||
|
}
|
||||||
|
if(WyvernMods.legendDifficultyBonus && skill.getKnowledge() > 99.0d){
|
||||||
|
diff -= 2d-((100d-skill.getKnowledge())*2d);
|
||||||
|
}
|
||||||
|
if(WyvernMods.masterDifficultyBonus && skill.getKnowledge() > 90.0d){
|
||||||
|
diff -= 2d-((100d-skill.getKnowledge())*0.2d);
|
||||||
|
}
|
||||||
|
if(item != null){
|
||||||
|
if(WyvernMods.itemRarityDifficultyBonus && item.getRarity() > 0){
|
||||||
|
diff -= item.getRarity();
|
||||||
|
}
|
||||||
|
if(WyvernMods.legendItemDifficultyBonus && item.getCurrentQualityLevel() > 99.0f){
|
||||||
|
diff -= 1d-((100d-item.getCurrentQualityLevel())*1d);
|
||||||
|
}
|
||||||
|
if(WyvernMods.masterItemDifficultyBonus && item.getCurrentQualityLevel() > 90.0f){
|
||||||
|
diff -= 1d-((100d-item.getCurrentQualityLevel())*0.1d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
public static float getCastPowerIncrease(Skill skill){
|
||||||
|
double addedPower = 0;
|
||||||
|
if(skill.affinity > 0){
|
||||||
|
addedPower += 2*skill.affinity;
|
||||||
|
}
|
||||||
|
if(skill.getKnowledge() > 0){
|
||||||
|
float lowFloat1 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat());
|
||||||
|
float lowFloat2 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat());
|
||||||
|
addedPower += Math.min(skill.getKnowledge()*lowFloat1, skill.getKnowledge()*lowFloat2);
|
||||||
|
}else{
|
||||||
|
logger.warning("Error: Some player just tried casting with no channeling skill!");
|
||||||
|
}
|
||||||
|
return (float) addedPower;
|
||||||
|
}
|
||||||
|
public static float getFavorCostMultiplier(Skill skill){
|
||||||
|
float mult = 1f;
|
||||||
|
if(skill.affinity > 0){
|
||||||
|
mult -= skill.affinity*0.02f; //2% reduction per affinity
|
||||||
|
}
|
||||||
|
if(skill.getKnowledge() > 90d){
|
||||||
|
mult -= 0.1d-((100d-skill.getKnowledge())*0.01d);
|
||||||
|
}
|
||||||
|
if(skill.getKnowledge() > 99d){
|
||||||
|
mult -= 0.1d-((100-skill.getKnowledge())*0.1d);
|
||||||
|
}
|
||||||
|
return mult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void changeExistingTitles(){
|
||||||
|
for (Titles.Title title : Titles.Title.values()) {
|
||||||
|
if (Objects.equals("Pumpkin King", title.getFemaleName())){
|
||||||
|
try {
|
||||||
|
ReflectionUtil.setPrivateField(title, ReflectionUtil.getField(title.getClass(), "femaleName"), "Pumpkin Queen");
|
||||||
|
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void preInit(){
|
||||||
|
try {
|
||||||
|
ClassPool classPool = HookManager.getInstance().getClassPool();
|
||||||
|
Class<Mastercraft> thisClass = Mastercraft.class;
|
||||||
|
|
||||||
|
// - Reduce skill check difficulty with high skills or tools - //
|
||||||
|
CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill");
|
||||||
|
|
||||||
|
if (WyvernMods.enableDifficultyAdjustments) {
|
||||||
|
Util.setReason("Modify difficulty for skill checks in MasterCraft.");
|
||||||
|
String replace = "$1 = " + Mastercraft.class.getName() + ".getNewDifficulty(this, $1, $2);";
|
||||||
|
Util.insertBeforeDeclared(thisClass, ctSkill, "checkAdvance", replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - Increase spellcasting power for skilled channelers - //
|
||||||
|
CtClass ctSpell = classPool.get("com.wurmonline.server.spells.Spell");
|
||||||
|
CtMethod[] ctRuns = ctSpell.getDeclaredMethods("run");
|
||||||
|
for(CtMethod method : ctRuns){
|
||||||
|
if (WyvernMods.empoweredChannelers) {
|
||||||
|
method.instrument(new ExprEditor() {
|
||||||
|
public void edit(MethodCall m) throws CannotCompileException {
|
||||||
|
if (m.getMethodName().equals("doEffect")) {
|
||||||
|
m.replace("$2 += " + Mastercraft.class.getName() + ".getCastPowerIncrease(castSkill);"
|
||||||
|
+ "$_ = $proceed($$);");
|
||||||
|
logger.info("Instrumented doEffect in run()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (WyvernMods.channelSkillFavorReduction) {
|
||||||
|
method.instrument(new ExprEditor() {
|
||||||
|
public void edit(MethodCall m) throws CannotCompileException {
|
||||||
|
if (m.getMethodName().equals("depleteFavor")) {
|
||||||
|
m.replace("$1 *= " + Mastercraft.class.getName() + ".getFavorCostMultiplier(castSkill);"
|
||||||
|
+ "$_ = $proceed($$);");
|
||||||
|
logger.info("Instrumented depleteFavor in run()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (CannotCompileException | NotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@ public class MeditationPerks {
|
|||||||
if(path.getPath() == Cults.PATH_HATE){
|
if(path.getPath() == Cults.PATH_HATE){
|
||||||
byte level = path.getLevel();
|
byte level = path.getLevel();
|
||||||
if(level >= 3){
|
if(level >= 3){
|
||||||
float levelDiff = level-3f;
|
float levelDiff = level-2f;
|
||||||
return 1.0f+(levelDiff*0.01f);
|
return 1.0f+(levelDiff*0.01f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,36 +156,54 @@ public class MeditationPerks {
|
|||||||
final Class<MeditationPerks> thisClass = MeditationPerks.class;
|
final Class<MeditationPerks> thisClass = MeditationPerks.class;
|
||||||
String replace;
|
String replace;
|
||||||
|
|
||||||
Util.setReason("Enable buff icons for meditation.");
|
|
||||||
CtClass ctCultist = classPool.get("com.wurmonline.server.players.Cultist");
|
CtClass ctCultist = classPool.get("com.wurmonline.server.players.Cultist");
|
||||||
replace = MeditationPerks.class.getName()+".sendPassiveBuffs($0);";
|
|
||||||
Util.insertBeforeDeclared(thisClass, ctCultist, "sendPassiveBuffs", replace);
|
|
||||||
|
|
||||||
Util.setReason("Make meditating paths more straightforward.");
|
|
||||||
CtClass ctCults = classPool.get("com.wurmonline.server.players.Cults");
|
CtClass ctCults = classPool.get("com.wurmonline.server.players.Cults");
|
||||||
replace = "{ return "+MeditationPerks.class.getName()+".getNewPathFor($1, $2, $3); }";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCults, "getPathFor", replace);
|
|
||||||
|
|
||||||
Util.setReason("Replace stamina modifier for new Insanity ability.");
|
|
||||||
CtClass ctActions = classPool.get("com.wurmonline.server.behaviours.Actions");
|
CtClass ctActions = classPool.get("com.wurmonline.server.behaviours.Actions");
|
||||||
replace = "{ return "+MeditationPerks.class.getName()+".newStaminaModifierFor($1, $2); }";
|
|
||||||
Util.setBodyDeclared(thisClass, ctActions, "getStaminaModiferFor", replace);
|
|
||||||
|
|
||||||
Util.setReason("Increase movement speed for Path of Hate users.");
|
|
||||||
CtClass ctMovementScheme = classPool.get("com.wurmonline.server.creatures.MovementScheme");
|
CtClass ctMovementScheme = classPool.get("com.wurmonline.server.creatures.MovementScheme");
|
||||||
replace = "if($_ > 0){" +
|
|
||||||
" $_ = $_ * "+MeditationPerks.class.getName()+".getCultistSpeedMultiplier(this);" +
|
|
||||||
"}";
|
|
||||||
Util.insertAfterDeclared(thisClass, ctMovementScheme, "getSpeedModifier", replace);
|
|
||||||
|
|
||||||
Util.setReason("Scale path of power stamina bonus from level 7 onwards.");
|
|
||||||
CtClass ctCreatureStatus = classPool.get("com.wurmonline.server.creatures.CreatureStatus");
|
CtClass ctCreatureStatus = classPool.get("com.wurmonline.server.creatures.CreatureStatus");
|
||||||
replace = "staminaMod += "+MeditationPerks.class.getName()+".getPowerStaminaBonus(this.statusHolder);" +
|
|
||||||
"$_ = false;";
|
|
||||||
Util.instrumentDeclared(thisClass, ctCreatureStatus, "modifyStamina", "usesNoStamina", replace);
|
|
||||||
|
|
||||||
Util.setReason("Scale path of knowledge skill gain from level 7 onwards.");
|
|
||||||
CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill");
|
CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill");
|
||||||
|
|
||||||
|
if (WyvernMods.simplifyMeditationTerrain) {
|
||||||
|
Util.setReason("Make meditating paths more straightforward.");
|
||||||
|
replace = "{ return " + MeditationPerks.class.getName() + ".getNewPathFor($1, $2, $3); }";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCults, "getPathFor", replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WyvernMods.removeInsanitySotG) {
|
||||||
|
Util.setReason("Remove shield of the gone effect.");
|
||||||
|
replace = "{ return 0.0f; }";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "getHalfDamagePercentage", replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WyvernMods.removeHateWarBonus) {
|
||||||
|
Util.setReason("Remove hate war damage effect.");
|
||||||
|
replace = "{ return false; }";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace);
|
||||||
|
Util.setReason("Remove hate war damage effect.");
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "doubleWarDamage", replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WyvernMods.insanitySpeedBonus) {
|
||||||
|
Util.setReason("Replace stamina modifier for new Insanity ability.");
|
||||||
|
replace = "{ return " + MeditationPerks.class.getName() + ".newStaminaModifierFor($1, $2); }";
|
||||||
|
Util.setBodyDeclared(thisClass, ctActions, "getStaminaModiferFor", replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WyvernMods.hateMovementBonus) {
|
||||||
|
Util.setReason("Increase movement speed for Path of Hate users.");
|
||||||
|
replace = "if($_ > 0){" +
|
||||||
|
" $_ = $_ * " + MeditationPerks.class.getName() + ".getCultistSpeedMultiplier(this);" +
|
||||||
|
"}";
|
||||||
|
Util.insertAfterDeclared(thisClass, ctMovementScheme, "getSpeedModifier", replace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WyvernMods.scalingPowerStaminaBonus) {
|
||||||
|
Util.setReason("Scale path of power stamina bonus from level 7 onwards.");
|
||||||
|
replace = "staminaMod += " + MeditationPerks.class.getName() + ".getPowerStaminaBonus(this.statusHolder);" +
|
||||||
|
"$_ = false;";
|
||||||
|
Util.instrumentDeclared(thisClass, ctCreatureStatus, "modifyStamina", "usesNoStamina", replace);
|
||||||
|
}
|
||||||
|
|
||||||
CtClass[] params1 = {
|
CtClass[] params1 = {
|
||||||
CtClass.doubleType,
|
CtClass.doubleType,
|
||||||
CtClass.booleanType,
|
CtClass.booleanType,
|
||||||
@@ -194,57 +212,61 @@ public class MeditationPerks {
|
|||||||
CtClass.doubleType
|
CtClass.doubleType
|
||||||
};
|
};
|
||||||
String desc1 = Descriptor.ofMethod(CtClass.voidType, params1);
|
String desc1 = Descriptor.ofMethod(CtClass.voidType, params1);
|
||||||
replace = "staminaMod *= "+MeditationPerks.class.getName()+".getKnowledgeSkillGain(player);" +
|
|
||||||
"$_ = false;";
|
|
||||||
Util.instrumentDescribed(thisClass, ctSkill, "alterSkill", desc1, "levelElevenSkillgain", replace);
|
|
||||||
|
|
||||||
Util.setReason("Remove shield of the gone effect.");
|
if (WyvernMods.scalingKnowledgeSkillGain) {
|
||||||
replace = "{ return 0.0f; }";
|
Util.setReason("Scale path of knowledge skill gain from level 7 onwards.");
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "getHalfDamagePercentage", replace);
|
replace = "staminaMod *= " + MeditationPerks.class.getName() + ".getKnowledgeSkillGain(player);" +
|
||||||
Util.setReason("Remove hate war damage effect.");
|
"$_ = false;";
|
||||||
replace = "{ return false; }";
|
Util.instrumentDescribed(thisClass, ctSkill, "alterSkill", desc1, "levelElevenSkillgain", replace);
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace);
|
}
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "doubleWarDamage", replace);
|
|
||||||
|
|
||||||
Util.setReason("Remove artifical tick timer for meditation.");
|
if (WyvernMods.removeMeditationTickTimer) {
|
||||||
replace = "$_ = 0;";
|
Util.setReason("Remove artifical tick timer for meditation.");
|
||||||
Util.instrumentDeclared(thisClass, ctCults, "meditate", "getLastMeditated", replace);
|
replace = "$_ = 0;";
|
||||||
|
Util.instrumentDeclared(thisClass, ctCults, "meditate", "getLastMeditated", replace);
|
||||||
|
}
|
||||||
|
|
||||||
// - Reduce meditation cooldowns - //
|
if (WyvernMods.newMeditationBuffs) {
|
||||||
replace = "return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*8)+";";
|
Util.setReason("Enable buff icons for meditation.");
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayRefresh", replace);
|
replace = MeditationPerks.class.getName() + ".sendPassiveBuffs($0);";
|
||||||
//ctCultist.getDeclaredMethod("mayRefresh").setBody("return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > 28800000;");
|
Util.insertBeforeDeclared(thisClass, ctCultist, "sendPassiveBuffs", replace);
|
||||||
replace = "return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*8)+";";
|
}
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayEnchantNature", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("mayEnchantNature").setBody("return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 28800000;");
|
|
||||||
replace = "return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*4)+";";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayStartLoveEffect", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("mayStartLoveEffect").setBody("return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > 14400000;");
|
|
||||||
replace = "return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*6)+";";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("mayStartDoubleWarDamage").setBody("return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > 21600000;");
|
|
||||||
replace = "return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*4)+";";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleStructDamage", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("mayStartDoubleStructDamage").setBody("return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > 14400000;");
|
|
||||||
replace = "return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*6)+";";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayStartFearEffect", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("mayStartFearEffect").setBody("return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > 21600000;");
|
|
||||||
replace = "return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*6)+";";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayStartNoElementalDamage", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("mayStartNoElementalDamage").setBody("return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > 21600000;");
|
|
||||||
replace = "return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*8)+";";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "maySpawnVolcano", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("maySpawnVolcano").setBody("return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 28800000;");
|
|
||||||
replace = "return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*4)+";";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayStartIgnoreTraps", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("mayStartIgnoreTraps").setBody("return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > 14400000;");
|
|
||||||
replace = "return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*4)+";";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayCreatureInfo", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("mayCreatureInfo").setBody("return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > 14400000;");
|
|
||||||
replace = "return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*4)+";";
|
|
||||||
Util.setBodyDeclared(thisClass, ctCultist, "mayInfoLocal", replace);
|
|
||||||
//ctCultist.getDeclaredMethod("mayInfoLocal").setBody("return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 14400000;");
|
|
||||||
|
|
||||||
|
if (WyvernMods.enableMeditationAbilityCooldowns) {
|
||||||
|
// - Adjust meditation ability cooldowns - //
|
||||||
|
replace = "return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > " + String.valueOf(WyvernMods.loveRefreshCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayRefresh", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > " + String.valueOf(WyvernMods.loveEnchantNatureCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayEnchantNature", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > " + String.valueOf(WyvernMods.loveLoveEffectCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayStartLoveEffect", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > " + String.valueOf(WyvernMods.hateWarDamageCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > " + String.valueOf(WyvernMods.hateStructureDamageCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleStructDamage", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > " + String.valueOf(WyvernMods.hateFearCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayStartFearEffect", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > " + String.valueOf(WyvernMods.powerElementalImmunityCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayStartNoElementalDamage", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > " + String.valueOf(WyvernMods.powerEruptFreezeCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "maySpawnVolcano", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > " + String.valueOf(WyvernMods.powerIgnoreTrapsCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayStartIgnoreTraps", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > " + String.valueOf(WyvernMods.knowledgeInfoCreatureCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayCreatureInfo", replace);
|
||||||
|
|
||||||
|
replace = "return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > " + String.valueOf(WyvernMods.knowledgeInfoTileCooldown) + ";";
|
||||||
|
Util.setBodyDeclared(thisClass, ctCultist, "mayInfoLocal", replace);
|
||||||
|
}
|
||||||
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
|
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
|
||||||
throw new HookException(e);
|
throw new HookException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,23 +23,6 @@ public class PlayerTitles {
|
|||||||
// Event Title ID's
|
// Event Title ID's
|
||||||
public static int TITAN_SLAYER = 10000;
|
public static int TITAN_SLAYER = 10000;
|
||||||
public static int SPECTRAL = 10001;
|
public static int SPECTRAL = 10001;
|
||||||
//public static int PASTAMANCER = 10002;
|
|
||||||
|
|
||||||
// Player Donation Title ID's
|
|
||||||
/*public static int PATRON = 19999;
|
|
||||||
public static int DONATOR = 20000;
|
|
||||||
public static int PAZZA_FAVORITE_GM = 20001;
|
|
||||||
public static int WARRIORGEN_THAT_GUY = 20002;
|
|
||||||
public static int ETERNALLOVE_WARRIORGENS_WIFE = 20003;
|
|
||||||
public static int BAMBAM_THORN_ONE = 20004;
|
|
||||||
public static int SVENJA_CARE_DEPENDANT = 20005;
|
|
||||||
public static int ALEXIA_THE_TREASURING = 20006;
|
|
||||||
public static int REEVI_SCIENCE_GUY = 20007;
|
|
||||||
public static int GENOCIDE_GRAND_DESIGNER = 20008;
|
|
||||||
public static int SELEAS_CRAZY_CAT_LORD = 20009;
|
|
||||||
public static int PIRATEMAX_SLAVE = 20010;
|
|
||||||
public static int ELTACOLAD_TRUE_TACO = 20011;
|
|
||||||
public static int ATTICUS_THE_GREAT_ILLUMINATY = 20012;*/
|
|
||||||
|
|
||||||
public static void init(){
|
public static void init(){
|
||||||
for (WyvernMods.CustomTitle title : WyvernMods.customTitles){
|
for (WyvernMods.CustomTitle title : WyvernMods.customTitles){
|
||||||
@@ -48,28 +31,8 @@ public class PlayerTitles {
|
|||||||
// Event Titles
|
// Event Titles
|
||||||
createTitle(TITAN_SLAYER, "Titanslayer", "Titanslayer", -1, "NORMAL");
|
createTitle(TITAN_SLAYER, "Titanslayer", "Titanslayer", -1, "NORMAL");
|
||||||
createTitle(SPECTRAL, "Spectral", "Spectral", -1, "NORMAL");
|
createTitle(SPECTRAL, "Spectral", "Spectral", -1, "NORMAL");
|
||||||
//PlayerTitles.createTitle(buster, "Holdstrong_Architect", 702, "Holdstrong Architect", "Holdstrong Architect", -1, Titles.TitleType.NORMAL);
|
|
||||||
//PlayerTitles.createTitle(buster, "Stronghold_Architect", 703, "Stronghold Architect", "Stronghold Architect", -1, Titles.TitleType.NORMAL);
|
|
||||||
//createTitle(PASTAMANCER, "Pastamancer", "Pastamancer", -1, "NORMAL");
|
|
||||||
|
|
||||||
// Donation Titles
|
// Display all existing titles
|
||||||
/* Moved to configuration
|
|
||||||
createTitle(PATRON, "Patron", "Patron", -1, "NORMAL");
|
|
||||||
createTitle(DONATOR, "Donator", "Donator", -1, "NORMAL");
|
|
||||||
createTitle(PAZZA_FAVORITE_GM, "Sindusks Favourite GM", "Sindusks Favourite GM", -1, "NORMAL");
|
|
||||||
createTitle(WARRIORGEN_THAT_GUY, "That Guy", "That Guy", -1, "NORMAL");
|
|
||||||
createTitle(ETERNALLOVE_WARRIORGENS_WIFE, "Warriorgens Wife", "Warriorgens Wife", -1, "NORMAL");
|
|
||||||
createTitle(BAMBAM_THORN_ONE, "Thorn One", "Thorn One", -1, "NORMAL");
|
|
||||||
createTitle(SVENJA_CARE_DEPENDANT, "The care-dependent", "The care-dependent", -1, "NORMAL");
|
|
||||||
createTitle(ALEXIA_THE_TREASURING, "The Treasuring", "The Treasuring", -1, "NORMAL");
|
|
||||||
createTitle(REEVI_SCIENCE_GUY, "Science Guy", "Science Guy", -1, "NORMAL");
|
|
||||||
createTitle(GENOCIDE_GRAND_DESIGNER, "Grand Designer", "Grand Designer", -1, "NORMAL");
|
|
||||||
createTitle(SELEAS_CRAZY_CAT_LORD, "The Crazy Cat Lord", "The Crazy Cat Lord", -1, "NORMAL");
|
|
||||||
createTitle(PIRATEMAX_SLAVE, "Slave", "Slave", -1, "NORMAL");
|
|
||||||
createTitle(ELTACOLAD_TRUE_TACO, "The One True Taco", "The One True Taco", -1, "NORMAL");
|
|
||||||
createTitle(ATTICUS_THE_GREAT_ILLUMINATY, "The Great Illuminaty", "The Great Illuminaty", -1, "NORMAL");*/
|
|
||||||
|
|
||||||
// Supporter titles
|
|
||||||
logger.info(Arrays.toString(Titles.Title.values()));
|
logger.info(Arrays.toString(Titles.Title.values()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,61 +68,5 @@ public class PlayerTitles {
|
|||||||
logger.warning("Failed to get title with ID "+titleId);
|
logger.warning("Failed to get title with ID "+titleId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*if(donatorTitles.contains(name)){
|
|
||||||
Titles.Title donator = Titles.Title.getTitle(DONATOR);
|
|
||||||
p.addTitle(donator);
|
|
||||||
}
|
|
||||||
if(patronTitles.contains(name)){
|
|
||||||
Titles.Title patron = Titles.Title.getTitle(PATRON);
|
|
||||||
p.addTitle(patron);
|
|
||||||
}
|
|
||||||
if(customTitles.containsKey(name)){
|
|
||||||
Titles.Title customTitle = Titles.Title.getTitle(customTitles.get(name));
|
|
||||||
p.addTitle(customTitle);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
public static void preInit(){
|
|
||||||
// Donations
|
|
||||||
/*donatorTitles.add("Pazza");
|
|
||||||
customTitles.put("Pazza", PAZZA_FAVORITE_GM); // Sindusks Favorite GM
|
|
||||||
|
|
||||||
donatorTitles.add("Warriorgen");
|
|
||||||
customTitles.put("Warriorgen", WARRIORGEN_THAT_GUY); // That Guy
|
|
||||||
|
|
||||||
donatorTitles.add("Eternallove");
|
|
||||||
customTitles.put("Eternallove", ETERNALLOVE_WARRIORGENS_WIFE); // Warriorgens Wife
|
|
||||||
|
|
||||||
donatorTitles.add("Bambam");
|
|
||||||
customTitles.put("Bambam", BAMBAM_THORN_ONE); // Thorn One
|
|
||||||
|
|
||||||
donatorTitles.add("Svenja");
|
|
||||||
customTitles.put("Svenja", SVENJA_CARE_DEPENDANT); // The care-dependent
|
|
||||||
playerTitles.put("Svenja", "Akuma");
|
|
||||||
|
|
||||||
donatorTitles.add("Alexiaselena");
|
|
||||||
customTitles.put("Alexiaselena", ALEXIA_THE_TREASURING); // The Treasuring
|
|
||||||
playerTitles.put("Alexiaselena", "Kami");
|
|
||||||
|
|
||||||
donatorTitles.add("Reevi");
|
|
||||||
customTitles.put("Reevi", REEVI_SCIENCE_GUY); // Science Guy
|
|
||||||
|
|
||||||
customTitles.put("Genocide", GENOCIDE_GRAND_DESIGNER); // Grand Designer
|
|
||||||
|
|
||||||
donatorTitles.add("Seleas");
|
|
||||||
customTitles.put("Seleas", SELEAS_CRAZY_CAT_LORD); // The Crazy Cat Lord
|
|
||||||
playerTitles.put("Seleas", "No, Really");
|
|
||||||
|
|
||||||
donatorTitles.add("Piratemax");
|
|
||||||
customTitles.put("Piratemax", PIRATEMAX_SLAVE); // Slave
|
|
||||||
playerTitles.put("Piratemax", "Boy Next Door");
|
|
||||||
|
|
||||||
donatorTitles.add("Eltacolad");
|
|
||||||
customTitles.put("Eltacolad", ELTACOLAD_TRUE_TACO); // The One True Taco
|
|
||||||
|
|
||||||
patronTitles.add("Atticus");
|
|
||||||
customTitles.put("Atticus", ATTICUS_THE_GREAT_ILLUMINATY); // The Great Illuminaty
|
|
||||||
|
|
||||||
// Other rewards
|
|
||||||
customTitles.put("Critias", PASTAMANCER);*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ public class SkillChanges {
|
|||||||
try {
|
try {
|
||||||
Skills parent = ReflectionUtil.getPrivateField(skill, ReflectionUtil.getField(skill.getClass(), "parent"));
|
Skills parent = ReflectionUtil.getPrivateField(skill, ReflectionUtil.getField(skill.getClass(), "parent"));
|
||||||
double advanceMultiplicator = (100.0 - skill.getKnowledge()) / (skill.getDifficulty(parent.priest) * skill.getKnowledge() * skill.getKnowledge()) * learnMod * bonus;
|
double advanceMultiplicator = (100.0 - skill.getKnowledge()) / (skill.getDifficulty(parent.priest) * skill.getKnowledge() * skill.getKnowledge()) * learnMod * bonus;
|
||||||
double negativeDecayRate = 5;
|
double negativeDecayRate = (double) WyvernMods.hybridNegativeDecayRate;
|
||||||
double positiveDecayRate = 3;
|
double positiveDecayRate = (double) WyvernMods.hybridPositiveDecayRate;
|
||||||
double valueAtZero = 3.74d;
|
double valueAtZero = (double) WyvernMods.hybridValueAtZero;
|
||||||
double valueAtOneHundred = 0.9d;
|
double valueAtOneHundred = (double) WyvernMods.hybridValueAtOneHundred;
|
||||||
//advanceMultiplicator *= Math.pow(2, ((2-Math.pow((100/(100+power)), p))*(100-power)/100));
|
//advanceMultiplicator *= Math.pow(2, ((2-Math.pow((100/(100+power)), p))*(100-power)/100));
|
||||||
//double mult = Math.pow(2, (2-Math.pow(100/(100+power), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate));
|
//double mult = Math.pow(2, (2-Math.pow(100/(100+power), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate));
|
||||||
double mult = valueAtOneHundred*Math.pow(valueAtZero/valueAtOneHundred, (2-Math.pow(100/(100+Math.max(-99,power)), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate));
|
double mult = valueAtOneHundred*Math.pow(valueAtZero/valueAtOneHundred, (2-Math.pow(100/(100+Math.max(-99,power)), negativeDecayRate))*Math.pow((100-power)*0.01, positiveDecayRate));
|
||||||
@@ -65,65 +65,52 @@ public class SkillChanges {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onServerStarted(){
|
public static void setSkillName(int id, String newName){
|
||||||
/*SkillTemplate exorcism = SkillSystem.templates.get(SkillList.EXORCISM);
|
SkillTemplate skillTemplate = SkillSystem.templates.get(id);
|
||||||
int[] deps = {SkillList.GROUP_ALCHEMY};
|
|
||||||
try {
|
try {
|
||||||
String newName = "Crystal handling";
|
ReflectionUtil.setPrivateField(skillTemplate, ReflectionUtil.getField(skillTemplate.getClass(), "name"), newName);
|
||||||
ReflectionUtil.setPrivateField(exorcism, ReflectionUtil.getField(exorcism.getClass(), "name"), newName);
|
SkillSystem.skillNames.put(skillTemplate.getNumber(), newName);
|
||||||
SkillSystem.skillNames.put(exorcism.getNumber(), newName);
|
SkillSystem.namesToSkill.put(newName, skillTemplate.getNumber());
|
||||||
SkillSystem.namesToSkill.put(newName, exorcism.getNumber());
|
|
||||||
ReflectionUtil.setPrivateField(exorcism, ReflectionUtil.getField(exorcism.getClass(), "dependencies"), deps);
|
|
||||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||||
logger.info("Failed to rename exorcism!");
|
logger.info("Failed to rename skill with ID "+id+"!");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
SkillTemplate ballistae = SkillSystem.templates.get(SkillList.BALLISTA);
|
}
|
||||||
int[] deps2 = {SkillList.GROUP_ALCHEMY};
|
public static void setSkillDifficulty(int id, float difficulty){
|
||||||
|
SkillTemplate skillTemplate = SkillSystem.templates.get(id);
|
||||||
|
skillTemplate.setDifficulty(difficulty);
|
||||||
|
}
|
||||||
|
public static void setSkillTickTime(int id, long tickTime){
|
||||||
|
SkillTemplate skillTemplate = SkillSystem.templates.get(id);
|
||||||
try {
|
try {
|
||||||
String newName = "Mystic components";
|
ReflectionUtil.setPrivateField(skillTemplate, ReflectionUtil.getField(skillTemplate.getClass(), "tickTime"), tickTime);
|
||||||
ReflectionUtil.setPrivateField(ballistae, ReflectionUtil.getField(ballistae.getClass(), "name"), newName);
|
|
||||||
SkillSystem.skillNames.put(ballistae.getNumber(), newName);
|
|
||||||
SkillSystem.namesToSkill.put(newName, ballistae.getNumber());
|
|
||||||
ReflectionUtil.setPrivateField(ballistae, ReflectionUtil.getField(ballistae.getClass(), "dependencies"), deps2);
|
|
||||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||||
logger.info("Failed to rename ballistae!");
|
logger.info("Failed to set tickTime for skill with ID "+id+"!");
|
||||||
e.printStackTrace();
|
|
||||||
}*/
|
|
||||||
SkillTemplate preaching = SkillSystem.templates.get(SkillList.PREACHING);
|
|
||||||
int[] deps3 = {SkillList.MASONRY};
|
|
||||||
try {
|
|
||||||
String newName = "Gem augmentation";
|
|
||||||
ReflectionUtil.setPrivateField(preaching, ReflectionUtil.getField(preaching.getClass(), "name"), newName);
|
|
||||||
SkillSystem.skillNames.put(preaching.getNumber(), newName);
|
|
||||||
SkillSystem.namesToSkill.put(newName, preaching.getNumber());
|
|
||||||
ReflectionUtil.setPrivateField(preaching, ReflectionUtil.getField(preaching.getClass(), "dependencies"), deps3);
|
|
||||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
|
||||||
logger.info("Failed to rename preaching!");
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
SkillTemplate stealing = SkillSystem.templates.get(SkillList.STEALING);
|
}
|
||||||
try {
|
|
||||||
ReflectionUtil.setPrivateField(stealing, ReflectionUtil.getField(stealing.getClass(), "tickTime"), 0);
|
|
||||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
|
||||||
logger.info("Failed to set tickTime for stealing!");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
SkillTemplate meditating = SkillSystem.templates.get(SkillList.MEDITATING);
|
|
||||||
try {
|
|
||||||
ReflectionUtil.setPrivateField(meditating, ReflectionUtil.getField(meditating.getClass(), "tickTime"), TimeConstants.HOUR_MILLIS);
|
|
||||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
|
||||||
logger.info("Failed to set tickTime for meditating!");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
meditating.setDifficulty(300f);
|
|
||||||
|
|
||||||
// Set mining difficulty down to be equivalent to digging.
|
public static void onServerStarted(){
|
||||||
SkillTemplate mining = SkillSystem.templates.get(SkillList.MINING);
|
for (int skillId : WyvernMods.skillName.keySet()){
|
||||||
mining.setDifficulty(3000f);
|
setSkillName(skillId, WyvernMods.skillName.get(skillId));
|
||||||
// Triple lockpicking skill
|
}
|
||||||
SkillTemplate lockpicking = SkillSystem.templates.get(SkillList.LOCKPICKING);
|
for (int skillId : WyvernMods.skillDifficulty.keySet()){
|
||||||
lockpicking.setDifficulty(700f);
|
setSkillDifficulty(skillId, WyvernMods.skillDifficulty.get(skillId));
|
||||||
|
}
|
||||||
|
for (int skillId : WyvernMods.skillTickTime.keySet()){
|
||||||
|
setSkillTickTime(skillId, WyvernMods.skillTickTime.get(skillId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WyvernMods.changePreachingLocation) {
|
||||||
|
SkillTemplate preaching = SkillSystem.templates.get(SkillList.PREACHING);
|
||||||
|
int[] deps3 = {SkillList.MASONRY};
|
||||||
|
try {
|
||||||
|
ReflectionUtil.setPrivateField(preaching, ReflectionUtil.getField(preaching.getClass(), "dependencies"), deps3);
|
||||||
|
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||||
|
logger.info("Failed to rename preaching!");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void preInit(){
|
public static void preInit(){
|
||||||
@@ -132,13 +119,15 @@ public class SkillChanges {
|
|||||||
final Class<SkillChanges> thisClass = SkillChanges.class;
|
final Class<SkillChanges> thisClass = SkillChanges.class;
|
||||||
String replace;
|
String replace;
|
||||||
|
|
||||||
Util.setReason("Allow skill check failures to add skill gain.");
|
if (WyvernMods.enableHybridSkillGain) {
|
||||||
CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill");
|
Util.setReason("Add hybrid skill gain system hook.");
|
||||||
replace = "{" +
|
CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill");
|
||||||
" double advanceMultiplicator = "+SkillChanges.class.getName()+".newDoSkillGainNew($0, $1, $2, $3, $4, $5);" +
|
replace = "{" +
|
||||||
" $0.alterSkill(advanceMultiplicator, false, $4, true, $5);" +
|
" double advanceMultiplicator = " + SkillChanges.class.getName() + ".newDoSkillGainNew($0, $1, $2, $3, $4, $5);" +
|
||||||
"}";
|
" $0.alterSkill(advanceMultiplicator, false, $4, true, $5);" +
|
||||||
Util.setBodyDeclared(thisClass, ctSkill, "doSkillGainNew", replace);
|
"}";
|
||||||
|
Util.setBodyDeclared(thisClass, ctSkill, "doSkillGainNew", replace);
|
||||||
|
}
|
||||||
|
|
||||||
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
|
} catch ( NotFoundException | IllegalArgumentException | ClassCastException e) {
|
||||||
throw new HookException(e);
|
throw new HookException(e);
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ import mod.sin.actions.items.SorcerySplitAction;
|
|||||||
import mod.sin.creatures.*;
|
import mod.sin.creatures.*;
|
||||||
import mod.sin.creatures.titans.*;
|
import mod.sin.creatures.titans.*;
|
||||||
import mod.sin.lib.Prop;
|
import mod.sin.lib.Prop;
|
||||||
|
import mod.sin.lib.SkillAssist;
|
||||||
import mod.sin.lib.Util;
|
import mod.sin.lib.Util;
|
||||||
import mod.sin.wyvern.bestiary.MethodsBestiary;
|
import mod.sin.wyvern.bestiary.MethodsBestiary;
|
||||||
import mod.sin.wyvern.mastercraft.Mastercraft;
|
|
||||||
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
|
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
|
||||||
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
|
import org.gotti.wurmunlimited.modloader.classhooks.HookException;
|
||||||
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
|
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
|
||||||
@@ -161,6 +161,65 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
public static boolean mineGemsToVehicle = true;
|
public static boolean mineGemsToVehicle = true;
|
||||||
public static boolean regenerateStaminaOnVehicleAnySlope = true;
|
public static boolean regenerateStaminaOnVehicleAnySlope = true;
|
||||||
|
|
||||||
|
// Combat Module Configuration
|
||||||
|
public static boolean enableCombatModule = true;
|
||||||
|
public static boolean enableCombatRatingAdjustments = true;
|
||||||
|
public static boolean royalExecutionerBonus = true;
|
||||||
|
public static boolean petSoulDepthScaling = true;
|
||||||
|
public static boolean vehicleCombatRatingPenalty = true;
|
||||||
|
public static boolean fixMagranonDamageStacking = true;
|
||||||
|
public static boolean adjustCombatRatingSpellPower = true;
|
||||||
|
public static boolean disableLegendaryRegeneration = true;
|
||||||
|
public static boolean useStaticLegendaryRegeneration = true;
|
||||||
|
|
||||||
|
// Mastercraft Module Configuration
|
||||||
|
public static boolean enableMastercraftModule = true;
|
||||||
|
public static boolean enableDifficultyAdjustments = true;
|
||||||
|
public static boolean affinityDifficultyBonus = true;
|
||||||
|
public static boolean legendDifficultyBonus = true;
|
||||||
|
public static boolean masterDifficultyBonus = true;
|
||||||
|
public static boolean itemRarityDifficultyBonus = true;
|
||||||
|
public static boolean legendItemDifficultyBonus = true;
|
||||||
|
public static boolean masterItemDifficultyBonus = true;
|
||||||
|
public static boolean empoweredChannelers = true;
|
||||||
|
public static boolean channelSkillFavorReduction = true;
|
||||||
|
|
||||||
|
// Skill Module Configuration
|
||||||
|
public static boolean enableSkillModule = true;
|
||||||
|
public static boolean enableHybridSkillGain = true;
|
||||||
|
public static float hybridNegativeDecayRate = 5f;
|
||||||
|
public static float hybridPositiveDecayRate = 3f;
|
||||||
|
public static float hybridValueAtZero = 3.74f;
|
||||||
|
public static float hybridValueAtOneHundred = 0.9f;
|
||||||
|
public static HashMap<Integer,String> skillName = new HashMap<>();
|
||||||
|
public static HashMap<Integer,Float> skillDifficulty = new HashMap<>();
|
||||||
|
public static HashMap<Integer,Long> skillTickTime = new HashMap<>();
|
||||||
|
public static boolean changePreachingLocation = true;
|
||||||
|
|
||||||
|
// Meditation Module Configuration
|
||||||
|
public static boolean enableMeditationModule = true;
|
||||||
|
public static boolean simplifyMeditationTerrain = true;
|
||||||
|
public static boolean removeInsanitySotG = true;
|
||||||
|
public static boolean removeHateWarBonus = true;
|
||||||
|
public static boolean insanitySpeedBonus = true;
|
||||||
|
public static boolean hateMovementBonus = true;
|
||||||
|
public static boolean scalingPowerStaminaBonus = true;
|
||||||
|
public static boolean scalingKnowledgeSkillGain = true;
|
||||||
|
public static boolean removeMeditationTickTimer = true;
|
||||||
|
public static boolean newMeditationBuffs = true;
|
||||||
|
public static boolean enableMeditationAbilityCooldowns = true;
|
||||||
|
public static long loveRefreshCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long loveEnchantNatureCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long loveLoveEffectCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long hateWarDamageCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long hateStructureDamageCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long hateFearCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long powerElementalImmunityCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long powerEruptFreezeCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long powerIgnoreTrapsCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long knowledgeInfoCreatureCooldown = 64800000L; // 18 hours default
|
||||||
|
public static long knowledgeInfoTileCooldown = 64800000L; // 18 hours default
|
||||||
|
|
||||||
// Treasure Chest Loot Module Configuration
|
// Treasure Chest Loot Module Configuration
|
||||||
public static boolean enableTreasureChestLootModule = true;
|
public static boolean enableTreasureChestLootModule = true;
|
||||||
|
|
||||||
@@ -345,6 +404,62 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
mineGemsToVehicle = Prop.getBooleanProperty("mineGemsToVehicle", mineGemsToVehicle);
|
mineGemsToVehicle = Prop.getBooleanProperty("mineGemsToVehicle", mineGemsToVehicle);
|
||||||
regenerateStaminaOnVehicleAnySlope = Prop.getBooleanProperty("regenerateStaminaOnVehicleAnySlope", regenerateStaminaOnVehicleAnySlope);
|
regenerateStaminaOnVehicleAnySlope = Prop.getBooleanProperty("regenerateStaminaOnVehicleAnySlope", regenerateStaminaOnVehicleAnySlope);
|
||||||
|
|
||||||
|
// Combat Module
|
||||||
|
enableCombatModule = Prop.getBooleanProperty("enableCombatModule", enableCombatModule);
|
||||||
|
enableCombatRatingAdjustments = Prop.getBooleanProperty("enableCombatRatingAdjustments", enableCombatRatingAdjustments);
|
||||||
|
royalExecutionerBonus = Prop.getBooleanProperty("royalExecutionerBonus", royalExecutionerBonus);
|
||||||
|
petSoulDepthScaling = Prop.getBooleanProperty("petSoulDepthScaling", petSoulDepthScaling);
|
||||||
|
vehicleCombatRatingPenalty = Prop.getBooleanProperty("vehicleCombatRatingPenalty", vehicleCombatRatingPenalty);
|
||||||
|
fixMagranonDamageStacking = Prop.getBooleanProperty("fixMagranonDamageStacking", fixMagranonDamageStacking);
|
||||||
|
adjustCombatRatingSpellPower = Prop.getBooleanProperty("adjustCombatRatingSpellPower", adjustCombatRatingSpellPower);
|
||||||
|
disableLegendaryRegeneration = Prop.getBooleanProperty("disableLegendaryRegeneration", disableLegendaryRegeneration);
|
||||||
|
useStaticLegendaryRegeneration = Prop.getBooleanProperty("useStaticLegendaryRegeneration", useStaticLegendaryRegeneration);
|
||||||
|
|
||||||
|
// Mastercraft Module
|
||||||
|
enableMastercraftModule = Prop.getBooleanProperty("enableMastercraftModule", enableMastercraftModule);
|
||||||
|
enableDifficultyAdjustments = Prop.getBooleanProperty("enableDifficultyAdjustments", enableDifficultyAdjustments);
|
||||||
|
affinityDifficultyBonus = Prop.getBooleanProperty("affinityDifficultyBonus", affinityDifficultyBonus);
|
||||||
|
legendDifficultyBonus = Prop.getBooleanProperty("legendDifficultyBonus", legendDifficultyBonus);
|
||||||
|
masterDifficultyBonus = Prop.getBooleanProperty("masterDifficultyBonus", masterDifficultyBonus);
|
||||||
|
itemRarityDifficultyBonus = Prop.getBooleanProperty("itemRarityDifficultyBonus", itemRarityDifficultyBonus);
|
||||||
|
legendItemDifficultyBonus = Prop.getBooleanProperty("legendItemDifficultyBonus", legendItemDifficultyBonus);
|
||||||
|
masterItemDifficultyBonus = Prop.getBooleanProperty("masterItemDifficultyBonus", masterItemDifficultyBonus);
|
||||||
|
empoweredChannelers = Prop.getBooleanProperty("empoweredChannelers", empoweredChannelers);
|
||||||
|
channelSkillFavorReduction = Prop.getBooleanProperty("channelSkillFavorReduction", channelSkillFavorReduction);
|
||||||
|
|
||||||
|
// Skill Module
|
||||||
|
enableSkillModule = Prop.getBooleanProperty("enableSkillModule", enableSkillModule);
|
||||||
|
enableHybridSkillGain = Prop.getBooleanProperty("enableHybridSkillGain", enableHybridSkillGain);
|
||||||
|
hybridNegativeDecayRate = Prop.getFloatProperty("hybridNegativeDecayRate", hybridNegativeDecayRate);
|
||||||
|
hybridPositiveDecayRate = Prop.getFloatProperty("hybridPositiveDecayRate", hybridPositiveDecayRate);
|
||||||
|
hybridValueAtZero = Prop.getFloatProperty("hybridValueAtZero", hybridValueAtZero);
|
||||||
|
hybridValueAtOneHundred = Prop.getFloatProperty("hybridValueAtOneHundred", hybridValueAtOneHundred);
|
||||||
|
changePreachingLocation = Prop.getBooleanProperty("changePreachingLocation", changePreachingLocation);
|
||||||
|
|
||||||
|
// Meditation Module
|
||||||
|
enableMeditationModule = Prop.getBooleanProperty("enableMeditationModule", enableMeditationModule);
|
||||||
|
simplifyMeditationTerrain = Prop.getBooleanProperty("simplifyMeditationTerrain", simplifyMeditationTerrain);
|
||||||
|
removeInsanitySotG = Prop.getBooleanProperty("removeInsanitySotG", removeInsanitySotG);
|
||||||
|
removeHateWarBonus = Prop.getBooleanProperty("removeHateWarBonus", removeHateWarBonus);
|
||||||
|
insanitySpeedBonus = Prop.getBooleanProperty("insanitySpeedBonus", insanitySpeedBonus);
|
||||||
|
hateMovementBonus = Prop.getBooleanProperty("hateMovementBonus", hateMovementBonus);
|
||||||
|
scalingPowerStaminaBonus = Prop.getBooleanProperty("scalingPowerStaminaBonus", scalingPowerStaminaBonus);
|
||||||
|
scalingKnowledgeSkillGain = Prop.getBooleanProperty("scalingKnowledgeSkillGain", scalingKnowledgeSkillGain);
|
||||||
|
removeMeditationTickTimer = Prop.getBooleanProperty("removeMeditationTickTimer", removeMeditationTickTimer);
|
||||||
|
newMeditationBuffs = Prop.getBooleanProperty("newMeditationBuffs", newMeditationBuffs);
|
||||||
|
enableMeditationAbilityCooldowns = Prop.getBooleanProperty("enableMeditationAbilityCooldowns", enableMeditationAbilityCooldowns);
|
||||||
|
loveRefreshCooldown = Prop.getLongProperty("loveRefreshCooldown", loveRefreshCooldown);
|
||||||
|
loveEnchantNatureCooldown = Prop.getLongProperty("loveEnchantNatureCooldown", loveEnchantNatureCooldown);
|
||||||
|
loveLoveEffectCooldown = Prop.getLongProperty("loveLoveEffectCooldown", loveLoveEffectCooldown);
|
||||||
|
hateWarDamageCooldown = Prop.getLongProperty("hateWarDamageCooldown", hateWarDamageCooldown);
|
||||||
|
hateStructureDamageCooldown = Prop.getLongProperty("hateStructureDamageCooldown", hateStructureDamageCooldown);
|
||||||
|
hateFearCooldown = Prop.getLongProperty("hateFearCooldown", hateFearCooldown);
|
||||||
|
powerElementalImmunityCooldown = Prop.getLongProperty("powerElementalImmunityCooldown", powerElementalImmunityCooldown);
|
||||||
|
powerEruptFreezeCooldown = Prop.getLongProperty("powerEruptFreezeCooldown", powerEruptFreezeCooldown);
|
||||||
|
powerIgnoreTrapsCooldown = Prop.getLongProperty("powerIgnoreTrapsCooldown", powerIgnoreTrapsCooldown);
|
||||||
|
knowledgeInfoCreatureCooldown = Prop.getLongProperty("knowledgeInfoCreatureCooldown", knowledgeInfoCreatureCooldown);
|
||||||
|
knowledgeInfoTileCooldown = Prop.getLongProperty("knowledgeInfoTileCooldown", knowledgeInfoTileCooldown);
|
||||||
|
|
||||||
// Treasure Chest Loot Module
|
// Treasure Chest Loot Module
|
||||||
enableTreasureChestLootModule = Prop.getBooleanProperty("enableTreasureChestLootModule", enableTreasureChestLootModule);
|
enableTreasureChestLootModule = Prop.getBooleanProperty("enableTreasureChestLootModule", enableTreasureChestLootModule);
|
||||||
|
|
||||||
@@ -398,6 +513,51 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
awardTitles.put(titleId, playerList);
|
awardTitles.put(titleId, playerList);
|
||||||
|
}else if (name.startsWith("skillName")) {
|
||||||
|
String[] values = value.split(",");
|
||||||
|
if(values.length < 2 || values.length > 2){
|
||||||
|
logger.warning("Error parsing Skill Name: Invalid amount of arguments for following property: "+value);
|
||||||
|
}
|
||||||
|
int skillId = SkillAssist.getSkill(values[0]);
|
||||||
|
if (skillId < 0){
|
||||||
|
skillId = Integer.parseInt(values[0]);
|
||||||
|
}
|
||||||
|
if (skillName.containsKey(skillId)){
|
||||||
|
logger.warning("Duplicate skill name configurations for skill id "+skillId);
|
||||||
|
}else{
|
||||||
|
String newName = values[1];
|
||||||
|
skillName.put(skillId, newName);
|
||||||
|
}
|
||||||
|
}else if (name.startsWith("skillDifficulty")) {
|
||||||
|
String[] values = value.split(",");
|
||||||
|
if(values.length < 2 || values.length > 2){
|
||||||
|
logger.warning("Error parsing Skill Difficulty: Invalid amount of arguments for following property: "+value);
|
||||||
|
}
|
||||||
|
int skillId = SkillAssist.getSkill(values[0]);
|
||||||
|
if (skillId < 0){
|
||||||
|
skillId = Integer.parseInt(values[0]);
|
||||||
|
}
|
||||||
|
if (skillDifficulty.containsKey(skillId)){
|
||||||
|
logger.warning("Duplicate difficulty configurations for skill id "+skillId);
|
||||||
|
}else{
|
||||||
|
float difficulty = Float.parseFloat(values[1]);
|
||||||
|
skillDifficulty.put(skillId, difficulty);
|
||||||
|
}
|
||||||
|
}else if (name.startsWith("skillTickTime")) {
|
||||||
|
String[] values = value.split(",");
|
||||||
|
if(values.length < 2 || values.length > 2){
|
||||||
|
logger.warning("Error parsing Skill Tick Time: Invalid amount of arguments for following property: "+value);
|
||||||
|
}
|
||||||
|
int skillId = SkillAssist.getSkill(values[0]);
|
||||||
|
if (skillId < 0){
|
||||||
|
skillId = Integer.parseInt(values[0]);
|
||||||
|
}
|
||||||
|
if (skillTickTime.containsKey(skillId)){
|
||||||
|
logger.warning("Duplicate tick time configurations for skill id "+skillId);
|
||||||
|
}else{
|
||||||
|
long difficulty = Long.parseLong(values[1]);
|
||||||
|
skillTickTime.put(skillId, difficulty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -545,6 +705,86 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
logger.info("Regenerate Stamina On Vehicle Any Slope: "+regenerateStaminaOnVehicleAnySlope);
|
logger.info("Regenerate Stamina On Vehicle Any Slope: "+regenerateStaminaOnVehicleAnySlope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info("Combat Module: "+enableCombatModule);
|
||||||
|
if (enableCombatModule){
|
||||||
|
logger.info("Combat Rating Adjustments: "+enableCombatRatingAdjustments);
|
||||||
|
if (enableCombatRatingAdjustments){
|
||||||
|
logger.info("Royal Executioner Bonus: "+royalExecutionerBonus);
|
||||||
|
logger.info("Pet Soul Depth Scaling: "+petSoulDepthScaling);
|
||||||
|
logger.info("Vehicle Combat Rating Penalty: "+vehicleCombatRatingPenalty);
|
||||||
|
}
|
||||||
|
logger.info("Fix Magranon Damage Stacking: "+fixMagranonDamageStacking);
|
||||||
|
logger.info("Adjust Combat Rating Spell Power: "+adjustCombatRatingSpellPower);
|
||||||
|
logger.info("Disable Legendary Regeneration: "+disableLegendaryRegeneration);
|
||||||
|
logger.info("Use Static Legendary Regeneration: "+useStaticLegendaryRegeneration);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Mastercraft Module: "+enableMastercraftModule);
|
||||||
|
if (enableMastercraftModule){
|
||||||
|
logger.info("Difficulty Adjustments: "+enableDifficultyAdjustments);
|
||||||
|
if (enableDifficultyAdjustments){
|
||||||
|
logger.info("Affinity Difficulty Bonus: "+affinityDifficultyBonus);
|
||||||
|
logger.info("Legend Difficulty Bonus: "+legendDifficultyBonus);
|
||||||
|
logger.info("Master Difficulty Bonus: "+masterDifficultyBonus);
|
||||||
|
logger.info("Item Rarity Difficulty Bonus: "+itemRarityDifficultyBonus);
|
||||||
|
logger.info("Legend Item Difficulty Bonus: "+legendItemDifficultyBonus);
|
||||||
|
logger.info("Master Item Difficulty Bonus: "+masterItemDifficultyBonus);
|
||||||
|
}
|
||||||
|
logger.info("Empowered Channelers: "+empoweredChannelers);
|
||||||
|
logger.info("Channel Skill Favor Reduction: "+channelSkillFavorReduction);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Skill Module: "+enableSkillModule);
|
||||||
|
if (enableSkillModule){
|
||||||
|
logger.info("Hybrid Skill Gain: "+enableHybridSkillGain);
|
||||||
|
if (enableHybridSkillGain){
|
||||||
|
logger.info("Hybrid Negative Decay Rate: "+hybridNegativeDecayRate);
|
||||||
|
logger.info("Hybrid Positive Decay Rate: "+hybridPositiveDecayRate);
|
||||||
|
logger.info("Hybrid Value At Zero: "+hybridValueAtZero);
|
||||||
|
logger.info("Hybrid Value At One Hundred: "+hybridValueAtOneHundred);
|
||||||
|
}
|
||||||
|
for (int skillId : skillName.keySet()){
|
||||||
|
logger.info(String.format("Changing name of skill %s to %s.",
|
||||||
|
SkillAssist.getSkill(skillId), skillName.get(skillId)));
|
||||||
|
}
|
||||||
|
for (int skillId : skillDifficulty.keySet()){
|
||||||
|
logger.info(String.format("Setting difficulty of skill %s to %.2f.",
|
||||||
|
SkillAssist.getSkill(skillId), skillDifficulty.get(skillId)));
|
||||||
|
}
|
||||||
|
for (int skillId : skillTickTime.keySet()){
|
||||||
|
logger.info(String.format("Setting tick time of skill %s to %d.",
|
||||||
|
SkillAssist.getSkill(skillId), skillTickTime.get(skillId)));
|
||||||
|
}
|
||||||
|
logger.info("Change Preaching Location: "+changePreachingLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("Meditation Module: "+enableMeditationModule);
|
||||||
|
if (enableMeditationModule){
|
||||||
|
logger.info("Simplify Meditation Terrain: "+simplifyMeditationTerrain);
|
||||||
|
logger.info("Remove Insanity Shield of the Gone: "+removeInsanitySotG);
|
||||||
|
logger.info("Remove Hate War Bonus: "+removeHateWarBonus);
|
||||||
|
logger.info("Insanity Speed Bonus: "+insanitySpeedBonus);
|
||||||
|
logger.info("Hate Movement Bonus: "+hateMovementBonus);
|
||||||
|
logger.info("Scaling Power Stamina Bonus: "+scalingPowerStaminaBonus);
|
||||||
|
logger.info("Scaling Knowledge Skill Gain: "+scalingKnowledgeSkillGain);
|
||||||
|
logger.info("Remove Meditation Tick Timer: "+removeMeditationTickTimer);
|
||||||
|
logger.info("New Meditation Buffs: "+newMeditationBuffs);
|
||||||
|
logger.info("Meditation Ability Cooldowns: "+enableMeditationAbilityCooldowns);
|
||||||
|
if (enableMeditationAbilityCooldowns){
|
||||||
|
logger.info("Love Refresh Cooldown: "+loveRefreshCooldown);
|
||||||
|
logger.info("Love Enchant Nature Cooldown: "+loveEnchantNatureCooldown);
|
||||||
|
logger.info("Love Love Effect Cooldown: "+loveLoveEffectCooldown);
|
||||||
|
logger.info("Hate War Bonus Cooldown: "+hateWarDamageCooldown);
|
||||||
|
logger.info("Hate Structure Damage Cooldown: "+hateStructureDamageCooldown);
|
||||||
|
logger.info("Hate Fear Cooldown: "+hateFearCooldown);
|
||||||
|
logger.info("Power Elemental Immunity Cooldown: "+powerElementalImmunityCooldown);
|
||||||
|
logger.info("Power Erupt/Freeze Cooldown: "+powerEruptFreezeCooldown);
|
||||||
|
logger.info("Power Ignore Traps Cooldown: "+powerIgnoreTrapsCooldown);
|
||||||
|
logger.info("Knowledge Info Creature Cooldown: "+knowledgeInfoCreatureCooldown);
|
||||||
|
logger.info("Knowledge Info Tile Cooldown: "+knowledgeInfoTileCooldown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
logger.info("Treasure Chest Loot Module: "+enableTreasureChestLootModule);
|
logger.info("Treasure Chest Loot Module: "+enableTreasureChestLootModule);
|
||||||
|
|
||||||
//this.logger.log(Level.INFO, "Property: " + this.somevalue);
|
//this.logger.log(Level.INFO, "Property: " + this.somevalue);
|
||||||
@@ -582,11 +822,6 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
Arena.preInit();
|
Arena.preInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom Titles Module Pre-Init
|
|
||||||
if (enableCustomTitlesModule) {
|
|
||||||
PlayerTitles.preInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Anti-Cheat Module Pre-Init
|
// Anti-Cheat Module Pre-Init
|
||||||
if (enableAntiCheatModule) {
|
if (enableAntiCheatModule) {
|
||||||
AntiCheat.preInit();
|
AntiCheat.preInit();
|
||||||
@@ -597,6 +832,24 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
QualityOfLife.preInit();
|
QualityOfLife.preInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Combat Module Pre-Init
|
||||||
|
if (enableCombatModule) {
|
||||||
|
CombatChanges.preInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mastercraft Module Pre-Init
|
||||||
|
if (enableMastercraftModule) {
|
||||||
|
Mastercraft.preInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableSkillModule) {
|
||||||
|
SkillChanges.preInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableMeditationModule) {
|
||||||
|
MeditationPerks.preInit();
|
||||||
|
}
|
||||||
|
|
||||||
// Treasure Chest Loot Module Pre-Init
|
// Treasure Chest Loot Module Pre-Init
|
||||||
if (enableTreasureChestLootModule) {
|
if (enableTreasureChestLootModule) {
|
||||||
TreasureChests.preInit();
|
TreasureChests.preInit();
|
||||||
@@ -607,15 +860,13 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
TeleportHandler.preInit();
|
TeleportHandler.preInit();
|
||||||
MethodsBestiary.preInit();
|
MethodsBestiary.preInit();
|
||||||
MissionCreator.preInit();
|
MissionCreator.preInit();
|
||||||
SkillChanges.preInit();
|
|
||||||
MeditationPerks.preInit();
|
|
||||||
MountedChanges.preInit();
|
MountedChanges.preInit();
|
||||||
EconomicChanges.preInit();
|
EconomicChanges.preInit();
|
||||||
Bloodlust.preInit();
|
|
||||||
Mastercraft.preInit();
|
|
||||||
SupplyDepots.preInit();
|
SupplyDepots.preInit();
|
||||||
KeyEvent.preInit();
|
KeyEvent.preInit();
|
||||||
CombatChanges.preInit();
|
|
||||||
|
// Bloodlust might no longer be necessary. Code remains for reference.
|
||||||
|
//Bloodlust.preInit();
|
||||||
|
|
||||||
// Gem Augmentation is not complete.
|
// Gem Augmentation is not complete.
|
||||||
//GemAugmentation.preInit();
|
//GemAugmentation.preInit();
|
||||||
@@ -737,7 +988,11 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
@Override
|
@Override
|
||||||
public void onPlayerLogin(Player p) {
|
public void onPlayerLogin(Player p) {
|
||||||
DatabaseHelper.onPlayerLogin(p);
|
DatabaseHelper.onPlayerLogin(p);
|
||||||
PlayerTitles.awardCustomTitles(p);
|
|
||||||
|
// Award Custom Titles on player login
|
||||||
|
if(enableCustomTitlesModule) {
|
||||||
|
PlayerTitles.awardCustomTitles(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -778,7 +1033,9 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
//espCounter = Servers.localServer.PVPSERVER; // Enables on PvP server by default.
|
//espCounter = Servers.localServer.PVPSERVER; // Enables on PvP server by default.
|
||||||
//espCounter = false;
|
//espCounter = false;
|
||||||
|
|
||||||
SkillChanges.onServerStarted();
|
if (enableSkillModule) {
|
||||||
|
SkillChanges.onServerStarted();
|
||||||
|
}
|
||||||
|
|
||||||
CreationEntry lockpicks = CreationMatrix.getInstance().getCreationEntry(ItemList.lockpick);
|
CreationEntry lockpicks = CreationMatrix.getInstance().getCreationEntry(ItemList.lockpick);
|
||||||
try {
|
try {
|
||||||
@@ -847,11 +1104,11 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea
|
|||||||
Bloodlust.pollLusts();
|
Bloodlust.pollLusts();
|
||||||
lastPolledBloodlust += pollBloodlustTime;
|
lastPolledBloodlust += pollBloodlustTime;
|
||||||
}
|
}
|
||||||
if(lastPolledUniqueRegeneration + pollUniqueRegenerationTime < System.currentTimeMillis()){
|
if(WyvernMods.useStaticLegendaryRegeneration && lastPolledUniqueRegeneration + pollUniqueRegenerationTime < System.currentTimeMillis()){
|
||||||
CombatChanges.pollUniqueRegeneration();
|
CombatChanges.pollUniqueRegeneration();
|
||||||
lastPolledUniqueRegeneration += pollUniqueRegenerationTime;
|
lastPolledUniqueRegeneration += pollUniqueRegenerationTime;
|
||||||
}
|
}
|
||||||
if(lastPolledUniqueCollection + pollUniqueCollectionTime < System.currentTimeMillis()){
|
if(WyvernMods.enableCombatModule && lastPolledUniqueCollection + pollUniqueCollectionTime < System.currentTimeMillis()){
|
||||||
CombatChanges.pollUniqueCollection();
|
CombatChanges.pollUniqueCollection();
|
||||||
lastPolledUniqueCollection += pollUniqueCollectionTime;
|
lastPolledUniqueCollection += pollUniqueCollectionTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,494 +0,0 @@
|
|||||||
package mod.sin.wyvern.mastercraft;
|
|
||||||
|
|
||||||
import javassist.bytecode.*;
|
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
|
|
||||||
public class BytecodeTools extends Bytecode {
|
|
||||||
|
|
||||||
//private static final int EMPTY_INT = Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
BytecodeTools(ConstPool constPool){
|
|
||||||
super(constPool);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Look for a class in the constant pool.
|
|
||||||
* Throws NoMatchingConstPoolIndexException if the references isn't found.
|
|
||||||
*
|
|
||||||
* @param className String Object type. Full class name using periods.
|
|
||||||
* @return int primitive, index in constant pool table.
|
|
||||||
*/
|
|
||||||
int findClassIndex(String className){
|
|
||||||
int classReferenceIndex = getClassReferenceIndex(className);
|
|
||||||
if (classReferenceIndex == -1)
|
|
||||||
throw new RuntimeException("No matching class found.");
|
|
||||||
this.add((classReferenceIndex >>> 8) & 0xFF, classReferenceIndex & 0xFF);
|
|
||||||
return classReferenceIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
int addClassIndex(String className){
|
|
||||||
int classReferenceIndex = getClassReferenceIndex(className);
|
|
||||||
if (classReferenceIndex == -1)
|
|
||||||
classReferenceIndex = this.getConstPool().addClassInfo(className);
|
|
||||||
this.add((classReferenceIndex >>> 8) & 0xFF, classReferenceIndex & 0xFF);
|
|
||||||
return classReferenceIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
int findMethodIndex(int opcode, String name, String descriptor, String className){
|
|
||||||
int methodReferenceIndex;
|
|
||||||
int classReferenceIndex = getClassReferenceIndex(className);
|
|
||||||
if (classReferenceIndex == -1)
|
|
||||||
throw new RuntimeException("No matching class found.");
|
|
||||||
|
|
||||||
methodReferenceIndex = IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Methodref)
|
|
||||||
.filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null)
|
|
||||||
.filter(value -> Objects.equals(this.getConstPool().getMethodrefClass(value), classReferenceIndex))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new RuntimeException("No matching method found."));
|
|
||||||
this.addOpcode(opcode);
|
|
||||||
this.add((methodReferenceIndex >>> 8) & 0xFF, methodReferenceIndex & 0xFF);
|
|
||||||
|
|
||||||
return methodReferenceIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
int addMethodIndex(int opcode, String name, String methodDescriptor, String className){
|
|
||||||
int classReferenceIndex = getClassReferenceIndex(className);
|
|
||||||
if (classReferenceIndex == -1)
|
|
||||||
classReferenceIndex = this.getConstPool().addClassInfo(className);
|
|
||||||
int indexReference = this.getConstPool().addMethodrefInfo(classReferenceIndex, name, methodDescriptor);
|
|
||||||
this.addOpcode(opcode);
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
return indexReference;
|
|
||||||
}
|
|
||||||
|
|
||||||
int findFieldIndex(int opcode, String name, String descriptor, String className){
|
|
||||||
int fieldReferenceIndex;
|
|
||||||
int classReferenceIndex = getClassReferenceIndex(className);
|
|
||||||
if (classReferenceIndex == -1)
|
|
||||||
throw new RuntimeException("No matching class found.");
|
|
||||||
fieldReferenceIndex = IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Fieldref)
|
|
||||||
.filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null)
|
|
||||||
.filter(value -> this.getConstPool().getFieldrefClass(value) == classReferenceIndex)
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new RuntimeException("No matching field found."));
|
|
||||||
this.addOpcode(opcode);
|
|
||||||
this.add((fieldReferenceIndex >>> 8) & 0xFF, fieldReferenceIndex & 0xFF);
|
|
||||||
return fieldReferenceIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
int addFieldIndex(int opcode, String name, String descriptor, String className){
|
|
||||||
int classReferenceIndex = getClassReferenceIndex(className);
|
|
||||||
if (classReferenceIndex == -1)
|
|
||||||
classReferenceIndex = this.getConstPool().addClassInfo(className);
|
|
||||||
int fieldReferenceIndex = this.getConstPool().addFieldrefInfo(classReferenceIndex, name, descriptor);
|
|
||||||
this.addOpcode(opcode);
|
|
||||||
this.add((fieldReferenceIndex >>> 8) & 0xFF, fieldReferenceIndex & 0xFF);
|
|
||||||
return fieldReferenceIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void findStringIndex(String string){
|
|
||||||
int indexReference = IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_String)
|
|
||||||
.filter(value -> Objects.equals(this.getConstPool().getStringInfo(value), string))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new RuntimeException("No matching string found."));
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addStringIndex(String string){
|
|
||||||
int indexReference = this.getConstPool().addStringInfo(string);
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void findLongIndex(long longValue){
|
|
||||||
int indexReference = IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Long)
|
|
||||||
.filter(value -> this.getConstPool().getLongInfo(value) == longValue)
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new RuntimeException("No matching long found."));
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addLongIndex(long longValue){
|
|
||||||
int indexReference = this.getConstPool().addLongInfo(longValue);
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void findFloatIndex(float floatValue){
|
|
||||||
int indexReference = IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Float)
|
|
||||||
.filter(value -> this.getConstPool().getFloatInfo(value) == floatValue)
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new RuntimeException("No matching float found."));
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addFloatIndex(float floatValue){
|
|
||||||
int indexReference = this.getConstPool().addFloatInfo(floatValue);
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* a double value stored in the constant pool is always a LDC2_W. This is different then a local variable holding a double.
|
|
||||||
*
|
|
||||||
* @param doubleValue primitive double.
|
|
||||||
*/
|
|
||||||
void findDoubleIndex(double doubleValue){
|
|
||||||
int indexReference = IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Double)
|
|
||||||
.filter(value -> this.getConstPool().getDoubleInfo(value) == doubleValue)
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new RuntimeException("No matching double found."));
|
|
||||||
this.addOpcode(Opcode.LDC2_W);
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* a double value stored in the constant pool is always a LDC2_W. This is different then a local variable holding a double.
|
|
||||||
*
|
|
||||||
* @param doubleValue primitive double.
|
|
||||||
*/
|
|
||||||
void addDoubleIndex(double doubleValue){
|
|
||||||
int indexReference = this.getConstPool().addDoubleInfo(doubleValue);
|
|
||||||
this.addOpcode(Opcode.LDC2_W);
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasAClassDeclaringTag(int tag){
|
|
||||||
return tag == ConstPool.CONST_Methodref || tag == ConstPool.CONST_Fieldref || tag == ConstPool.CONST_InterfaceMethodref;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Often a class's name will appear twice in the constant pool. One of the occurrence is not used as a declaring class for anything.
|
|
||||||
* I have no idea why it's present but it can break looking up constant pool references if the unassociated one is picked. JA has a
|
|
||||||
* built in way of finding existent references but a underlying mechanic is that a hash map uses a string class name as a key
|
|
||||||
* in a hashMap. Two equal strings will overwrite each other in this case. This is part the the tools library to look for matches
|
|
||||||
* instead of relying on JA.
|
|
||||||
*
|
|
||||||
* 1. scan the constant pool and get the class references that match className.
|
|
||||||
* 2. scan again through the constant pool looking for class associations that use the references found in #1. One of the options
|
|
||||||
* will have no references and illuminate that one to return the one that should be used.
|
|
||||||
*
|
|
||||||
* @param className String type object, uses full class name and periods.
|
|
||||||
* @return int primitive, the address in constant pool for the class matching className.
|
|
||||||
*/
|
|
||||||
private int getClassReferenceIndex(String className){
|
|
||||||
return IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Class)
|
|
||||||
.filter(value -> Objects.equals(Descriptor.toClassName(this.getConstPool().getClassInfoByDescriptor(value)), className))
|
|
||||||
.filter( verifyIndex ->
|
|
||||||
IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> hasAClassDeclaringTag(this.getConstPool().getTag(value)))
|
|
||||||
.filter(value -> {
|
|
||||||
boolean result = false;
|
|
||||||
switch (this.getConstPool().getTag(value)) {
|
|
||||||
case ConstPool.CONST_Methodref:
|
|
||||||
result = this.getConstPool().getMethodrefClass(value) == verifyIndex;
|
|
||||||
break;
|
|
||||||
case ConstPool.CONST_Fieldref:
|
|
||||||
result = this.getConstPool().getFieldrefClass(value) == verifyIndex;
|
|
||||||
break;
|
|
||||||
case ConstPool.CONST_InterfaceMethodref:
|
|
||||||
result = this.getConstPool().getInterfaceMethodrefClass(value) == verifyIndex;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return result;})
|
|
||||||
.count() > 0
|
|
||||||
)
|
|
||||||
.findFirst()
|
|
||||||
.orElse(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void findInterfaceMethodIndex(String name, String descriptor){
|
|
||||||
if(IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_InterfaceMethodref)
|
|
||||||
.filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null)
|
|
||||||
.count() != 1){
|
|
||||||
throw new RuntimeException("No matching interface found.");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int indexReference = IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_InterfaceMethodref)
|
|
||||||
.filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null)
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new RuntimeException("No matching interface found."));
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addInterfaceMethodIndex(String name, String descriptor){
|
|
||||||
int classIndexReference = IntStream.range(1, this.getConstPool().getSize())
|
|
||||||
.filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Class)
|
|
||||||
.filter(value -> Objects.equals(this.getConstPool().getClassInfoByDescriptor(value), Descriptor.toClassName(descriptor)))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new RuntimeException("No matching class found."));
|
|
||||||
int indexReference = this.getConstPool().addInterfaceMethodrefInfo(classIndexReference, name, descriptor);
|
|
||||||
this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void codeBranching(int opcode, int branchCount){
|
|
||||||
this.addOpcode(opcode);
|
|
||||||
this.add((branchCount >>> 8) & 0xFF, branchCount & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void localVariableIndex(int opcode, int slot){
|
|
||||||
this.addOpcode(opcode);
|
|
||||||
this.add(slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
void integerIndex(int opcode, int value){
|
|
||||||
switch (opcode) {
|
|
||||||
case Opcode.BIPUSH :
|
|
||||||
this.addOpcode(Opcode.BIPUSH);
|
|
||||||
this.add((byte)value);
|
|
||||||
break;
|
|
||||||
case Opcode.SIPUSH :
|
|
||||||
this.addOpcode(Opcode.SIPUSH);
|
|
||||||
this.add((value >>> 8) & 0xFF, value & 0xFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode the value for arg "integer" into the appropriate byteCode opCode + operand for the java-int. Add the
|
|
||||||
* encoded information to the byte code object "bytecode".
|
|
||||||
*
|
|
||||||
* @param integer int value.
|
|
||||||
*/
|
|
||||||
void addInteger(int integer) {
|
|
||||||
switch (integer) {
|
|
||||||
case -1:
|
|
||||||
this.add(Opcode.ICONST_M1);
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
this.add(Opcode.ICONST_0);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
this.add(Opcode.ICONST_1);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
this.add(Opcode.ICONST_2);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
this.add(Opcode.ICONST_3);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
this.add(Opcode.ICONST_4);
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
this.add(Opcode.ICONST_5);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (integer >= Byte.MIN_VALUE && integer <= Byte.MAX_VALUE) {
|
|
||||||
this.add(Opcode.BIPUSH);
|
|
||||||
// integer bound to byte size.
|
|
||||||
this.add(integer);
|
|
||||||
} else if (integer >= Short.MIN_VALUE && integer <= Short.MAX_VALUE) {
|
|
||||||
this.add(Opcode.SIPUSH);
|
|
||||||
// Since byte code requires byte sized blocks, break up integer with bitmask and shift.
|
|
||||||
this.add((integer & 0xff00) >>> 8, integer & 0x00ff);
|
|
||||||
} else {
|
|
||||||
// Appends LDC or LDC_W depending on constant pool size.
|
|
||||||
this.addLdc(this.getConstPool().addIntegerInfo(integer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode the byte code represented by a opCode + operand(s) at the position in arg "instructionIndex". Return
|
|
||||||
* decoded data as java-int.
|
|
||||||
*
|
|
||||||
* @param codeIterator JA CodeIterator object.
|
|
||||||
* @param instructionIndex int value, it is the codeIterator index of an opCode.
|
|
||||||
* @return int value.
|
|
||||||
*/
|
|
||||||
int getInteger(CodeIterator codeIterator, int instructionIndex) {
|
|
||||||
int opCode = codeIterator.byteAt(instructionIndex);
|
|
||||||
switch (opCode) {
|
|
||||||
case Opcode.ICONST_M1:
|
|
||||||
return -1;
|
|
||||||
case Opcode.ICONST_0:
|
|
||||||
return 0;
|
|
||||||
case Opcode.ICONST_1:
|
|
||||||
return 1;
|
|
||||||
case Opcode.ICONST_2:
|
|
||||||
return 2;
|
|
||||||
case Opcode.ICONST_3:
|
|
||||||
return 3;
|
|
||||||
case Opcode.ICONST_4:
|
|
||||||
return 4;
|
|
||||||
case Opcode.ICONST_5:
|
|
||||||
return 5;
|
|
||||||
case Opcode.BIPUSH:
|
|
||||||
return codeIterator.byteAt(instructionIndex + 1);
|
|
||||||
case Opcode.SIPUSH:
|
|
||||||
return codeIterator.s16bitAt(instructionIndex + 1);
|
|
||||||
case Opcode.LDC:
|
|
||||||
return this.getConstPool().getIntegerInfo(codeIterator.byteAt(instructionIndex + 1));
|
|
||||||
case Opcode.LDC_W:
|
|
||||||
return this.getConstPool().getIntegerInfo(codeIterator.u16bitAt(instructionIndex + 1));
|
|
||||||
default:
|
|
||||||
throw new RuntimeException(String.format("Failed to decode integer. Pos = %d, Bytecode = %d", instructionIndex, opCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int findSlotInLocalVariableTable(CodeAttribute codeAttribute, String variableName){
|
|
||||||
LocalVariableAttribute table = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
|
|
||||||
int tableOrdinal;
|
|
||||||
tableOrdinal = IntStream.range(0,table.tableLength()).filter(value -> Objects.equals(table.variableName(value), variableName )).findFirst().orElse(-1);
|
|
||||||
if (tableOrdinal == -1){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return table.index(tableOrdinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int findLineNumberInLineNumberTable(CodeAttribute codeAttribute, String variableName){
|
|
||||||
LocalVariableAttribute table = (LocalVariableAttribute) codeAttribute.getAttribute(LineNumberAttribute.tag);
|
|
||||||
int tableOrdinal;
|
|
||||||
tableOrdinal = IntStream.range(0,table.tableLength()).filter(value -> Objects.equals(table.variableName(value), variableName )).findFirst().orElse(-1);
|
|
||||||
if (tableOrdinal == -1){
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return table.index(tableOrdinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int[] getInstruction(int size, int index, CodeIterator codeIterator) {
|
|
||||||
int[] toReturn = null;
|
|
||||||
int bitLine;
|
|
||||||
int bitLine2;
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
bitLine = codeIterator.byteAt(index);
|
|
||||||
toReturn = new int[]{
|
|
||||||
bitLine
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
bitLine = codeIterator.s16bitAt(index);
|
|
||||||
toReturn = new int[]{
|
|
||||||
(bitLine & 0xff00) >>> 8,
|
|
||||||
bitLine & 0x00ff
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
bitLine = codeIterator.s32bitAt(index);
|
|
||||||
toReturn = new int[]{
|
|
||||||
(bitLine & 0xff000000) >>> 24,
|
|
||||||
(bitLine & 0x00ff0000) >>> 16,
|
|
||||||
(bitLine & 0x0000ff00) >>> 8
|
|
||||||
// not using the last byte
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
bitLine = codeIterator.s32bitAt(index);
|
|
||||||
toReturn = new int[]{
|
|
||||||
(bitLine & 0xff000000) >>> 24,
|
|
||||||
(bitLine & 0x00ff0000) >>> 16,
|
|
||||||
(bitLine & 0x0000ff00) >>> 8,
|
|
||||||
(bitLine & 0x000000ff)
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
bitLine = codeIterator.s32bitAt(index);
|
|
||||||
bitLine2 = codeIterator.byteAt(index + 4);
|
|
||||||
toReturn = new int[]{
|
|
||||||
(bitLine & 0xff000000) >>> 24,
|
|
||||||
(bitLine & 0x00ff0000) >>> 16,
|
|
||||||
(bitLine & 0x0000ff00) >>> 8,
|
|
||||||
(bitLine & 0x000000ff),
|
|
||||||
bitLine2
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
bitLine = codeIterator.s32bitAt(index);
|
|
||||||
bitLine2 = codeIterator.s16bitAt(index + 4);
|
|
||||||
toReturn = new int[]{
|
|
||||||
(bitLine & 0xff000000) >>> 24,
|
|
||||||
(bitLine & 0x00ff0000) >>> 16,
|
|
||||||
(bitLine & 0x0000ff00) >>> 8,
|
|
||||||
(bitLine & 0x000000ff),
|
|
||||||
(bitLine2 & 0xff00) >>> 8,
|
|
||||||
(bitLine2 & 0x00ff)
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
bitLine = codeIterator.s32bitAt(index);
|
|
||||||
bitLine2 = codeIterator.s32bitAt(index + 4);
|
|
||||||
toReturn = new int[]{
|
|
||||||
(bitLine & 0xff000000) >>> 24,
|
|
||||||
(bitLine & 0x00ff0000) >>> 16,
|
|
||||||
(bitLine & 0x0000ff00) >>> 8,
|
|
||||||
(bitLine & 0x000000ff),
|
|
||||||
(bitLine2 & 0xff000000) >>> 24,
|
|
||||||
(bitLine2 & 0x00ff0000) >>> 16,
|
|
||||||
(bitLine2 & 0x0000ff00) >>> 8
|
|
||||||
// not using the last byte
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
bitLine = codeIterator.s32bitAt(index);
|
|
||||||
bitLine2 = codeIterator.s32bitAt(index + 4);
|
|
||||||
toReturn = new int[]{
|
|
||||||
(bitLine & 0xff000000) >>> 24,
|
|
||||||
(bitLine & 0x00ff0000) >>> 16,
|
|
||||||
(bitLine & 0x0000ff00) >>> 8,
|
|
||||||
(bitLine & 0x000000ff),
|
|
||||||
(bitLine2 & 0xff000000) >>> 24,
|
|
||||||
(bitLine2 & 0x00ff0000) >>> 16,
|
|
||||||
(bitLine2 & 0x0000ff00) >>> 8,
|
|
||||||
(bitLine2 & 0x000000ff)
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void byteCodePrint(String destinationPath, CodeIterator codeIterator) throws FileNotFoundException, BadBytecode {
|
|
||||||
Path printPath = Paths.get(destinationPath);
|
|
||||||
PrintWriter out = new PrintWriter(printPath.toFile());
|
|
||||||
final String[] instructionOut = {""};
|
|
||||||
codeIterator.begin();
|
|
||||||
while (codeIterator.hasNext()) {
|
|
||||||
int index = codeIterator.next();
|
|
||||||
int[] instruction = getInstruction(codeIterator.lookAhead() - index, index, codeIterator);
|
|
||||||
instructionOut[0] += Integer.toString(index);
|
|
||||||
instructionOut[0] += " ";
|
|
||||||
instructionOut[0] += Mnemonic.OPCODE[instruction[0]];
|
|
||||||
if (instruction.length > 1) {
|
|
||||||
instructionOut[0] += " ";
|
|
||||||
IntStream.range(1, instruction.length)
|
|
||||||
.forEach(value -> {
|
|
||||||
instructionOut[0] += Integer.toString(instruction[value]);
|
|
||||||
instructionOut[0] += " ";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
out.println(instructionOut[0]);
|
|
||||||
instructionOut[0] = "";
|
|
||||||
}
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void printArrayToHex(Object[] obj, String name, Logger logger){
|
|
||||||
int length = obj.length;
|
|
||||||
int[] c = new int[length];
|
|
||||||
for (int i=0;i<length;i++){
|
|
||||||
c[i]=(int)obj[i];
|
|
||||||
}
|
|
||||||
String[] a = new String[length];
|
|
||||||
for (int i=0;i<length;i++){
|
|
||||||
a[i]=String.format("%02X", c[i] & 0xff);
|
|
||||||
}
|
|
||||||
logger.log(Level.INFO,name + " : " + Arrays.toString(a));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
package mod.sin.wyvern.mastercraft;
|
|
||||||
|
|
||||||
import com.wurmonline.server.skills.SkillList;
|
|
||||||
import javassist.*;
|
|
||||||
import javassist.bytecode.*;
|
|
||||||
|
|
||||||
import org.gotti.wurmunlimited.modloader.classhooks.CodeReplacer;
|
|
||||||
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
class ExtendTitleEnum {
|
|
||||||
|
|
||||||
private final String className;
|
|
||||||
private final int valuesSizerIndex; // the bytecode index which puts a size specifying value on the stack for anewarray.
|
|
||||||
private final int populateVALUESIndex; // the bytecode index where references to various enum instances are put in the $VALUES array.
|
|
||||||
private final ConstPool constPool;
|
|
||||||
|
|
||||||
private static ArrayList<EnumFields> toExtendEntries = new ArrayList<>();
|
|
||||||
private static ExtendTitleEnum singletonInstance;
|
|
||||||
|
|
||||||
private ExtendTitleEnum(String className, int valuesSizerIndex, int populateVALUESIndex, ConstPool constPool) {
|
|
||||||
this.className = className;
|
|
||||||
this.valuesSizerIndex = valuesSizerIndex;
|
|
||||||
this.populateVALUESIndex = populateVALUESIndex;
|
|
||||||
this.constPool = constPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Goes through the enum class's initiator to find bytecode index positions.
|
|
||||||
*
|
|
||||||
* @throws BadBytecode forwarded, Javassist stuff.
|
|
||||||
*/
|
|
||||||
static void builder(String className) throws BadBytecode, NotFoundException {
|
|
||||||
int valuesSizerIndex = -1;
|
|
||||||
//int indexANEWARRAY = -1;
|
|
||||||
int populateVALUESIndex = -1;
|
|
||||||
CtClass ctClassEnum = HookManager.getInstance().getClassPool().get(className);
|
|
||||||
ConstPool constPool = ctClassEnum.getClassFile().getConstPool();
|
|
||||||
CodeIterator codeIterator = ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute().iterator();
|
|
||||||
// Get the byte code instruction index for
|
|
||||||
// 1) size value for ANEWARRAY,
|
|
||||||
// 2) the VALUES array assignment or population.
|
|
||||||
BytecodeTools b = new BytecodeTools(constPool);
|
|
||||||
String valuesDescriptor = className.replace(".", "/");
|
|
||||||
valuesDescriptor = "[L" + valuesDescriptor + ";";
|
|
||||||
int constPoolValuesIndex = b.findFieldIndex(Opcode.PUTSTATIC, "$VALUES",
|
|
||||||
valuesDescriptor, className);
|
|
||||||
codeIterator.begin();
|
|
||||||
int lastIndex = 0;
|
|
||||||
while (codeIterator.hasNext()){
|
|
||||||
int instructionIndex = codeIterator.next();
|
|
||||||
int opCode = codeIterator.byteAt(instructionIndex);
|
|
||||||
switch (opCode){
|
|
||||||
case Opcode.ANEWARRAY :
|
|
||||||
valuesSizerIndex = lastIndex;
|
|
||||||
//indexANEWARRAY = instructionIndex;
|
|
||||||
break;
|
|
||||||
case Opcode.PUTSTATIC :
|
|
||||||
int cpAddress = codeIterator.u16bitAt(instructionIndex+1);
|
|
||||||
if (cpAddress == constPoolValuesIndex){
|
|
||||||
populateVALUESIndex = instructionIndex;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lastIndex = instructionIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (ExtendTitleEnum.class) {
|
|
||||||
singletonInstance = new ExtendTitleEnum(className, valuesSizerIndex, populateVALUESIndex, constPool);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static ExtendTitleEnum getSingletonInstance() {
|
|
||||||
return singletonInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A method to create data structures and add record a reference for that object.
|
|
||||||
*
|
|
||||||
* @param fieldName the name for the enum entry.
|
|
||||||
* @param titleId an ordinal for the Titles.Title enum.
|
|
||||||
* @param maleName in-game title name for male toons.
|
|
||||||
* @param femaleName in-game title name for femaleName toons.
|
|
||||||
* @param skillId A id number for the skill associated with the title, see {@link SkillList}
|
|
||||||
* @param titleTypes A string representation of entries in {@link com.wurmonline.server.players.Titles.TitleType}. In
|
|
||||||
* order to avoid premature class initialization for Javassist's bytecode stages we use a string
|
|
||||||
* instead of the WU object. The string must match one of the enum field names.
|
|
||||||
*/
|
|
||||||
synchronized void addExtendEntry(String fieldName, int titleId, String maleName, String femaleName, int skillId, String titleTypes) {
|
|
||||||
if (singletonInstance == null) {
|
|
||||||
throw new RuntimeException("ExtendTitleEnum instance is null, build it before addExtendEntry");
|
|
||||||
}
|
|
||||||
EnumFields enumFields = new EnumFields(fieldName, titleId, maleName, femaleName, skillId, titleTypes);
|
|
||||||
toExtendEntries.add(enumFields);
|
|
||||||
}
|
|
||||||
|
|
||||||
class EnumFields {
|
|
||||||
final String fieldName;
|
|
||||||
final int titleId;
|
|
||||||
final String maleName;
|
|
||||||
final String femaleName;
|
|
||||||
final int skillId;
|
|
||||||
final String titleTypes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param fieldName the name for the enum entry.
|
|
||||||
* @param titleId an ordinal for the Titles.Title enum.
|
|
||||||
* @param maleName in-game title name for male toons.
|
|
||||||
* @param femaleName in-game title name for femaleName toons.
|
|
||||||
* @param skillId A id number for the skill associated with the title, see {@link SkillList}
|
|
||||||
* @param titleTypes A string representation of entries in {@link com.wurmonline.server.players.Titles.TitleType}. In
|
|
||||||
* order to avoid premature class initialization for Javassist's bytecode stages we use a string
|
|
||||||
* instead of the WU object.
|
|
||||||
**/
|
|
||||||
EnumFields(String fieldName, int titleId, String maleName, String femaleName,
|
|
||||||
int skillId, String titleTypes){
|
|
||||||
this.fieldName = fieldName;
|
|
||||||
this.titleId = titleId;
|
|
||||||
this.maleName = maleName;
|
|
||||||
this.femaleName = femaleName;
|
|
||||||
this.skillId = skillId;
|
|
||||||
this.titleTypes = titleTypes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intended to be used in WurmServerMod-initiate section and it's for bytecode changes. This adds field objects to the enum class.
|
|
||||||
*
|
|
||||||
* @throws CannotCompileException forwarded, Javassist stuff.
|
|
||||||
*/
|
|
||||||
private synchronized void createFieldsInEnum() throws CannotCompileException, NotFoundException {
|
|
||||||
if (toExtendEntries.size() == 0){
|
|
||||||
throw new RuntimeException("Can not extend an enum without values in toExtendEntries arrayList.");
|
|
||||||
}
|
|
||||||
|
|
||||||
CtClass enumCtClass = HookManager.getInstance().getClassPool().get(this.className);
|
|
||||||
for (EnumFields enumData : toExtendEntries) {
|
|
||||||
CtField field = new CtField(enumCtClass, enumData.fieldName, enumCtClass);
|
|
||||||
field.setModifiers(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL | Modifier.ENUM);
|
|
||||||
enumCtClass.addField(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method uses JA bytecode to inject into the Enum's class initiator in order to expand the enum's $VALUES field.
|
|
||||||
*
|
|
||||||
* @throws BadBytecode forwarded, Javassist stuff.
|
|
||||||
*/
|
|
||||||
private void resizeEnumVALUES() throws BadBytecode, ClassNotFoundException, NotFoundException {
|
|
||||||
int expansion = toExtendEntries.size();
|
|
||||||
CtClass ctClassEnum = HookManager.getInstance().getClassPool().get(this.className);
|
|
||||||
CodeIterator codeIterator = ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute().iterator();
|
|
||||||
|
|
||||||
BytecodeTools findBytecode = new BytecodeTools(this.constPool);
|
|
||||||
int currentSize = findBytecode.getInteger(codeIterator, this.valuesSizerIndex);
|
|
||||||
findBytecode.addInteger(currentSize);
|
|
||||||
findBytecode.addOpcode(Opcode.ANEWARRAY);
|
|
||||||
findBytecode.addClassIndex(this.className);
|
|
||||||
|
|
||||||
BytecodeTools replaceBytecode = new BytecodeTools(this.constPool);
|
|
||||||
replaceBytecode.addInteger(currentSize + expansion);
|
|
||||||
replaceBytecode.addOpcode(Opcode.ANEWARRAY);
|
|
||||||
replaceBytecode.addClassIndex(this.className);
|
|
||||||
|
|
||||||
CodeReplacer codeReplacer = new CodeReplacer(ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute());
|
|
||||||
codeReplacer.replaceCode(findBytecode.get(), replaceBytecode.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method builds bytecode to inject into the enum's initiator. The injected code initializes new enum entries and adds
|
|
||||||
* a reference of that new object to the $VALUES array.
|
|
||||||
*
|
|
||||||
* @throws BadBytecode forwarded, JA stuff.
|
|
||||||
* @throws ClassNotFoundException forwarded, JA stuff.
|
|
||||||
* @throws NotFoundException forwarded, JA stuff.
|
|
||||||
*/
|
|
||||||
synchronized void ExtendEnumEntries() throws BadBytecode, ClassNotFoundException, NotFoundException, CannotCompileException {
|
|
||||||
createFieldsInEnum();
|
|
||||||
CtClass ctClassEnum = HookManager.getInstance().getClassPool().get(this.className);
|
|
||||||
CodeIterator initiatorCodeIterator = ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute().iterator();
|
|
||||||
|
|
||||||
BytecodeTools enumInitiator = new BytecodeTools(ctClassEnum.getClassFile().getConstPool());
|
|
||||||
BytecodeTools populateVALUES = new BytecodeTools(ctClassEnum.getClassFile().getConstPool());
|
|
||||||
int extensionCounter = 0;
|
|
||||||
int valuesSize = enumInitiator.getInteger(initiatorCodeIterator, this.valuesSizerIndex);
|
|
||||||
// Construct the two bytecode objects to be inserted. The multiple enumData in toExtendEntries are combined into one
|
|
||||||
// long bytecode sequence and inserted at the proper point.
|
|
||||||
for (EnumFields enumData : toExtendEntries) {
|
|
||||||
enumInitiator.addOpcode(Opcode.NEW);
|
|
||||||
enumInitiator.findClassIndex(this.className);
|
|
||||||
enumInitiator.addOpcode(Opcode.DUP);
|
|
||||||
enumInitiator.addLdc(enumData.fieldName);
|
|
||||||
enumInitiator.addInteger(valuesSize + extensionCounter);
|
|
||||||
enumInitiator.addInteger(enumData.titleId);
|
|
||||||
enumInitiator.addLdc(enumData.maleName);
|
|
||||||
enumInitiator.addLdc(enumData.femaleName);
|
|
||||||
enumInitiator.addInteger(enumData.skillId);
|
|
||||||
enumInitiator.addFieldIndex(Opcode.GETSTATIC, enumData.titleTypes,
|
|
||||||
"Lcom/wurmonline/server/players/Titles$TitleType;",
|
|
||||||
"com/wurmonline/server/players/Titles$TitleType");
|
|
||||||
enumInitiator.addMethodIndex(Opcode.INVOKESPECIAL, "<init>",
|
|
||||||
"(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;ILcom/wurmonline/server/players/Titles$TitleType;)V",
|
|
||||||
this.className);
|
|
||||||
enumInitiator.addFieldIndex(Opcode.PUTSTATIC, enumData.fieldName, "Lcom/wurmonline/server/players/Titles$Title;",
|
|
||||||
this.className);
|
|
||||||
|
|
||||||
populateVALUES.addOpcode(Opcode.DUP);
|
|
||||||
populateVALUES.addInteger(valuesSize + extensionCounter);
|
|
||||||
extensionCounter++;
|
|
||||||
populateVALUES.findFieldIndex(Opcode.GETSTATIC, enumData.fieldName, "Lcom/wurmonline/server/players/Titles$Title;",
|
|
||||||
this.className);
|
|
||||||
populateVALUES.addOpcode(Opcode.AASTORE);
|
|
||||||
}
|
|
||||||
// Do bytecode changes from the bottom up so bytecode indexes don't change after every insert.
|
|
||||||
initiatorCodeIterator.insert(populateVALUESIndex, populateVALUES.get());
|
|
||||||
resizeEnumVALUES();
|
|
||||||
initiatorCodeIterator.insert(valuesSizerIndex, enumInitiator.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
package mod.sin.wyvern.mastercraft;
|
|
||||||
|
|
||||||
import com.wurmonline.server.Server;
|
|
||||||
import com.wurmonline.server.items.Item;
|
|
||||||
import com.wurmonline.server.players.Titles;
|
|
||||||
import com.wurmonline.server.skills.Skill;
|
|
||||||
import com.wurmonline.server.skills.SkillList;
|
|
||||||
import javassist.*;
|
|
||||||
import javassist.bytecode.BadBytecode;
|
|
||||||
import javassist.expr.ExprEditor;
|
|
||||||
import javassist.expr.MethodCall;
|
|
||||||
import mod.sin.lib.Util;
|
|
||||||
import org.gotti.wurmunlimited.modloader.ReflectionUtil;
|
|
||||||
import org.gotti.wurmunlimited.modloader.classhooks.HookManager;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
public class Mastercraft {
|
|
||||||
private static Logger logger = Logger.getLogger(Mastercraft.class.getName());
|
|
||||||
public static double getNewDifficulty(Skill skill, double diff, Item item){
|
|
||||||
if(skill.affinity > 0){
|
|
||||||
diff -= skill.affinity;
|
|
||||||
}
|
|
||||||
if(skill.getKnowledge() > 99.0d){
|
|
||||||
diff -= 2d-((100d-skill.getKnowledge())*2d);
|
|
||||||
}
|
|
||||||
if(skill.getKnowledge() > 90.0d){
|
|
||||||
diff -= 2d-((100d-skill.getKnowledge())*0.2d);
|
|
||||||
}
|
|
||||||
if(item != null){
|
|
||||||
if(item.getRarity() > 0){
|
|
||||||
diff -= item.getRarity();
|
|
||||||
}
|
|
||||||
if(item.getCurrentQualityLevel() > 99.0f){
|
|
||||||
diff -= 1d-((100d-item.getCurrentQualityLevel())*1d);
|
|
||||||
}
|
|
||||||
if(item.getCurrentQualityLevel() > 90.0f){
|
|
||||||
diff -= 1d-((100d-item.getCurrentQualityLevel())*0.1d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
public static float getCastPowerIncrease(Skill skill){
|
|
||||||
double addedPower = 0;
|
|
||||||
if(skill.affinity > 0){
|
|
||||||
addedPower += 2*skill.affinity;
|
|
||||||
}
|
|
||||||
if(skill.getKnowledge() > 0){
|
|
||||||
float lowFloat1 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat());
|
|
||||||
float lowFloat2 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat());
|
|
||||||
addedPower += Math.min(skill.getKnowledge()*lowFloat1, skill.getKnowledge()*lowFloat2);
|
|
||||||
}else{
|
|
||||||
logger.warning("Error: Some player just tried casting with no channeling skill!");
|
|
||||||
}
|
|
||||||
return (float) addedPower;
|
|
||||||
}
|
|
||||||
public static float getFavorCostMultiplier(Skill skill){
|
|
||||||
float mult = 1f;
|
|
||||||
if(skill.affinity > 0){
|
|
||||||
mult -= skill.affinity*0.02f; //2% reduction per affinity
|
|
||||||
}
|
|
||||||
if(skill.getKnowledge() > 90d){
|
|
||||||
mult -= 0.1d-((100d-skill.getKnowledge())*0.01d);
|
|
||||||
}
|
|
||||||
if(skill.getKnowledge() > 99d){
|
|
||||||
mult -= 0.1d-((100-skill.getKnowledge())*0.1d);
|
|
||||||
}
|
|
||||||
return mult;
|
|
||||||
}
|
|
||||||
/*public static void addNewTitles(){
|
|
||||||
try {
|
|
||||||
ExtendTitleEnum.builder("com.wurmonline.server.players.Titles$Title");
|
|
||||||
// GM/Developer Titles
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Game_Master", 2500, "Game Master", "Game Master", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Developer", 2501, "Developer", "Developer", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pet_Me", 2502, "Pet Me", "Pet Me", -1, "NORMAL");
|
|
||||||
|
|
||||||
// Troll Titles
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Macro_King", 550, "Macro King", "Macro King", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Drama_Queen", 551, "Drama Queen", "Drama Queen", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Zergling", 552, "Zergling", "Zergling", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Special_Title", 553, "Special Guy", "Special Girl", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Prophet_Ear", 554, "Prophet Ear", "Prophet Ear", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Koza", 555, "Koza", "Koza", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Wyvern_Hunter", 556, "Wyvern Hunter", "Wyvern Hunter", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Overlord", 557, "Overlord", "Overlord", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Troll", 558, "Troll", "Troll", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Beggar", 559, "Beggar", "Beggar", -1, "NORMAL");
|
|
||||||
|
|
||||||
// Contest Titles
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Home_Decorator", 600, "Home Decorator", "Home Decorator", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Arena_Champion", 601, "Champion of the Arena", "Champion of the Arena", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pastamancer", 602, "Pastamancer", "Pastamancer", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pizzamancer", 603, "Pizzamancer", "Pizzamancer", -1, "NORMAL");
|
|
||||||
|
|
||||||
// Special Event Titles
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Titan_Slayer", 700, "Titanslayer", "Titanslayer", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Spectral_Slayer", 701, "Spectral Warrior", "Spectral Warrior", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Holdstrong_Architect", 702, "Holdstrong Architect", "Holdstrong Architect", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Stronghold_Architect", 703, "Stronghold Architect", "Stronghold Architect", -1, "NORMAL");
|
|
||||||
|
|
||||||
// Donation titles
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Donator", 800, "Donator", "Donator", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pazza_FavoriteGM", 801, "Sindusks Favourite GM", "Sindusks Favourite GM", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Warriorgen_ThatGuy", 802, "That Guy", "That Guy", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Eternallove_WarriorgensWife", 803, "Warriorgens Wife", "Warriorgens Wife", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Bambam_ThornOne", 804, "Thorn One", "Thorn One", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Svenja_CareDependant", 805, "The care-dependent", "The care-dependent", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Alexia_TheTreasuring", 806, "The Treasuring", "The Treasuring", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Reevi_ScienceGuy", 807, "Science Guy", "Science Guy", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Genocide_GrandDesigner", 808, "Grand Designer", "Grand Designer", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Seleas_CrazyCatLord", 809, "The Crazy Cat Lord", "The Crazy Cat Lord", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Piratemax_Slave", 810, "Slave", "Slave", -1, "NORMAL");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Eltacolad_TrueTaco", 811, "The One True Taco", "The One True Taco", -1, "NORMAL");
|
|
||||||
|
|
||||||
// Skill Titles (100)
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Archery_Legendary", 1500, "Legendary Marksman", "Legendary Marksman", 1030, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Body_Legendary", 1501, "Hercules", "Hercules", 1, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Axes_Legendary", 1502, "Viking", "Viking", 1003, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Baking_Legendary", 1503, "Patissier", "Patissier", 10039, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Archaeology_Legendary", 1504, "Curator", "Curator", 10069, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("CarvingKnife_Legendary", 1505, "Woodsculptor", "Woodsculptor", 10007, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Taming_Legendary", 1506, "King of the Jungle", "Queen of the Jungle", 10078, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Climbing_Legendary", 1507, "Moonwalker", "Moonwalker", 10073, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Tracking_Legendary", 1508, "Bloodhound", "Bloodhound", 10018, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Clubs_Legendary", 1509, "Bam Bam", "Bam Bam", 1025, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Catapults_Legendary", 1510, "Castle Crasher", "Castle Crasher", 10077, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Firemaking_Legendary", 1511, "Incendiary", "Incendiary", 1010, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Gardening_Legendary", 1512, "Earthbound", "Earthbound", 10045, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Hammers_Legendary", 1513, "Doomhammer", "Doomhammer", 1027, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Locksmithing_Legendary", 1514, "Vault Smith", "Vault Smith", 10034, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Religion_Legendary", 1515, "Chosen", "Chosen", 1026, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Yoyo_Legendary", 1516, "String Theorist", "String Theorist", 10050, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Nature_Legendary", 1517, "Naturalist", "Naturalist", 1019, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Mind_Legendary", 1518, "Enlightened", "Enlightened", 2, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Mauls_Legendary", 1519, "Breaker", "Breaker", 1004, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Shipbuilding_Legendary", 1520, "Naval Engineer", "Naval Engineer", 10082, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("NaturalSubstances_Legendary", 1521, "Biochemist", "Biochemist", 10042, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("WarMachines_Legendary", 1522, "Eradicator", "Eradicator", 1029, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Thievery_Legendary", 1523, "Shadow", "Shadow", 1028, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Swords_Legendary", 1524, "Samurai", "Samurai", 1000, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().addExtendEntry("Forestry_Legendary", 1525, "Silvanus", "Mother Nature", 10048, "LEGENDARY");
|
|
||||||
ExtendTitleEnum.getSingletonInstance().ExtendEnumEntries();
|
|
||||||
|
|
||||||
} catch (BadBytecode | ClassNotFoundException | NotFoundException | CannotCompileException e) {
|
|
||||||
logger.warning(e.getMessage());
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public static void changeExistingTitles(){
|
|
||||||
for (Titles.Title title : Titles.Title.values()) {
|
|
||||||
if (Objects.equals("Pumpkin King", title.getFemaleName())){
|
|
||||||
try {
|
|
||||||
ReflectionUtil.setPrivateField(title, ReflectionUtil.getField(title.getClass(), "femaleName"), "Pumpkin Queen");
|
|
||||||
} catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void preInit(){
|
|
||||||
try {
|
|
||||||
ClassPool classPool = HookManager.getInstance().getClassPool();
|
|
||||||
Class<Mastercraft> thisClass = Mastercraft.class;
|
|
||||||
|
|
||||||
// - Reduce skill check difficulty with high skills or tools - //
|
|
||||||
CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill");
|
|
||||||
|
|
||||||
/*ctSkill.getDeclaredMethod("checkAdvance").insertBefore(""
|
|
||||||
+ "$1 = "+Mastercraft.class.getName()+".getNewDifficulty(this, $1, $2);");*/
|
|
||||||
Util.setReason("Modify difficulty for skill checks in MasterCraft.");
|
|
||||||
String replace = "$1 = "+Mastercraft.class.getName()+".getNewDifficulty(this, $1, $2);";
|
|
||||||
Util.insertBeforeDeclared(thisClass, ctSkill, "checkAdvance", replace);
|
|
||||||
|
|
||||||
// - Increase spellcasting power for skilled channelers - //
|
|
||||||
CtClass ctSpell = classPool.get("com.wurmonline.server.spells.Spell");
|
|
||||||
CtMethod[] ctRuns = ctSpell.getDeclaredMethods("run");
|
|
||||||
for(CtMethod method : ctRuns){
|
|
||||||
method.instrument(new ExprEditor(){
|
|
||||||
public void edit(MethodCall m) throws CannotCompileException {
|
|
||||||
if (m.getMethodName().equals("doEffect")) {
|
|
||||||
m.replace("$2 += "+Mastercraft.class.getName()+".getCastPowerIncrease(castSkill);"
|
|
||||||
+ "$_ = $proceed($$);");
|
|
||||||
logger.info("Instrumented doEffect in run()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
method.instrument(new ExprEditor(){
|
|
||||||
public void edit(MethodCall m) throws CannotCompileException {
|
|
||||||
if (m.getMethodName().equals("depleteFavor")) {
|
|
||||||
m.replace("$1 *= "+Mastercraft.class.getName()+".getFavorCostMultiplier(castSkill);"
|
|
||||||
+ "$_ = $proceed($$);");
|
|
||||||
logger.info("Instrumented depleteFavor in run()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (CannotCompileException | NotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user