diff --git a/build.gradle b/build.gradle index ab276ea..c5e79dc 100644 --- a/build.gradle +++ b/build.gradle @@ -11,8 +11,9 @@ repositories { } dependencies { - compile 'org.gotti.wurmunlimited:server-modlauncher:0.43-beta1' + compile 'org.gotti.wurmunlimited:server-modlauncher:0.43' compile 'com.github.Sindusk:sindusklibrary:v2.2' + compile 'com.github.bdew-wurm:bdew_server_mod_tools:v1.0.0' compile 'com.github.Sindusk:DiscordRelay:v1.2' compile 'com.github.Sindusk:DUSKombat:v1.0' compile 'com.github.Sindusk:TreasureHunting:1.1.4' diff --git a/mods/WyvernMods.properties b/mods/WyvernMods.properties index 3b8b85c..5aa6675 100644 --- a/mods/WyvernMods.properties +++ b/mods/WyvernMods.properties @@ -1,6 +1,524 @@ classname=mod.sin.wyvern.WyvernMods classpath=WyvernMods.jar sharedClassLoader=true -depend.import=SinduskLibrary,TreasureHunting,DiscordRelay -#If true, will print debug messages and log heavily. -debug=true \ No newline at end of file + +# Bdew's Server Mod Tools mod is required for operation of WyvernMods. +depend.requires=bdew_server_mod_tools + +# These other mods are required to be installed. Each one is able to be configured to avoid operation. +depend.import=SinduskLibrary,TreasureHunting,DiscordRelay,DUSKombat + +# If automata is installed, it should be loaded first to avoid conflict. It is not required. +depend.suggests=automata + +# -- Introduction -- # +# WyvernMods contains many different modules. Each configuration section is separated based on the module it controls. +# Each module has a "master" configuration which completely enables or disables the module. +# If a master configuration is disabled, all the further configurations do not need to be adjusted. +# There may also be sub-modules that can be enabled and disabled. +# Module configurations are separated by formatted comments in this configuration file: + +## >> MAJOR MODULE << ## +# > MINOR MODULE < # +# > END MINOR MODULE < # +## >> END MAJOR MODULE << ## + +# Finally, there will also be configurations which are open-ended and allow an unlimited amount of configurations. +# These configurations will be annotated with "-#" appended to the configuration. +# These will always be identified with a dash in the configuration. For example, "itemCreation-1:" +# Every individual configuration made in this way needs it's own unique number after it (called an index). +# Multiple configurations with the same index will not apply properly. Make sure each configuration has it's own unique index. +# Finally, all multiple configurations will be separated using a colon (:) instead of an equals sign (=). + +## >> MISCELLANEOUS CHANGES MODULE << ## +## The Miscellaneous Changes module includes various bugfixes and QoL improvements that affect gameplay. +enableMiscChangesModule=true + +# > INFO TAB < # +# The information tab is a tab which appears for all players on login. +enableInfoTab=true +#infoTabName: The name of the tab to display when the players log in. +infoTabName=Server +#infoTabLine-#: Line to be added to the info tab on login. +# This is a multiple configuration option. +infoTabLine-1:Server Thread: https://forum.wurmonline.com/index.php?/topic/162067-revenant-modded-pvepvp-3x-action-new-skillgain/ +infoTabLine-2:Website/Maps: https://www.sarcasuals.com/ +infoTabLine-3:Server Discord: https://discord.gg/r8QNXAC +infoTabLine-4:Server Data: https://docs.google.com/spreadsheets/d/1yjqTHoxUan4LIldI3jgrXZgXj1M2ENQ4MXniPUz0rE4 +infoTabLine-5:Server Wiki/Documentation: https://docs.google.com/document/d/1cbPi7-vZnjaiYrENhaefzjK_Wz7_F1CcPYJtC6uCi98/edit?usp=sharing +infoTabLine-6:Patreon: https://www.patreon.com/sindusk +# > END INFO TAB < # + +#ignoreBridgeChecks: Disable most bridge validity checks, allowing them to be built in/over/through houses. +ignoreBridgeChecks=true +#disableMailboxUsageWhileLoaded: Disables the usage of mailboxes while they're loaded in a vehicle. +# This option is used in tandem with the ability to allow mailboxes to be loaded. +# If they cannot be loaded, this option will do nothing. +disableMailboxUsageWhileLoaded=true +#increasedLegendaryCreatures: Changes the chances for a legendary creature (AKA "Uniques") to spawn when checked. +# This can be used for multiple purposes, including disabling natural unique spawns altogether. +# Use the next setting while this option is enabled to tweak how you want them to spawn. +increasedLegendaryCreatures=true +#increasedLegendaryFrequency: The amount of times to check for a legendary to spawn when they are checked (6 hours). +# 0 = Disable legendary creatures from spawning altogether. +# 1 = Vanilla settings for spawning legendary creatures. +# 2 = Double the default chance for legendary to spawn when checked. +# 5 = Five times the default chance for legendary to spawn when checked. +increasedLegendaryFrequency=5 +#allowFacebreykerNaturalSpawn: Adds Facebreyker (custom creature from WyvernMods) to the natural spawn list for legendary creatures. +allowFacebreykerNaturalSpawn=true +#announcePlayerTitles: When players obtain a title, there will be a server message stating they've just earned it. +# The announcement ignores any title obtained on a PvP server, as well as any titles gained by GM's (power 1 or higher). +# This will also create a message in Discord via DiscordRelay to the "event" channel. +announcePlayerTitles=true +# TODO: Allow editing the tab that it announces the title and the discord channel it sends to. +#improveCombinedLeather: If leather is able to be combined (via other configuration), it will by default prevent improving items with higher QL than the material. +# This option overrides that interaction, and allows leather of any QL be used to improve despite it being able to be combined. +improveCombinedLeather=true +#allowModdedImproveTemplates: Enables the usage of modded improve templates while improving certain items (Spectral Hide & Glimmerscale). +allowModdedImproveTemplates=true +#fatigueActionOverride: Allows players to take fatiguing actions (improve, farming, mining, etc.) while not grounded. +# This means players can mine from a wagon, farm from a cart, improve on their horse, etc. +# An exception to this is destroy actions on PvP servers. They have special handling to disable their usage while mounted. +fatigueActionOverride=true +#fixPortalIssues: Fixes some kind of portal issues. Don't remember what caused this change to be made or what it does. +fixPortalIssues=true +#disableMinimumShieldDamage: By default, shields take a minimum of 0.01 damage each time they're hit. +# This option disables that threshhold and allows shields to take less than 0.01 damage when hit. +# Specifically, if a shield is made of adamantine or similar, it would always take less damage than one made from iron. +disableMinimumShieldDamage=true +#disableGMEmoteLimit: By default, players must wait 5 seconds before the sound from another emote will play. +# This option allows GM's (power 1 or higher) to bypass this limit. +# This change was made so I could rapidly slap my GM's or players when they upset me by binding a key with Bdew's custom actions mod. +# Instead of only seeing the event tab messages from the slap assault, they would also hear each and every excruciating slap. +disableGMEmoteLimit=true +#creatureArcheryWander: When a creature is struck by an arrow from a long distance, they will fail to acquire the player as a target. +# This prevents them from moving in to attack someone who is archering them. +# In some cases, players were able to abuse this to gain archery skill at zero risk. +# This option makes creatures wander slightly in a random direction after being hit by archery. +# Usually, this results in them moving close enough to the player to acquire them as a target +# and engage them in melee combat or far enough the player cannot archer anymore. +creatureArcheryWander=true +#globalDeathTabs: Broadcast death tabs to GL-Freedom on all servers. +# This does not override the Deaths tab on the server the player died on. +# It just humiliates them globally instead of just on that server. +globalDeathTabs=true +#disablePvPOnlyDeathTabs: Allows PvP deaths on a PvE server to be broadcast in the Deaths tab. +disablePvPOnlyDeathTabs=true +#fixLibilaCrossingIssues: There were issues where Libila priest faith would reset when crossing servers. +# This was a fix attempted to prevent it. It may no longer be necessary as of the 1.9 Priest Update but does no harm being enabled. +fixLibilaCrossingIssues=true +#higherFoodAffinities: Increases the potency of food affinity skill gains from 10% to 30%. +higherFoodAffinities=true +#TODO: Allow adjustment of the percentage increase (and potentially reduction) of food affinities. +#fasterCharcoalBurn: Increases the rate at which charcoal burns by double. +# It does this by triggering the "production" each time it ticks twice, applying double damage afterwards. +# It will produce the same amount of resources, but do so twice as quickly. +fasterCharcoalBurn=true +#TODO: Allow further adjustment of the rate at which charcoal burns. +#uncapTraderItemCount: By default, traders can only show 9 of each item they have in stock. +# This option removes that cap, and allows them to show their full stock of each item. +uncapTraderItemCount=true +#logExcessiveActions: Log any player performing more than 10 commands in a single second. +# This is useful to catch potential macro's, but also has false positives! +# It will log players who hold down a key for a command for example. +logExcessiveActions=true + +# > DYNAMIC SKILL RATE < # +# Dynamic Skill Rate is a new skill rate system that adjusts the skill gain rate as skill increase. +# For reference, please see the Revenant Skill Gain graph: https://i.imgur.com/XQeMJjV.png +useDynamicSkillRate=true +#TODO: Add options to adjust the dynamic skill gain rates. +#> END DYNAMIC SKILL RATE < # + +#reduceLockpickBreaking: Adds 40QL to the calculations when a lockpick is checking whether it should break. +# This results in a much lower rate of lockpicks breaking. They still take damage when lockpicking. +reduceLockpickBreaking=true +#allowFreedomMyceliumAbsorb: Allows players on Freedom servers that follow Libila to absorb mycelium. +allowFreedomMyceliumAbsorb=true +#largerHouses: Doubles the size that players can construct buildings. +# It does this by multiplying their effective carpentry during planning checks. +largerHouses=true +#TODO: Add option to adjust the carpentry multiplier. +#reduceImbuePower: Reduces the amount of power applied by smearing imbues. +# This does not affect their functionality, simply reduces the amount of power applied per imbue to 1/5th. +reduceImbuePower=true +#TODO: Add option to adjust multiplier on imbue power. +#fixVehicleSpeeds: When updating the speed of a vehicle, the vanilla code uses a random check to determine whether to update. +# This creates scenarios where the speed of a vehicle does not update properly for a long duration. +# For example, when archering a horse, it could take anywhere from 1 to 20 seconds for the speed to properly reduce. +# This option removes that random check and forces it to update immediately whenever the vehicle speed would change. +fixVehicleSpeeds=true +#reduceMailingCosts: Reduces mailing costs from 1 copper to 10 iron. +reduceMailingCosts=true +#TODO: Add option to adjust mailing cost to a percentage of default. +#guardTargetChanges: Prevent guards from assisting in combat with some of the stronger modded creatures. +# Includes: Legendary Creatures, Titans, and Rare Spawns. +guardTargetChanges=true +#enableLibilaStrongwallPvE: Enables Strongwall for Libila on Freedom/PvE servers. +enableLibilaStrongwallPvE=true +#royalCookNoFoodDecay: Royal Cooks (kingdom title) will create "royal" food which is immune to decay. +royalCookNoFoodDecay=true +#mayorsCommandAbandonedVehicles: Allows mayors to take temporary command of vehicles abandoned on their deed. +# This does not allow them to access the contents/hold of the vehicle. +# They can only command the vehicle if it is within their village. +# The vehicle must belong to a player who has not logged in for 7 days. +# If they move the vehicle off their deed and disembark, they will no longer be able to command it. +mayorsCommandAbandonedVehicles=true +#opulenceFoodAffinityTimerIncrease: Adds 0.25% increased timer per power of opulence on a food. +# Example: Food grants 1 minute per bite. With 100 Opulence, it would gain 25% increased timer, giving 1.25 minutes per bite. +opulenceFoodAffinityTimerIncrease=true +#TODO: Add option to configure the amount of increase per opulence power. [Side-note: Maybe add to Spellcraft instead] +#disableFoodFirstBiteBonus: By default, when eating food the affinity timer will give 10x longer duration on the first bite. +# This creates a meta where taking a single bite out of a good affinity meal then waiting for the buff to expire is optimal to conserve food. +# This option disables that first bite bonus, making each bite grant the same duration regardless of whether it's the first +# bite or if they're adding onto an already existing food affinity timer. +disableFoodFirstBiteBonus=true +#bedQualitySleepBonus: The quality of the bed a player sleeps in will increase the amount of sleep bonus obtained after waking up. +# The increase in sleep bonus is equivalent to 0.5% more per QL of the bed. At 100QL, the bed will grant 50% more sleep bonus. +bedQualitySleepBonus=true +#TODO: Add option to configure the amount of bonus the bed QL grants. +#royalSmithImproveFaster: Royal Smiths (kingdom title) will improve smithing items 10% faster. +# This bonus is comparable to having 10 additional Wind of Ages power on the tools using to improve with. +royalSmithImproveFaster=true +#TODO: Add option to configure improve speed bonus. +#fixMountedBodyStrength: When body strength is modded to allow higher carry weights, mounts do not register the increase. +# Issues such as being unable to move on a horse because it thinks you're over encumbered begin to crop up. +# This option fixes that interaction by making the code which handles mounted encumberance to adjust for the increase in strength. +fixMountedBodyStrength=true +#adjustedFoodBiteFill: Adjusts the amount of fill from foods from being linear along the QL axis. +# Instead, it grants more fill than usual at lower QL, but drops off to less fill per QL at higher QL. +# See this graph for the difference: https://i.imgur.com/RsBo86z.png +adjustedFoodBiteFill=true +#TODO: Add additional options to configure the amount of food fill. +#rareMaterialImprove: Allows rare materials to potentially transfer rarity when improving normally, instead of only when consumed. +# This prevents players from being punished by combining rare materials, and offers a more intuitive approach to using rare materials. +rareMaterialImprove=true +#rarityWindowBadLuckProtection: This provides a new system that creates "bad luck protection" in rarity windows. +# Instead of being entirely random, the chance for a rarity window will increase each time the roll fails. +# Every time the roll succeeds, the chance will decrease to adjust. This creates a more even spread of RNG. +# Mathematically, this also helps prevent outliers such as having multiple rarity windows in a row or the opposite of not having any for a long duration. +rarityWindowBadLuckProtection=true +#rareCreationAdjustments: Rarity from creation materials will apply when creating new items. +# The following system only applies to items which are created in their entirety from two consumable resources. +# For example, using a rare handle and a rare sword blade to create a sword would use this system. +# Using a rare anvil and a rare lump will not use this system, since the anvil is not consumed in the process. +# Metallurgy does work. Using rare charcoal with rare iron will produce rare steel, for example. +# When the item is created, it will roll randomly between the two rarities of the resources used to create it, distributed equally. +# For example, using a rare handle with a supreme blade will give a 50% chance at a rare, and 50% chance at a supreme. +# Using a normal handle on that same supreme blade would yield a 33% chance at normal, 33% chance at rare, and 33% chance at supreme. +# Using a fantastic handle on the supreme blade would offer a 50% chance at supreme, 50% chance on fantastic. +# If both items are the same rarity, it completely guarantees that the resulting item will be the same rarity. +# A fantastic handle and a fantstic blade will always create a fantastic sword. +rareCreationAdjustments=true +#alwaysArmourTitleBenefits: Armour titles grant a bonus to improvement when equipped. +# This option grants these bonuses at all times even if the title is not equipped. +alwaysArmourTitleBenefits=true +#tomeUsageAnyAltar: Allows sorcery tomes to be used at any 3x3 flat altar. +# This removes height restrictions, being near water, in a cave, etc. Any flat 3x3 area with an altar will work to use the tome. +tomeUsageAnyAltar=true +#keyOfHeavensLoginOnly: Forces Key of the Heavens to only be able to be used on the login server. +# This is done to prevent issues with deity generation. +keyOfHeavensLoginOnly=true +#lessFillingDrinks: Makes drinks (not water) fill less of the water bar (roughly 1/5 as much as default). +# This allows players to get more use out of affinity drinks. +lessFillingDrinks=true +#TODO: Add additional options to adjust how much less filling drinks are. +#disableHelpGMCommands: Disables GM commands from appearing for non-GM's when using /help. This is a bug with the vanilla game. +disableHelpGMCommands=true +#reduceActionInterruptOnDamage: Reduces the chances of actions being interrupted when taking damage. +# The reduction should be something around 1/2 as likely to be interrupted, though it's hard to tell for sure. +reduceActionInterruptOnDamage=true +#TODO: Add multiplier option for chance to be interrupted. +#fixMissionNullPointerException: In rare instances, the Epic Mission system can fail to properly intialize it's item template list. +# When this happens, there's a chance that another function will call for a random item template. +# Upon execution, it fails to find a random template and crashes the server with a Null Pointer Exception. +# This option fixes this issue and will initialize the list if one does not exist when the server calls for a random template. +fixMissionNullPointerException=true +#disableSmeltingPots: Simply disables the functionality of smelting pots. +# Smelting pots will still exist, but it will display an error "Smelting is disabled." when attempting to smelt. +disableSmeltingPots=true +#hideSorceryBuffBar: Hides the buff icons for sorceries. They can still be found in the Spell Effects window. +hideSorceryBuffBar=true +#sqlAchievementFix: Fixes the errors that occur with achievements in SQL in WU 1.9. +sqlAchievementFix=true + +## >> END MISCELLANEOUS CHANGES MODULE << ## + +## >> ARENA MODULE << ## +## The Arena Module handles many miscellaneous tweaks and additions specific to PvP servers. +## Some of the options here can also have positive impact on PvE servers and were configured here because there was +## overlap in the code where the functionality for Arena-specific features had to be made. +enableArenaModule=true + +#equipHorseGearByLeading: Allow players to equip horse gear by simply leading. +# If enabled, this also allows GM's (power 1 and higher) to bypass all restrictions for equipping items on creatures for both PvE and PvP servers. +equipHorseGearByLeading=true +#lockpickingImprovements: Reduces the restrictions for allowing lockpicking. +# On PvP servers, this will make it so basically any container is able to be lockpicked by anyone without permissions getting in the way. +# On PvE servers, this allows players to lockpick chests which are not owned by a player (such as treasure chests from TreasureHunting mod). +lockpickingImprovements=true +#placeDeedsOutsideKingdomInfluence: Allows placing deeds outside of kingdom influence for all kingdoms. +# Keep in mind this also removes the requirement of creating a tower before planting a deed. +placeDeedsOutsideKingdomInfluence=true +#disablePMKs: Disables the ability to create a Player Made Kingdom. +disablePMKs=true +#disablePlayerChampions: Disables the ability for players to become a Champion. +disablePlayerChampions=true +#arenaAggression: Adjusts the aggression for creatures and players towards other players to fit a same-kingdom PvP environment. +arenaAggression=true +#enemyTitleHook: Allows (ENEMY) to be appended to players who are hostile towards eachother in a same-kingdom PvP environment. +# On PvE servers, this also the hook for the extra custom title module. +enemyTitleHook=true +#enemyPresenceOnAggression: Adjusts the enemy presence mechanic to work based on the aggression of a player instead of kingdom. +# By default, in same-kingdom PvP enviornments, a player of the same kingdom will not apply enemy presence in local. +# This option makes it so even if the player is in the same kingdom, if they are considered hostile to the player they will apply enemy presence. +enemyPresenceOnAggression=true +#disableFarwalkerItems: Disables farwalker twigs and farwalker stones on PvP servers. +disableFarwalkerItems=true +#alwaysAllowAffinitySteal: Always allow players to steal affinities from players they slay in PvP combat. +alwaysAllowAffinitySteal=true +#adjustFightSkillGain: Increases fight skill gained on PvP servers by 50%. +# It does this by adding an additional tick of fight skill gain equivalent to 50% of the first tick. +adjustFightSkillGain=true +#TODO: Add additional option to adjust fight skill gain multiplier. +#useAggressionForNearbyEnemies: Changes the check for nearby enemies to use aggression instead of kingdom checks. +# This option is meant to help enable same-kingdom PvP environments. +useAggressionForNearbyEnemies=true +#disablePvPCorpseProtection: Disables the loot protection systems on corpses on PvP servers. +# This allows anyone, regardless of permission status, to loot a corpse when it drops. +disablePvPCorpseProtection=true +#bypassHousePermissions: This bypasses most of the permissions and restriction checks in houses for players on PvP servers. +# This option is meant to help enable same-kingdom PvP environments. +bypassHousePermissions=true +#allowStealingAgainstDeityWishes: Allows players to steal items against their deity wishes without being punished on PvP servers. +# This option is meant to help enable same-kingdom PvP environments. +allowStealingAgainstDeityWishes=true +#sameKingdomVehicleTheft: When a vehicle is unlocked, enemy kingdom players can "take ownership" by commanding the vehicle. +# This option is meant to help enable same-kingdom PvP environments by allowing players to take ownership +# of an unlocked vehicle even if it belongs to a player in the same kingdom as them. +sameKingdomVehicleTheft=true +#adjustMineDoorDamage: Increases the amount of damage done by bashing mine doors by 3x on PvP servers. +adjustMineDoorDamage=true +#TODO: Add option to adjust how much to multiply bash damage by. +#sameKingdomPermissionsAdjustments: Various adjustments to same-kingdom permissions. +# This option is meant to help enable same-kingdom PvP environments. +sameKingdomPermissionsAdjustments=true +#disableCAHelpOnPvP: Disables players from seeing the CA HELP window on PvP servers. +# This can be abused to allow players to see enemy CA's who are online. +disableCAHelpOnPvP=true +#sameKingdomVillageWarfare: Makes players in a village enemies with all other villages that are not in their alliance. +# This option is meant to help enable same-kingdom PvP environments. +sameKingdomVillageWarfare=true +#adjustHotARewards: Adjusts the rewards from winning Hunt of the Ancients. +# Keep in mind one of the rewards that gets added with this option is a key fragment (1/50th of a key of the heavens). +adjustHotARewards=true +#TODO: Add options to further customize the rewards from HotA. +#capMaximumGuards: Caps the maximum amount of guards in a village to 5. +capMaximumGuards=true +#TODO: Add option to configure maximum amount of guards. +#disableTowerConstruction: Disables the ability to construct towers on PvP servers. +# This does not remove existing towers or disable them from being spawned in by GM's. +disableTowerConstruction=true +#adjustLocalRange: Changes the local range on PvP servers from 80 tiles to 50 tiles. +adjustLocalRange=true +#TODO: Add option to configure new local range. +#disableKarmaTeleport: Disables the ability to use Karma Teleport on PvP servers. +disableKarmaTeleport=true +#limitLeadCreatures: Limits the amount of creatures players can lead on PvP servers to 1. +limitLeadCreatures=true +#TODO: Add option to configure how many creatures players can lead at a time. +#adjustBashTimer: Doubles the bash timer for destroying walls/structures. +# This option can be useful for high action speed servers, as the destroy timers are affected by action time multipliers. +adjustBashTimer=true +#TODO: Add option to adjust the base bash timer. +#discordRelayHotAMessages: Adds HotA messages to Discord Relay. +discordRelayHotAMessages=true +#TODO: Add this option to DiscordRelay instead with configuration of channel and similar. +#allowAttackingSameKingdomGuards: Allows players to attack guards of the same kingdom. +# This option is meant to help enable same-kingdom PvP environments. +allowAttackingSameKingdomGuards=true +#fixGuardsAttackingThemselves: If the server is configured for same-kingdom PvP, you can sometimes run into an issue. +# Guards will attempt to target themselves and see themselves as enemies, and try to attack themselves. +# Luckily the game does not allow them to fight themselves. However, they will spam the local log with messages. +# If you encounter this issue, enable this option to stop them from being stupid. +fixGuardsAttackingThemselves=true +#reducedMineDoorOpenTime: Reduces the amount of time a mine door stays open when an enemy passes through from 120 seconds to 30 seconds. +reducedMineDoorOpenTime=true +#allowSameKingdomFightSkillGains: Allow players to gain fight skill from killing members of the same kingdom. +# This option is meant to help enable same-kingdom PvP environments. +allowSameKingdomFightSkillGains=true +#allowArcheringOnSameKingdomDeeds: Allows archery against other players while they are on a same-kingdom deed. +# This option is meant to help enable same-kingdom PvP environments. +allowArcheringOnSameKingdomDeeds=true +#sendNewSpawnQuestionOnPvP: A new spawn question created when a player dies. +# The new spawn question allows them to respawn on another server instead of the one they died on. +# WARNING: I highly recommend disabling this option as it will not work on most servers. +sendNewSpawnQuestionOnPvP=true +#TODO: Improve this option into a minor module and make the new spawn question function well for servers that are not Revenant. +#sendArtifactDigsToDiscord: When a player digs up an artifact, this option will announce the artifact message in Discord. +# The message will be identical to the one found in the Area History for the server. +sendArtifactDigsToDiscord=true +#TODO: Add this option to DiscordRelay instead with configuration of channel and similar. +#makeFreedomFavoredKingdom: Makes Freedom always the favored kingdom on the server. Affects both PvE and PvP servers. +# This option is specifically meant to prevent PvP servers from creating epic missions which favor inactive kingdoms. +# In that way, it is sort of meant to enable same-kingdom PvP environments, but can be useful in other senses as well. +makeFreedomFavoredKingdom=true +#crownInfluenceOnAggression: Converts the Crown of Might influence effect (that grants CR) to affect allies instead of kingdom. +# This option is meant to help enable same-kingdom PvP environments. +crownInfluenceOnAggression=true +#disableOWFL: Disables players from dropping items on their corpse on PvP servers. This option will have no effect on PvE servers. +# OWFL = Open World Full Loot. This option is designed to make a PvP environment where players do not lose their inventory on death. +# This option essentially operates by making an always-functioning resurrection stone apply to every player that dies. +disableOWFL=true +#resurrectionStonesProtectSkill: Players with a resurrection stone will not lose skill upon death. Affects both PvE and PvP servers. +resurrectionStonesProtectSkill=true +#resurrectionStonesProtectFightSkill: Players with a resurrection stone will not lose fighting skill upon death. Affects both PvE and PvP servers. +resurrectionStonesProtectFightSkill=true +#resurrectionStonesProtectAffinities: Players with a resurrection stone will not lose affinities on death on PvP servers. +resurrectionStonesProtectAffinities=true +#bypassPlantedPermissionChecks: Removes all permission checks for if a player can move a planted item on PvP servers. +# This option is meant to help enable same-kingdom PvP environments. +bypassPlantedPermissionChecks=true + +## >> END ARENA MODULE << ## + +## >> CUSTOM TITLES MODULE << ## +## The Custom Titles Module allows configuration and addition of new titles. +enableCustomTitlesModule=true + +#addCustomTitle-#: Adds a custom title. Format: addTitle-#:titleId,maleTitle,femaleTitle,skillId,titleType +# titleId = Some value, preferably greater than 1000, used to index the title that you're adding. These need to be unique to each title. +# maleTitle = The title name when a male character is using the title. +# femaleTitle = The title name when a female character is using the title. +# skillId = The ID of the skill to award this title for. If you don't want to attach this to a skill or don't know what this means, use -1 to disable. +# titleType = The skill level to award at. NORMAL (50), MINOR (70), MASTER (90), LEGENDARY (100). If you aren't using a skillId, then use NORMAL. +addCustomTitle-1:19999,Patron,Patron,-1,NORMAL +addCustomTitle-2:20000,Donator,Donator,-1,NORMAL +addCustomTitle-3:20001,Sindusks Favourite GM,Sindusk Favourite GM,-1,NORMAL +addCustomTitle-4:20002,That Guy,That Guy,-1,NORMAL +addCustomTitle-5:20003,Warriorgens Wife,Warriorgens Wife,-1,NORMAL +addCustomTitle-6:20004,Thorn One,Thorn One,-1,NORMAL +addCustomTitle-7:20005,The care-dependent,The care-dependent,-1,NORMAL +addCustomTitle-8:20006,The Treasuring,The Treasuring,-1,NORMAL +addCustomTitle-9:20007,Science Guy,Science Guy,-1,NORMAL +addCustomTitle-10:20008,Grand Designer,Grand Designer,-1,NORMAL +addCustomTitle-11:20009,The Crazy Cat Lord,The Crazy Cat Lord,-1,NORMAL +addCustomTitle-12:20010,Slave,Slave,-1,NORMAL +addCustomTitle-13:20011,The One True Taco,The One True Taco,-1,NORMAL +addCustomTitle-14:20012,The Great Illuminaty,The Great Illuminaty,-1,NORMAL + +# Event Titles +addCustomTitle-100:10002,Pastamancer,Pastamancer,-1,NORMAL + +#awardTitle-#: Awards a title to a player on their next login. Format: awardTitle-#:titleId,playerName,playerName,playerName... +# titleId = The id of the title to award the player. This can be the ID of a default title or custom title. Both will work. +# playerName = The name of the player to award the title to. +# - The playerName option can be repeated for as many players you want to award the title to. +# Example: awardTitle-1:10000,Sindusk,Sindawn,Sinsalt +# If a player already has the title, the system will identify they've already received the title. +# It's safe to leave configurations here for players who have already claimed their title. +awardTitle-1:19999,Atticus +awardTitle-2:20000,Pazza,Warriorgen,Eternallove,Bambam,Svenja,Alexiaselena,Reevi,Seleas,Piratemax,Eltacolad +awardTitle-3:20001,Pazza +awardTitle-4:20002,Warriorgen +awardTitle-5:20003,Eternallove +awardTitle-6:20004,Bambam +awardTitle-7:20005,Svenja +awardTitle-8:20006,Alexiaselena +awardTitle-9:20007,Reevi +awardTitle-10:20008,Genocide +awardTitle-11:20009,Seleas +awardTitle-12:20010,Piratemax +awardTitle-13:20011,Eltacolad +awardTitle-14:20012,Atticus + +# Event Titles +awardTitle-100:10002,Critias + +## >> END CUSTOM TITLES MODULE << ## + +## >> ANTI-CHEAT MODULE << ## +## The Anti-Cheat Module helps mitigate client mods that allow players to utilize data that should never be sent. +## Wyvern Anti-Cheat does NOT prevent ESP mods. +## It does, however, do a fairly effective job at limiting the use of X-Ray and livemap for detecting ores they should not see. +enableAntiCheatModule=true + +# > SPOOF HIDDEN ORE < # +# Spoofing hidden ore is the process of falsifying information sent to the client to hide ore they should not be able to see. +# This process works by the server identifying whether or not a player should be able to see a vein of ore through various checks. +# For example, if a vein is surrounded by 4 cave walls, the player should not be able to see that ore since it's completely surrounded. +# This system will "spoof" the data sent from the server to clients in the strip (area) around the vein as normal rock. +# This prevents anyone from using a client mod to see the vein (X-Ray or Livemap for example) which would normally be obscured from view. +# The system will have no effect on veins which players should normally be able to see. Exposed veins are not spoofed. +# Finally, this is also unable to be countered through any client modding efforts. Since there is no difference between the data +# that is sent instead of a normal rock vein, no amount of client modding would be able to surpass this anti-cheat method. +enableSpoofHiddenOre=true +#prospectingVision: This system allows players with high prospecting skill to bypass the spoof system to a certain extent. +# In it's current implementation, after 20 prospecting, players will be allowed to see 1 tile out per 18 prospecting levels. +# For example, a player with 50 prospecting skill would receive proper information to their client up to 3 tiles into a wall. +# This system is meant to give information to players about what exists in a cave system without requiring them to prospect every wall. +prospectingVision=true +#TODO: Add additional options to the spoof hidden ore minor module to configure further operation. + +# > END SPOOF HIDDEN ORE < # + +#mapSteamIds: This option will map player SteamID's to their name in the modsupport database under SteamIdMap. +# Since this option's creation, there has been a STEAM_IDS table added to the wurmplayers database by default which logs Steam ID's on each login. +# The default system works by logging the access times for each Steam ID and when it was connected, alongside the duration of the login. +# Overall, the default system is more accurate, but it's also quite difficult to read at a glance. +# Viewing a single player's Steam ID will require cross referencing their player WurmID with the PLAYERS table. +# What this option does is make a table that is simply NAME and STEAMID, with one unique entry each. +# This makes it very easy to find a player's Steam ID and ban it, if necessary. +# Additionally, it makes it simple to know all the SteamID's which have been used to access a single account. +# ! This table & option is also required for other certain functions in WyvernMods ! +mapSteamIds=true + +## >> END ANTI-CHEAT MODULE << ## + +## >> QUALITY OF LIFE MODULE << ## +## The Quality Of Life Module includes some additions that improve the general quality of life of gameplay. +## Many of these options are built with a mindset of enhancing the play of normal players, +## but can be abused to significant gain by those who see them as an opportunity to make cheating easier. +## It's important to think of the abuse cases and whether or not you're okay with those abuse cases being +## available before enabling this module or its features. +enableQualityOfLifeModule=true + +#mineCaveToVehicle: Allows mining from cave wall directly into a vehicle while commander. +# Requires the fatigue action override under Misc Changes Module to function (otherwise you cannot mine while commanding a vehicle). +# When enabled, this will also deposit the ore directly into a BSB until full if one exists. +# If no BSB exists, it will deposit to crates until full. +# If no crates exist in the vehicle, it will simply mine into the cargo hold of the vehicle until it's full. +# If there is no space in the vehicle for the ore, it will mine to ground as normal until a full pile exists. +mineCaveToVehicle=true +#mineSurfaceToVehicle: Allows surface mining directly into a vehicle while commanding. +# This option is identical to mineCaveToVehicle, but applies to surface mining instead. +# Also requires fatigue action override in Misc Changes Module to function. +mineSurfaceToVehicle=true +#chopLogsToVehicle: Allows chopping up logs directly into a vehicle while commander. +# This option is identical to mineCaveToVehicle, but applies to chopping up logs instead. +# Also requires fatigue action override in Misc Changes Module to function. +chopLogsToVehicle=true +#statuetteAnyMaterial: Allows casting using a statuette of any material. +# By default, a statuette that is not made of gold or silver will not work for spell casting. +# This option changes that functionality by disregarding the material and only checking the item itself. +# Will not allow players to use incorrect statuettes for casting (such as statuette of Fo to cast as a Vynora priest). +statuetteAnyMaterial=true +#mineGemsToVehicle: Allows mining gems and other materials (like salt) directly to vehicle. +# This option is identical to mineCaveToVehicle, but handles tertiary materials like gems and salt instead. +# Also requires fatigue action override in Misc Changes Module to function. +mineGemsToVehicle=true +#regenerateStaminaOnVehicleAnySlope: Allows players to regenerate stamina while on a vehicle regardless of the slope underneath the vehicle. +# By default, if you are on a slope greater than 20 while on a vehicle, you do not regenerate stamina. +# This option removes the 20 slope limitation and allows players to regenerate stamina while on a vehicle so long as they are stationary. +regenerateStaminaOnVehicleAnySlope=true + +## >> END QUALITY OF LIFE MODULE << ## + +## >> TREASURE CHEST LOOT MODULE << ## +## 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. +enableTreasureChestLootModule=true + +# TODO: Add additional options to configure the loot granted from treasure chests. +## >> END TREASURE CHEST LOOT MODULE << ## diff --git a/src/main/java/mod/sin/items/ArrowPackHunting.java b/src/main/java/mod/sin/items/ArrowPackHunting.java index 8d26c97..bd5d867 100644 --- a/src/main/java/mod/sin/items/ArrowPackHunting.java +++ b/src/main/java/mod/sin/items/ArrowPackHunting.java @@ -28,7 +28,8 @@ public class ArrowPackHunting { itemBuilder.itemTypes(new short[]{ // {108, 146, 44, 21, 147, 113} - War Arrow ItemTypes.ITEM_TYPE_NAMED, ItemTypes.ITEM_TYPE_REPAIRABLE, - ItemTypes.ITEM_TYPE_WOOD + ItemTypes.ITEM_TYPE_WOOD, + ItemTypes.ITEM_TYPE_WEAPON }); itemBuilder.imageNumber((short) 760); itemBuilder.behaviourType((short) 1); diff --git a/src/main/java/mod/sin/items/ArrowPackWar.java b/src/main/java/mod/sin/items/ArrowPackWar.java index 30bd72a..b9421a7 100644 --- a/src/main/java/mod/sin/items/ArrowPackWar.java +++ b/src/main/java/mod/sin/items/ArrowPackWar.java @@ -28,7 +28,8 @@ public class ArrowPackWar { itemBuilder.itemTypes(new short[]{ // {108, 146, 44, 21, 147, 113} - War Arrow ItemTypes.ITEM_TYPE_NAMED, ItemTypes.ITEM_TYPE_REPAIRABLE, - ItemTypes.ITEM_TYPE_WOOD + ItemTypes.ITEM_TYPE_WOOD, + ItemTypes.ITEM_TYPE_WEAPON }); itemBuilder.imageNumber((short) 760); itemBuilder.behaviourType((short) 1); diff --git a/src/main/java/mod/sin/items/StatuetteCyberhusky.java b/src/main/java/mod/sin/items/StatuetteCyberhusky.java index 1923f25..9200543 100644 --- a/src/main/java/mod/sin/items/StatuetteCyberhusky.java +++ b/src/main/java/mod/sin/items/StatuetteCyberhusky.java @@ -17,10 +17,10 @@ import com.wurmonline.server.skills.SkillList; public class StatuetteCyberhusky implements ItemTypes, MiscConstants { public static Logger logger = Logger.getLogger(StatuetteCyberhusky.class.getName()); public static int templateId; - private String name = "statuette of Cyberhusky"; + private String name = "statuette of Reevi"; public void createTemplate() throws IOException{ ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.statuette.cyberhusky"); - itemBuilder.name(name, "statuettes", "A statuette resembling the artists interpretation of the deity Cyberhusky."); + itemBuilder.name(name, "statuettes", "A statuette resembling the artists interpretation of the deity Reevi."); itemBuilder.itemTypes(new short[]{ // {108, 52, 22, 44, 87, 92, 147} - Statuette ItemTypes.ITEM_TYPE_NAMED, ItemTypes.ITEM_TYPE_DECORATION, diff --git a/src/main/java/mod/sin/wyvern/AntiCheat.java b/src/main/java/mod/sin/wyvern/AntiCheat.java index a1fbd3d..bc29506 100644 --- a/src/main/java/mod/sin/wyvern/AntiCheat.java +++ b/src/main/java/mod/sin/wyvern/AntiCheat.java @@ -121,7 +121,7 @@ public class AntiCheat { return false; } private static int getDummyWallAntiCheat(int tilex, int tiley){ - return Tiles.encode(Tiles.decodeHeight(Server.caveMesh.data[tilex | tiley << Constants.meshSize]), Tiles.Tile.TILE_CAVE_WALL.id, Tiles.decodeData((int)Server.caveMesh.data[tilex | tiley << Constants.meshSize])); + return Tiles.encode(Tiles.decodeHeight(Server.caveMesh.data[tilex | tiley << Constants.meshSize]), Tiles.Tile.TILE_CAVE_WALL.id, Tiles.decodeData(Server.caveMesh.data[tilex | tiley << Constants.meshSize])); } public static void sendCaveStripAntiCheat(Communicator comm, short xStart, short yStart, int width, int height){ if (comm.player != null && comm.player.hasLink()) { @@ -149,7 +149,7 @@ public class AntiCheat { if(!(Tiles.decodeType(Server.caveMesh.getTile(xx, yy)) == Tiles.Tile.TILE_CAVE_EXIT.id)){ if(prospecting < 20 && isSurroundedByCaveWalls(xx, yy)){ bb.putInt(getDummyWallAntiCheat(xx, yy)); - }else if(prospecting > 20 && playerCanSeeVein(xx, yy, distance)){ + }else if(WyvernMods.prospectingVision && prospecting > 20 && playerCanSeeVein(xx, yy, distance)){ bb.putInt(Server.caveMesh.data[xx | yy << Constants.meshSize]); }else if(!isSurroundedByCaveWalls(xx, yy)){ bb.putInt(Server.caveMesh.data[xx | yy << Constants.meshSize]); @@ -178,6 +178,8 @@ public class AntiCheat { } } } + + @Deprecated public static boolean isVisibleThroughTerrain(Creature performer, Creature defender){ int trees = 0; //int treetilex = -1; @@ -230,6 +232,8 @@ public class AntiCheat { } return true; } + + @Deprecated public static boolean isVisibleToAntiCheat(Creature cret, Creature watcher) { if (!cret.isVisible()) { return cret.getPower() > 0 && cret.getPower() <= watcher.getPower(); @@ -276,17 +280,18 @@ public class AntiCheat { String replace; // - Change the caveStrip method to the custom one, so we can edit what the clients see! - // - CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); - replace = "{ mod.sin.wyvern.AntiCheat.sendCaveStripAntiCheat(this, $$); }"; - Util.setBodyDeclared(thisClass, ctCommunicator, "sendCaveStrip", replace); - /*ctCommunicator.getDeclaredMethod("sendCaveStrip").setBody("{" - + " mod.sin.wyvern.AntiCheat.sendCaveStripAntiCheat(this, $$);" - + "}");*/ + if (WyvernMods.enableSpoofHiddenOre) { + CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); + replace = "{ mod.sin.wyvern.AntiCheat.sendCaveStripAntiCheat(this, $$); }"; + Util.setBodyDeclared(thisClass, ctCommunicator, "sendCaveStrip", replace); + } - Util.setReason("Map Steam ID's to Modsupport table."); - CtClass ctLoginHandler = classPool.get("com.wurmonline.server.LoginHandler"); - replace = AntiCheat.class.getName()+".mapPlayerSteamId($1, $2);"; - Util.insertBeforeDeclared(thisClass, ctLoginHandler, "preValidateLogin", replace); + if (WyvernMods.mapSteamIds) { + Util.setReason("Map Steam ID's to Modsupport table."); + CtClass ctLoginHandler = classPool.get("com.wurmonline.server.LoginHandler"); + replace = AntiCheat.class.getName() + ".mapPlayerSteamId($1, $2);"; + Util.insertBeforeDeclared(thisClass, ctLoginHandler, "preValidateLogin", replace); + } // - Change the creature isVisibleTo method to the custom one, so we can edit what the clients see! - // /*CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); diff --git a/src/main/java/mod/sin/wyvern/Arena.java b/src/main/java/mod/sin/wyvern/Arena.java index 9ca0b76..b770a58 100644 --- a/src/main/java/mod/sin/wyvern/Arena.java +++ b/src/main/java/mod/sin/wyvern/Arena.java @@ -216,31 +216,19 @@ public class Arena { // - Allow horse gear to be added/removed from horses without branding or taming (PvP Only) - // CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); - replace = "if(this.player.getPower() > 0){" + - " $_ = this.player;" + - "}else if(com.wurmonline.server.Servers.isThisAPvpServer() && owner.getDominator() != this.player){" - + " $_ = owner.getLeader();" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_MOVE_INVENTORY", "getDominator", replace); - Util.instrumentDeclared(thisClass, ctCommunicator, "equipCreatureCheck", "getDominator", replace); - /*ctCommunicator.getDeclaredMethod("reallyHandle_CMD_MOVE_INVENTORY").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getDominator")) { - m.replace("if(com.wurmonline.server.Servers.isThisAPvpServer() && owner.getDominator() != this.player){" - + " $_ = owner.getLeader();" - + "}else{" - + " if(this.player.getPower() > 0){" - + " $_ = this.player;" - + " }else{" - + " $_ = $proceed($$);" - + " }" - + "}"); - return; - } - } - });*/ + if (WyvernMods.equipHorseGearByLeading) { + Util.setReason("Allow equipping horse gear without taming."); + replace = "if(this.player.getPower() > 0){" + + " $_ = this.player;" + + "}else if(com.wurmonline.server.Servers.isThisAPvpServer() && owner.getDominator() != this.player){" + + " $_ = owner.getLeader();" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_MOVE_INVENTORY", "getDominator", replace); + Util.setReason("Allow equipping horse gear without taming."); + Util.instrumentDeclared(thisClass, ctCommunicator, "equipCreatureCheck", "getDominator", replace); + } // - Allow lockpicking on PvP server, as well as treasure chests on PvE - // CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); @@ -256,69 +244,72 @@ public class Arena { CtClass.floatType }; String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1); - Util.setReason("Allow lockpicking on the PvP server and improve PvE treasure chest lockpicking."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = true;" - + "}else{" - + " $_ = target.getLastOwnerId() == -10 || target.getLastOwnerId() == 0 || target.getTemplateId() == 995;" - + "}"; - Util.instrumentDescribed(thisClass, ctItemBehaviour, "action", desc1, "isInPvPZone", replace); - CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems"); - replace = "$_ = $proceed($$);" - + "if($_ == -10 || $_ == 0){ ok = true; }"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "picklock", "getLastOwnerId", replace); - /*ctMethodsItems.getDeclaredMethod("picklock").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getLastOwnerId")) { - m.replace("$_ = $proceed($$);" - + "if($_ == -10 || $_ == 0){ ok = true; }"); - return; - } - } - });*/ + if (WyvernMods.lockpickingImprovements) { + Util.setReason("Allow lockpicking on the PvP server and improve PvE treasure chest lockpicking."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = target.getLastOwnerId() == -10 || target.getLastOwnerId() == 0 || target.getTemplateId() == 995;" + + "}"; + Util.instrumentDescribed(thisClass, ctItemBehaviour, "action", desc1, "isInPvPZone", replace); + + Util.setReason("Allow lockpicking if a container is not owned by a player."); + replace = "$_ = $proceed($$);" + + "if($_ == -10 || $_ == 0){ ok = true; }"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "picklock", "getLastOwnerId", replace); + } // - Disable villages and PMK's on the PvP server - // CtClass ctVillageFoundationQuestion = classPool.get("com.wurmonline.server.questions.VillageFoundationQuestion"); - Util.setReason("Allow placing deed outside of kingdom border."); - replace = "$_ = (byte) 4;"; - Util.instrumentDeclared(thisClass, ctVillageFoundationQuestion, "checkSize", "getKingdom", replace); + if (WyvernMods.placeDeedsOutsideKingdomInfluence) { + Util.setReason("Allow placing deed outside of kingdom border."); + replace = "$_ = (byte) 4;"; + Util.instrumentDeclared(thisClass, ctVillageFoundationQuestion, "checkSize", "getKingdom", replace); + } CtClass ctKingdomFoundationQuestion = classPool.get("com.wurmonline.server.questions.KingdomFoundationQuestion"); - Util.setReason("Disable PMK's on the Arena server."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " this.getResponder().getCommunicator().sendSafeServerMessage(\"Player-Made Kingdoms are disabled on this server.\");" - + " return;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctKingdomFoundationQuestion, "sendQuestion", replace); + if (WyvernMods.disablePMKs) { + Util.setReason("Disable PMK's on the Arena server."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " this.getResponder().getCommunicator().sendSafeServerMessage(\"Player-Made Kingdoms are disabled on this server.\");" + + " return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctKingdomFoundationQuestion, "sendQuestion", replace); + } // - Disable champion players altogether - // CtClass ctRealDeathQuestion = classPool.get("com.wurmonline.server.questions.RealDeathQuestion"); - Util.setReason("Disable player champions."); - replace = "this.getResponder().getCommunicator().sendSafeServerMessage(\"Champion players are disabled on this server.\");" - + "return;"; - Util.insertBeforeDeclared(thisClass, ctRealDeathQuestion, "sendQuestion", replace); + if (WyvernMods.disablePlayerChampions) { + Util.setReason("Disable player champions."); + replace = "this.getResponder().getCommunicator().sendSafeServerMessage(\"Champion players are disabled on this server.\");" + + "return;"; + Util.insertBeforeDeclared(thisClass, ctRealDeathQuestion, "sendQuestion", replace); + } // - Re-sort player aggression on the PvP server - // CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return "+Arena.class.getName()+".getArenaAttitude(this, $1);" - + "}"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "getAttitude", replace); + if (WyvernMods.arenaAggression) { + Util.setReason("Adjust creature-player aggression on the PvP server."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return " + Arena.class.getName() + ".getArenaAttitude(this, $1);" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "getAttitude", replace); - Util.setReason("Re-sort creature-player aggression on the PvP server."); - replace = "" + - "if(com.wurmonline.server.Servers.localServer.PVPSERVER && ($1.isPlayer() || this.isPlayer())){" + - " if($1.citizenVillage != null && this.citizenVillage != null){" + - " if($1.citizenVillage == this.citizenVillage){" + - " return 1;" + - " }" + - " if($1.citizenVillage.isAlly(this.citizenVillage)){" + - " return 1;" + - " }" + - " }" + - "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "getAttitude", replace); + Util.setReason("Re-sort creature-player aggression on the PvP server."); + replace = "" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER && ($1.isPlayer() || this.isPlayer())){" + + " if($1.citizenVillage != null && this.citizenVillage != null){" + + " if($1.citizenVillage == this.citizenVillage){" + + " return 1;" + + " }" + + " if($1.citizenVillage.isAlly(this.citizenVillage)){" + + " return 1;" + + " }" + + " }" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCreature, "getAttitude", replace); + } // - Hook for (ENEMY) declaration to allow for enemy presence blocking - // CtClass ctVirtualZone = classPool.get("com.wurmonline.server.zones.VirtualZone"); @@ -331,101 +322,71 @@ public class Arena { CtClass.floatType }; String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2); - replace = "if(this.watcher.isPlayer()){" + - " if("+PlayerTitles.class.getName()+".hasCustomTitle(creature)){" + - " suff = suff + "+PlayerTitles.class.getName()+".getCustomTitle(creature);" + - " }" + - " if(com.wurmonline.server.Servers.localServer.PVPSERVER && creature.isPlayer() && "+Arena.class.getName()+".getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" - + " suff = suff + \" (ENEMY)\";" - + " enemy = true;" + - " }" - + "}" - + "$_ = $proceed($$);"; - Util.instrumentDescribed(thisClass, ctVirtualZone, "addCreature", desc2, "isChampion", replace); + if (WyvernMods.enemyTitleHook) { + Util.setReason("Add hook for custom titles on all servers and arena aggression ENEMY suffix on PvP servers."); + replace = "if(this.watcher.isPlayer()){" + + " if(" + PlayerTitles.class.getName() + ".hasCustomTitle(creature)){" + + " suff = suff + " + PlayerTitles.class.getName() + ".getCustomTitle(creature);" + + " }" + + " if(com.wurmonline.server.Servers.localServer.PVPSERVER && creature.isPlayer() && " + Arena.class.getName() + ".getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" + + " suff = suff + \" (ENEMY)\";" + + " enemy = true;" + + " }" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctVirtualZone, "addCreature", desc2, "isChampion", replace); + } // - Modify when an enemy is present or not to use attitude instead of kingdom - // - replace = "if(this.watcher.isPlayer() && creature.isPlayer() && com.wurmonline.server.Servers.localServer.PVPSERVER && "+Arena.class.getName()+".getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" - + " $_ = 1;" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctVirtualZone, "checkIfEnemyIsPresent", "getKingdomId", replace); - /*ctVirtualZone.getDeclaredMethod("checkIfEnemyIsPresent").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getKingdomId")) { - m.replace("if(this.watcher.isPlayer() && creature.isPlayer() && com.wurmonline.server.Servers.localServer.PVPSERVER && mod.sin.wyvern.Arena.getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" - + " $_ = 1;" - + "}else{" - + " $_ = $proceed($$);" - + "}"); - return; - } - } - });*/ + if (WyvernMods.enemyPresenceOnAggression) { + Util.setReason("Apply enemy presence based on aggression instead of kingdom."); + replace = "if(this.watcher.isPlayer() && creature.isPlayer() && com.wurmonline.server.Servers.localServer.PVPSERVER && " + Arena.class.getName() + ".getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" + + " $_ = 1;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctVirtualZone, "checkIfEnemyIsPresent", "getKingdomId", replace); + } // - Block twigs and stones on the PvP server - // CtClass ctMethodsCreatures = classPool.get("com.wurmonline.server.behaviours.MethodsCreatures"); - Util.setReason("Block farwalker twigs and stones on PvP."); - replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"; - Util.instrumentDeclared(thisClass, ctMethodsCreatures, "teleportCreature", "isInPvPZone", replace); - /*ctMethodsCreatures.getDeclaredMethod("teleportCreature").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isInPvPZone")) { - m.replace("$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"); - return; - } - } - });*/ - - // - After respawn on PvP, send directly to PvE server - // - /*CtClass ctSpawnQuestion = classPool.get("com.wurmonline.server.questions.SpawnQuestion"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " "+Arena.class.getName()+".respawnPlayer(this.getResponder(), com.wurmonline.server.Servers.localServer);" - + " return;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctSpawnQuestion, "sendQuestion", replace);*/ - /*ctSpawnQuestion.getDeclaredMethod("sendQuestion").insertBefore("" - + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " mod.sin.wyvern.Arena.respawnPlayer(this.getResponder(), com.wurmonline.server.Servers.localServer);" - + " return;" - + "}");*/ + if (WyvernMods.disableFarwalkerItems) { + Util.setReason("Block farwalker twigs and stones on PvP."); + replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"; + Util.instrumentDeclared(thisClass, ctMethodsCreatures, "teleportCreature", "isInPvPZone", replace); + } // - Allow affinity stealing and battle rank changes - // - Util.setReason("Allow affinity stealing and battle rank changes."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = true;" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "isEnemyOnChaos", replace); + if (WyvernMods.alwaysAllowAffinitySteal) { + Util.setReason("Allow affinity stealing and battle rank changes."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "isEnemyOnChaos", replace); + } //CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - Util.setReason("Increase fight skill gain on PvP server."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " p.getFightingSkill().setKnowledge(pskill + (skillGained*1.5d), false);" - + "}" - + "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkInitialTitle", replace); + if (WyvernMods.adjustFightSkillGain) { + Util.setReason("Adjust fight skill gain on PvP server."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " p.getFightingSkill().setKnowledge(pskill + (skillGained*1.5d), false);" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkInitialTitle", replace); + } // - Fix nearby enemy check to find aggression instead of kingdom - // - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = c.getAttitude(performer) != 2 && c.getAttitude(performer) != 1;" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "isEnemiesNearby", "isFriendlyKingdom", replace); - /*ctMethodsItems.getDeclaredMethod("isEnemiesNearby").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isFriendlyKingdom")) { - m.replace("if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = c.getAttitude(performer) != 2;" - + "}else{" - + " $_ = $proceed($$);" - + "}"); - return; - } - } - });*/ + if (WyvernMods.useAggressionForNearbyEnemies) { + Util.setReason("Fix nearby enemy check to use aggression instead of kingdom."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = c.getAttitude(performer) != 2 && c.getAttitude(performer) != 1;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "isEnemiesNearby", "isFriendlyKingdom", replace); + } // Die method description CtClass ctString = classPool.get("java.lang.String"); @@ -437,144 +398,137 @@ public class Arena { String desc8 = Descriptor.ofMethod(CtClass.voidType, params8); // - Ensure corpses are not loot protected on PvP - // - Util.setReason("Ensure corpses are not loot protected."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = $proceed(false);" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "setProtected", replace); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " $_ = true;" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "isInPvPZone", replace); + if (WyvernMods.disablePvPCorpseProtection) { + Util.setReason("Ensure corpses are not loot protected."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = $proceed(false);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "setProtected", replace); + Util.setReason("Ensure corpses are not loot protected."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "isInPvPZone", replace); + } // - Allow players to do actions in PvP houses - // CtClass ctMethods = classPool.get("com.wurmonline.server.behaviours.Methods"); - Util.setReason("Enable players to do actions in PvP houses."); - replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"; - Util.instrumentDeclared(thisClass, ctMethods, "isNotAllowedMessage", "isEnemy", replace); + if (WyvernMods.bypassHousePermissions) { + Util.setReason("Enable players to do actions in PvP houses."); + replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"; + Util.instrumentDeclared(thisClass, ctMethods, "isNotAllowedMessage", "isEnemy", replace); + } // - Allow stealing against deity wishes without being punished on Arena - // - //CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); - Util.setReason("Allow stealing against deity wishes without being punished."); - replace = "$_ = $proceed($$) || com.wurmonline.server.Servers.localServer.PVPSERVER;"; - Util.instrumentDeclared(thisClass, ctAction, "checkLegalMode", "isLibila", replace); - /*ctAction.getDeclaredMethod("checkLegalMode").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isLibila")) { - m.replace("$_ = $proceed($$) || com.wurmonline.server.Servers.localServer.PVPSERVER;"); - return; - } - } - });*/ + if (WyvernMods.allowStealingAgainstDeityWishes) { + Util.setReason("Allow stealing against deity wishes without being punished."); + replace = "$_ = $proceed($$) || com.wurmonline.server.Servers.localServer.PVPSERVER;"; + Util.instrumentDeclared(thisClass, ctAction, "checkLegalMode", "isLibila", replace); + } // - Allow taking ownership of vehicles on Arena - // - // TODO: Fix. - Util.setReason("Allow taking ownership of vehicles on Arena."); - CtClass[] params3 = new CtClass[]{ - CtClass.longType, - CtClass.booleanType, - CtClass.byteType, - CtClass.intType, - CtClass.intType - }; - String desc3 = Descriptor.ofMethod(CtClass.voidType, params3); - replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER && !lVehicle.isLocked();"; - Util.instrumentDescribed(thisClass, ctCreature, "setVehicle", desc3, "isThisAChaosServer", replace); + if (WyvernMods.sameKingdomVehicleTheft) { + Util.setReason("Allow taking ownership of vehicles on Arena."); + CtClass[] params3 = new CtClass[]{ + CtClass.longType, + CtClass.booleanType, + CtClass.byteType, + CtClass.intType, + CtClass.intType + }; + String desc3 = Descriptor.ofMethod(CtClass.voidType, params3); + replace = "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER && !lVehicle.isLocked();"; + Util.instrumentDescribed(thisClass, ctCreature, "setVehicle", desc3, "isThisAChaosServer", replace); + } // - Multiply mine door bash damage by 3 on Arena - // CtClass ctTerraforming = classPool.get("com.wurmonline.server.behaviours.Terraforming"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " damage *= 3d;" - + "}" - + "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctTerraforming, "destroyMineDoor", "getOrCreateTile", replace); - /*ctTerraforming.getDeclaredMethod("destroyMineDoor").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getOrCreateTile")) { - m.replace("if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " damage *= 3d;" - + "}" - + "$_ = $proceed($$);"); - return; - } - } - });*/ + if (WyvernMods.adjustMineDoorDamage) { + Util.setReason("Adjust mine door bash damage."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " damage *= 3d;" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctTerraforming, "destroyMineDoor", "getOrCreateTile", replace); + } // - Prevent tons of errors for legality on Arena. - // - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return true;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "isOkToKillBy", replace); - /*ctCreature.getDeclaredMethod("isOkToKillBy").insertBefore("" - + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return true;" - + "}");*/ - Util.insertBeforeDeclared(thisClass, ctCreature, "hasBeenAttackedBy", replace); - /*ctCreature.getDeclaredMethod("hasBeenAttackedBy").insertBefore("" - + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return true;" - + "}");*/ + if (WyvernMods.sameKingdomPermissionsAdjustments) { + Util.setReason("Adjust same-kingdom permissions on Arena."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return true;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCreature, "isOkToKillBy", replace); + Util.setReason("Adjust same-kingdom permissions on Arena."); + Util.insertBeforeDeclared(thisClass, ctCreature, "hasBeenAttackedBy", replace); + } // - Disable CA Help on Arena - // - Util.setReason("Disable CA HELP on Arena."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" - + " return false;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "seesPlayerAssistantWindow", replace); + if (WyvernMods.disableCAHelpOnPvP) { + Util.setReason("Disable CA HELP on PvP servers."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return false;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "seesPlayerAssistantWindow", replace); + } - Util.setReason("Make players who are non-allied enemies of villages."); - CtClass ctVillage = classPool.get("com.wurmonline.server.villages.Village"); - CtClass[] params4 = new CtClass[]{ - ctCreature, - CtClass.booleanType - }; - String desc4 = Descriptor.ofMethod(CtClass.booleanType, params4); - replace = "" + - "if(com.wurmonline.server.Servers.localServer.PVPSERVER && $1.isPlayer()){" + - " if($1.getPower() > 0){" + - " return false;" + - " }" + - " if(this.isCitizen($1) || this.isAlly($1)){" + - " return false;" + - " }" + - " return true;" + - "}" + - // Additional code added to ensure village guards do not attack titans or rare creatures. - "if("+Titans.class.getName()+".isTitan($1) || "+RareSpawns.class.getName()+".isRareCreature($1)){" + - " return false;" + - "}"; - Util.insertBeforeDescribed(thisClass, ctVillage, "isEnemy", desc4, replace); + CtClass ctVillage = classPool.get("com.wurmonline.server.villages.Village"); + if (WyvernMods.sameKingdomVillageWarfare) { + Util.setReason("Make players who are non-allied enemies of villages."); + CtClass[] params4 = new CtClass[]{ + ctCreature, + CtClass.booleanType + }; + String desc4 = Descriptor.ofMethod(CtClass.booleanType, params4); + replace = "" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER && $1.isPlayer()){" + + " if($1.getPower() > 0){" + + " return false;" + + " }" + + " if(this.isCitizen($1) || this.isAlly($1)){" + + " return false;" + + " }" + + " return true;" + + "}" + + // Additional code added to ensure village guards do not attack titans or rare creatures. + "if(" + Titans.class.getName() + ".isTitan($1) || " + RareSpawns.class.getName() + ".isRareCreature($1)){" + + " return false;" + + "}"; + Util.insertBeforeDescribed(thisClass, ctVillage, "isEnemy", desc4, replace); - Util.setReason("Make all deeds enemies of eachother unless allied."); - CtClass[] params5 = new CtClass[]{ - ctVillage - }; - String desc5 = Descriptor.ofMethod(CtClass.booleanType, params5); - replace = "{ if($1 == null){" + - " return false;" + - " }" + - " if($1.kingdom != this.kingdom){" + - " return true;" + - " }" + - " if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " if(this.isAlly($1)){" + - " return false;" + - " }" + - " if($0 == $1){" + - " return false;" + - " }" + - " return true;" + - "}" + - "return false; }"; - Util.setBodyDescribed(thisClass, ctVillage, "isEnemy", desc5, replace); + Util.setReason("Make all deeds enemies of eachother unless allied."); + CtClass[] params5 = new CtClass[]{ + ctVillage + }; + String desc5 = Descriptor.ofMethod(CtClass.booleanType, params5); + replace = "{ if($1 == null){" + + " return false;" + + " }" + + " if($1.kingdom != this.kingdom){" + + " return true;" + + " }" + + " if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " if(this.isAlly($1)){" + + " return false;" + + " }" + + " if($0 == $1){" + + " return false;" + + " }" + + " return true;" + + "}" + + "return false; }"; + Util.setBodyDescribed(thisClass, ctVillage, "isEnemy", desc5, replace); + } - Util.setReason("Change HotA reward"); - replace = Arena.class.getName()+".createNewHotaPrize(this, $1);"; - Util.setBodyDeclared(thisClass, ctVillage, "createHotaPrize", replace); + if (WyvernMods.adjustHotARewards) { + Util.setReason("Adjust HotA rewards."); + replace = Arena.class.getName() + ".createNewHotaPrize(this, $1);"; + Util.setBodyDeclared(thisClass, ctVillage, "createHotaPrize", replace); + } CtClass ctGuardPlan = classPool.get("com.wurmonline.server.villages.GuardPlan"); CtClass[] params6 = new CtClass[]{ @@ -582,122 +536,140 @@ public class Arena { CtClass.intType }; String desc6 = Descriptor.ofMethod(CtClass.intType, params6); - Util.setReason("Cap maximum guards to 5."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " return Math.min(5, Math.max(3, $1 * $2 / 49));" + - "}"; - Util.insertBeforeDescribed(thisClass, ctGuardPlan, "getMaxGuards", desc6, replace); + if (WyvernMods.capMaximumGuards) { + Util.setReason("Cap maximum guards to 5."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return Math.min(5, Math.max(3, $1 * $2 / 49));" + + "}"; + Util.insertBeforeDescribed(thisClass, ctGuardPlan, "getMaxGuards", desc6, replace); + } - Util.setReason("Disable towers"); - CtClass ctAdvancedCreationEntry = classPool.get("com.wurmonline.server.items.AdvancedCreationEntry"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " performer.getCommunicator().sendAlertServerMessage(\"Towers are disabled for now. A new system is in progress.\");" + - " throw new com.wurmonline.server.NoSuchItemException(\"Towers are disabled.\");" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctAdvancedCreationEntry, "cont", "isTowerTooNear", replace); - Util.instrumentDeclared(thisClass, ctAdvancedCreationEntry, "run", "isTowerTooNear", replace); + if (WyvernMods.disableTowerConstruction) { + Util.setReason("Disable towers from being constructed."); + CtClass ctAdvancedCreationEntry = classPool.get("com.wurmonline.server.items.AdvancedCreationEntry"); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " performer.getCommunicator().sendAlertServerMessage(\"Towers are disabled.\");" + + " throw new com.wurmonline.server.NoSuchItemException(\"Towers are disabled.\");" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctAdvancedCreationEntry, "cont", "isTowerTooNear", replace); + Util.setReason("Disable towers from being constructed."); + Util.instrumentDeclared(thisClass, ctAdvancedCreationEntry, "run", "isTowerTooNear", replace); + } - Util.setReason("Reduce local range (player)."); - replace = "if($3 > 5){" + - " $_ = $proceed($1, $2, 50);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctVirtualZone, "coversCreature", "isWithinDistanceTo", replace); - Util.setReason("Reduce local range (creature)."); - replace = "$_ = true;"; - Util.instrumentDeclared(thisClass, ctVirtualZone, "coversCreature", "isPlayer", replace); + if (WyvernMods.adjustLocalRange) { + Util.setReason("Reduce local range (player)."); + replace = "if($3 > 5){" + + " $_ = $proceed($1, $2, 50);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctVirtualZone, "coversCreature", "isWithinDistanceTo", replace); + Util.setReason("Reduce local range (creature)."); + replace = "$_ = true;"; + Util.instrumentDeclared(thisClass, ctVirtualZone, "coversCreature", "isPlayer", replace); + } - CtClass ctKarmaQuestion = classPool.get("com.wurmonline.server.questions.KarmaQuestion"); - Util.setReason("Disable Karma teleport."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $_ = true;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctKarmaQuestion, "answer", "isInPvPZone", replace); + if (WyvernMods.disableKarmaTeleport) { + CtClass ctKarmaQuestion = classPool.get("com.wurmonline.server.questions.KarmaQuestion"); + Util.setReason("Disable Karma teleport."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctKarmaQuestion, "answer", "isInPvPZone", replace); + } - Util.setReason("Make players only able to lead one creature."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " return this.followers == null || this.followers.size() < 1;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "mayLeadMoreCreatures", replace); + if (WyvernMods.limitLeadCreatures) { + Util.setReason("Make players only able to lead one creature."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return this.followers == null || this.followers.size() < 1;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "mayLeadMoreCreatures", replace); + } - CtClass ctMethodsStructure = classPool.get("com.wurmonline.server.behaviours.MethodsStructure"); - Util.setReason("Increase bash timer to 15 seconds."); - replace = "time = 600;" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctMethodsStructure, "destroyWall", "getStructure", replace); + if (WyvernMods.adjustBashTimer) { + CtClass ctMethodsStructure = classPool.get("com.wurmonline.server.behaviours.MethodsStructure"); + Util.setReason("Increase bash timer."); + replace = "time = 600;" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctMethodsStructure, "destroyWall", "getStructure", replace); + } - CtClass ctHota = classPool.get("com.wurmonline.server.epic.Hota"); - Util.setReason("Display discord message for HotA announcements."); - replace = Arena.class.getName()+".sendHotaMessage($1);" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctHota, "poll", "broadCastSafe", replace); - Util.setReason("Display discord message for HotA wins."); - Util.instrumentDeclared(thisClass, ctHota, "win", "broadCastSafe", replace); - Util.setReason("Display discord message for HotA conquers & neutralizes."); - replace = "if($2.getData1() == 0){" + - " "+Arena.class.getName()+".sendHotaMessage($1.getName() + \" neutralizes the \" + $2.getName() + \".\");" + - "}else{" + - " "+Arena.class.getName()+".sendHotaMessage($1.getName() + \" conquers the \" + $2.getName() + \".\");" + - "}"; - Util.insertBeforeDeclared(thisClass, ctHota, "addPillarConquered", replace); + if (WyvernMods.discordRelayHotAMessages) { + CtClass ctHota = classPool.get("com.wurmonline.server.epic.Hota"); + Util.setReason("Display discord message for HotA announcements."); + replace = Arena.class.getName() + ".sendHotaMessage($1);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctHota, "poll", "broadCastSafe", replace); + Util.setReason("Display discord message for HotA wins."); + Util.instrumentDeclared(thisClass, ctHota, "win", "broadCastSafe", replace); + Util.setReason("Display discord message for HotA conquers & neutralizes."); + replace = "if($2.getData1() == 0){" + + " " + Arena.class.getName() + ".sendHotaMessage($1.getName() + \" neutralizes the \" + $2.getName() + \".\");" + + "}else{" + + " " + Arena.class.getName() + ".sendHotaMessage($1.getName() + \" conquers the \" + $2.getName() + \".\");" + + "}"; + Util.insertBeforeDeclared(thisClass, ctHota, "addPillarConquered", replace); + } - // handle_TARGET_and_TARGET_HOSTILE - CtClass ctCreatureBehaviour = classPool.get("com.wurmonline.server.behaviours.CreatureBehaviour"); - Util.setReason("Allow players to attack enemy guards."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $_ = false;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctCreatureBehaviour, "handle_TARGET_and_TARGET_HOSTILE", "isFriendlyKingdom", replace); + if (WyvernMods.allowAttackingSameKingdomGuards) { + CtClass ctCreatureBehaviour = classPool.get("com.wurmonline.server.behaviours.CreatureBehaviour"); + Util.setReason("Allow players to attack enemy guards."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCreatureBehaviour, "handle_TARGET_and_TARGET_HOSTILE", "isFriendlyKingdom", replace); + } - Util.setReason("Fix templars attacking themselves."); - replace = "if($1.isSpiritGuard()){" + - " return;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctVillage, "addTarget", replace); + if (WyvernMods.fixGuardsAttackingThemselves) { + Util.setReason("Fix templars attacking themselves."); + replace = "if($1.isSpiritGuard()){" + + " return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctVillage, "addTarget", replace); + } - Util.setReason("Keep mine doors open for shorter durations."); - replace = "$_ = true;"; - Util.instrumentDeclared(thisClass, ctCreature, "checkOpenMineDoor", "isThisAChaosServer", replace); + if (WyvernMods.reducedMineDoorOpenTime) { + Util.setReason("Keep mine doors open for 30 seconds instead of 120 seconds."); + replace = "$_ = true;"; + Util.instrumentDeclared(thisClass, ctCreature, "checkOpenMineDoor", "isThisAChaosServer", replace); + } - Util.setReason("Fix fight skill gains against enemy players."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " if($0 == this){" + - " $_ = -1;" + - " }else{" + - " $_ = $proceed($$);" + - " }" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "getKingdomId", replace); + if (WyvernMods.allowSameKingdomFightSkillGains) { + Util.setReason("Fix fight skill gains against enemy players."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " if($0 == this){" + + " $_ = -1;" + + " }else{" + + " $_ = $proceed($$);" + + " }" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "getKingdomId", replace); + } - Util.setReason("Enable archering enemies on deeds."); - replace = "$_ = true;"; - Util.instrumentDeclared(thisClass, ctVillage, "mayAttack", "isEnemyOnChaos", replace); + if (WyvernMods.allowArcheringOnSameKingdomDeeds) { + Util.setReason("Enable archering enemies on deeds."); + replace = "$_ = true;"; + Util.instrumentDeclared(thisClass, ctVillage, "mayAttack", "isEnemyOnChaos", replace); + } - // Server.rand.nextFloat()*(35/(1-2*desiredPercent)) - Util.setReason("Nerf magranon faith protection."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $_ = com.wurmonline.server.Server.rand.nextInt(40);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctCreature, "die", desc8, "getFavor", replace); + if (WyvernMods.sendNewSpawnQuestionOnPvP) { + Util.setReason("Adjust spawn question mechanics."); + CtClass ctSpawnQuestion = classPool.get("com.wurmonline.server.questions.SpawnQuestion"); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + Arena.class.getName() + ".sendNewSpawnQuestion(this);" + + "return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctSpawnQuestion, "sendQuestion", replace); + } - Util.setReason("Adjust spawn question mechanics."); - CtClass ctSpawnQuestion = classPool.get("com.wurmonline.server.questions.SpawnQuestion"); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - Arena.class.getName()+".sendNewSpawnQuestion(this);" + - "return;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctSpawnQuestion, "sendQuestion", replace); CtClass ctMeshIO = classPool.get("com.wurmonline.mesh.MeshIO"); CtClass[] params7 = new CtClass[]{ ctCreature, @@ -711,20 +683,25 @@ public class Arena { CtClass.booleanType }; String desc7 = Descriptor.ofMethod(CtClass.booleanType, params7); - replace = Arena.class.getName()+".sendHotaMessage($1+\" \"+$2);" + - "$_ = $proceed($$);"; - Util.instrumentDescribed(thisClass, ctTerraforming, "dig", desc7, "addHistory", replace); + if (WyvernMods.sendArtifactDigsToDiscord) { + Util.setReason("Announce digging up artifacts on Discord."); + replace = Arena.class.getName() + ".sendHotaMessage($1+\" \"+$2);" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctTerraforming, "dig", desc7, "addHistory", replace); + } // Creature performer, Item source, int tilex, int tiley, int tile, float counter, boolean corner, MeshIO mesh, boolean toPile - Util.setReason("Set favored kingdom for PvP"); - CtClass ctDeities = classPool.get("com.wurmonline.server.deities.Deities"); - replace = "{ return (byte) 4; }"; - Util.setBodyDeclared(thisClass, ctDeities, "getFavoredKingdom", replace); + if (WyvernMods.makeFreedomFavoredKingdom) { + CtClass ctDeities = classPool.get("com.wurmonline.server.deities.Deities"); + Util.setReason("Set favored kingdom for PvP"); + replace = "{ return (byte) 4; }"; + Util.setBodyDeclared(thisClass, ctDeities, "getFavoredKingdom", replace); - Util.setReason("Set favored kingdom for PvP"); - CtClass ctDeity = classPool.get("com.wurmonline.server.deities.Deity"); - replace = "{ return (byte) 4; }"; - Util.setBodyDeclared(thisClass, ctDeities, "getFavoredKingdom", replace); + CtClass ctDeity = classPool.get("com.wurmonline.server.deities.Deity"); + Util.setReason("Set favored kingdom for PvP"); + replace = "{ return (byte) 4; }"; + Util.setBodyDeclared(thisClass, ctDeities, "getFavoredKingdom", replace); + } /*Util.setReason("Decrease PvP combat damage."); CtClass ctString = classPool.get("java.lang.String"); @@ -753,51 +730,62 @@ public class Arena { "}"; Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc8, replace);*/ + /* Removed in favor of DUSKombat. Util.setReason("Reduce player vs player damage by half."); CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler"); replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && ($1.isDominated() || $1.isPlayer()) && $0.creature.isPlayer()){" + //" logger.info(\"Detected player hit against player/pet opponent. Halving damage.\");" + " $3 = $3 * 0.7d;" + "}"; - Util.insertBeforeDeclared(thisClass, ctCombatHandler, "setDamage", replace); + Util.insertBeforeDeclared(thisClass, ctCombatHandler, "setDamage", replace);*/ - Util.setReason("Disable crown influence from spreading to enemies."); - replace = "$_ = $0.getAttitude(this) == 1;"; - Util.instrumentDeclared(thisClass, ctPlayer, "spreadCrownInfluence", "isFriendlyKingdom", replace); + if (WyvernMods.crownInfluenceOnAggression) { + Util.setReason("Disable crown influence from spreading to enemies."); + replace = "$_ = $0.getAttitude(this) == 1;"; + Util.instrumentDeclared(thisClass, ctPlayer, "spreadCrownInfluence", "isFriendlyKingdom", replace); + } - Util.setReason("Disable item drops from players on Arena."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer()){" + - " this.getCommunicator().sendSafeServerMessage(\"You have died on the Arena server and your items are kept safe.\");" + - " keepItems = true;" + - "}" + - "$_ = $proceed($$);"; - Util.instrumentDescribedCount(thisClass, ctCreature, "die", desc8, "isOnCurrentServer", 1, replace); + if (WyvernMods.disableOWFL) { + Util.setReason("Disable item drops from players on Arena."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer()){" + + " this.getCommunicator().sendSafeServerMessage(\"You have died on the Arena server and your items are kept safe.\");" + + " keepItems = true;" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDescribedCount(thisClass, ctCreature, "die", desc8, "isOnCurrentServer", 1, replace); + } - Util.setReason("Disable player skill loss on Arena."); - replace = "if(this.isPlayer() && this.isDeathProtected()){" + - " this.getCommunicator().sendSafeServerMessage(\"You have died with a Resurrection Stone and your knowledge is kept safe.\");" + - " return;" + - "}else{" + - " this.getCommunicator().sendAlertServerMessage(\"You have died without a Resurrection Stone, resulting in some of your knowledge being lost.\");" + - "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "punishSkills", replace); + if (WyvernMods.resurrectionStonesProtectSkill) { + Util.setReason("Disable player skill loss on Arena."); + replace = "if(this.isPlayer() && this.isDeathProtected()){" + + " this.getCommunicator().sendSafeServerMessage(\"You have died with a Resurrection Stone and your knowledge is kept safe.\");" + + " return;" + + "}else{" + + " this.getCommunicator().sendAlertServerMessage(\"You have died without a Resurrection Stone, resulting in some of your knowledge being lost.\");" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCreature, "punishSkills", replace); + } - Util.setReason("Disable player fight skill loss on Arena."); - replace = "if(this.isPlayer() && this.isDeathProtected()){" + - " $_ = null;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclaredCount(thisClass, ctCreature, "modifyFightSkill", "setKnowledge", 1, replace); + if (WyvernMods.resurrectionStonesProtectFightSkill) { + Util.setReason("Disable player fight skill loss if they have a resurrection stone."); + replace = "if(this.isPlayer() && this.isDeathProtected()){" + + " $_ = null;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclaredCount(thisClass, ctCreature, "modifyFightSkill", "setKnowledge", 1, replace); + } - Util.setReason("Disable player affinity loss on Arena."); - replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer() && this.isDeathProtected()){" + - " this.getCommunicator().sendSafeServerMessage(\"Your resurrection stone keeps your affinities safe from your slayers.\");" + - " $_ = "+Arena.class.getName()+".getNullAffinities();" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "getAffinities", replace); + if (WyvernMods.resurrectionStonesProtectAffinities) { + Util.setReason("Disable player affinity loss on Arena."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER && this.isPlayer() && this.isDeathProtected()){" + + " this.getCommunicator().sendSafeServerMessage(\"Your resurrection stone keeps your affinities safe from your slayers.\");" + + " $_ = " + Arena.class.getName() + ".getNullAffinities();" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "modifyRanking", "getAffinities", replace); + } /*Util.setReason("Enable stealing from deeds."); replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + @@ -807,6 +795,14 @@ public class Arena { "}"; Util.instrumentDeclared(thisClass, ctMethodsItems, "checkIfStealing", "mayPass", replace);*/ + if (WyvernMods.bypassPlantedPermissionChecks) { + Util.setReason("Allow movement of planted items on Arena regardless of permission status."); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return true;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctItem, "checkPlantedPermissions", replace); + } + }catch (NotFoundException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/GemAugmentation.java b/src/main/java/mod/sin/wyvern/GemAugmentation.java index f6ba55b..467b18c 100644 --- a/src/main/java/mod/sin/wyvern/GemAugmentation.java +++ b/src/main/java/mod/sin/wyvern/GemAugmentation.java @@ -25,6 +25,11 @@ public class GemAugmentation { Class thisClass = GemAugmentation.class; String replace; + Util.setReason("Disable Gem Augmentation skill from converting."); + CtClass ctMethodsReligion = classPool.get("com.wurmonline.server.behaviours.MethodsReligion"); + replace = "$_ = $proceed($1, $2, true, $4);"; + Util.instrumentDeclared(thisClass, ctMethodsReligion, "listen", "skillCheck", replace); + Util.setReason("Primary Gem Augmentation Hook."); CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems"); replace = "$_ = "+GemAugmentation.class.getName()+".setGemmedQuality($0, power, maxGain, modifier);"; diff --git a/src/main/java/mod/sin/wyvern/ItemMod.java b/src/main/java/mod/sin/wyvern/ItemMod.java index 806135f..77ab7d7 100644 --- a/src/main/java/mod/sin/wyvern/ItemMod.java +++ b/src/main/java/mod/sin/wyvern/ItemMod.java @@ -204,7 +204,7 @@ public class ItemMod { //SKELETON_DECORATION.initCreationEntry(); SOUL_FORGE.initCreationEntry(); STATUETTE_BREYK.initCreationEntry(); - //STATUETTE_CYBERHUSKY.initCreationEntry(); + STATUETTE_CYBERHUSKY.initCreationEntry(); WARHAMMER.initCreationEntry(); WARHAMMER_HEAD.initCreationEntry(); diff --git a/src/main/java/mod/sin/wyvern/MiscChanges.java b/src/main/java/mod/sin/wyvern/MiscChanges.java index 4a9c9b0..65f9a76 100644 --- a/src/main/java/mod/sin/wyvern/MiscChanges.java +++ b/src/main/java/mod/sin/wyvern/MiscChanges.java @@ -325,7 +325,7 @@ public class MiscChanges { // Is send to buff bar and not something we're stopping, so allow it. return true; } - + public static void preInit(){ try{ ClassPool classPool = HookManager.getInstance().getClassPool(); @@ -334,214 +334,263 @@ public class MiscChanges { // - Create Server tab with initial messages - // CtClass ctPlayers = classPool.get("com.wurmonline.server.Players"); - CtMethod m = ctPlayers.getDeclaredMethod("sendStartGlobalKingdomChat"); - String infoTabTitle = "Server"; - // Initial messages: - String[] infoTabLine = {"Server Thread: https://forum.wurmonline.com/index.php?/topic/162067-revenant-modded-pvepvp-3x-action-new-skillgain/", - "Website/Maps: https://www.sarcasuals.com/", - "Server Discord: https://discord.gg/r8QNXAC", - "Server Data: https://docs.google.com/spreadsheets/d/1yjqTHoxUan4LIldI3jgrXZgXj1M2ENQ4MXniPUz0rE4", - "Server Wiki/Documentation: https://docs.google.com/document/d/1cbPi7-vZnjaiYrENhaefzjK_Wz7_F1CcPYJtC6uCi98/edit?usp=sharing", - "Patreon: https://www.patreon.com/sindusk"}; - StringBuilder str = new StringBuilder("{" - + " com.wurmonline.server.Message mess;"); - for (String anInfoTabLine : infoTabLine) { - str.append(" mess = new com.wurmonline.server.Message(player, (byte)16, \"").append(infoTabTitle).append("\",\"").append(anInfoTabLine).append("\", 0, 255, 0);").append(" player.getCommunicator().sendMessage(mess);"); + if (WyvernMods.enableInfoTab) { + CtMethod m = ctPlayers.getDeclaredMethod("sendStartGlobalKingdomChat"); + String infoTabTitle = WyvernMods.infoTabName; + // Initial messages: + //String[] infoTabLine = (String[]) WyvernMods.infoTabLines.toArray(); + /*String[] infoTabLine = {"Server Thread: https://forum.wurmonline.com/index.php?/topic/162067-revenant-modded-pvepvp-3x-action-new-skillgain/", + "Website/Maps: https://www.sarcasuals.com/", + "Server Discord: https://discord.gg/r8QNXAC", + "Server Data: https://docs.google.com/spreadsheets/d/1yjqTHoxUan4LIldI3jgrXZgXj1M2ENQ4MXniPUz0rE4", + "Server Wiki/Documentation: https://docs.google.com/document/d/1cbPi7-vZnjaiYrENhaefzjK_Wz7_F1CcPYJtC6uCi98/edit?usp=sharing", + "Patreon: https://www.patreon.com/sindusk"};*/ + StringBuilder str = new StringBuilder("{ com.wurmonline.server.Message mess;"); + for (String anInfoTabLine : WyvernMods.infoTabLines) { + str.append(" mess = new com.wurmonline.server.Message(player, (byte)16, \"").append(infoTabTitle).append("\",\"").append(anInfoTabLine).append("\", 0, 255, 0);").append(" player.getCommunicator().sendMessage(mess);"); + } + str.append("}"); + m.insertAfter(str.toString()); } - str.append("}"); - m.insertAfter(str.toString()); // - Enable bridges to be built inside/over/through houses - // CtClass ctPlanBridgeChecks = classPool.get("com.wurmonline.server.structures.PlanBridgeChecks"); - replace = "{ return new com.wurmonline.server.structures.PlanBridgeCheckResult(false); }"; - Util.setBodyDeclared(thisClass, ctPlanBridgeChecks, "checkForBuildings", replace); + if (WyvernMods.ignoreBridgeChecks) { + Util.setReason("Disable bridge construction checks."); + replace = "{ return new com.wurmonline.server.structures.PlanBridgeCheckResult(false); }"; + Util.setBodyDeclared(thisClass, ctPlanBridgeChecks, "checkForBuildings", replace); + } // - Disable mailboxes from being used while loaded - // CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); - replace = "$_ = $proceed($$);" - + "com.wurmonline.server.items.Item theTarget = com.wurmonline.server.Items.getItem(targetId);" - + "if(theTarget != null && theTarget.getTemplateId() >= 510 && theTarget.getTemplateId() <= 513){" - + " if(theTarget.getTopParent() != theTarget.getWurmId()){" - + " mover.getCommunicator().sendNormalServerMessage(\"Mailboxes cannot be used while loaded.\");" - + " return false;" - + " }" - + "}"; - Util.instrumentDeclared(thisClass, ctItem, "moveToItem", "getOwnerId", replace); + if (WyvernMods.disableMailboxUsageWhileLoaded) { + Util.setReason("Disable mailbox usage while loaded."); + replace = "$_ = $proceed($$);" + + "com.wurmonline.server.items.Item theTarget = com.wurmonline.server.Items.getItem(targetId);" + + "if(theTarget != null && theTarget.getTemplateId() >= 510 && theTarget.getTemplateId() <= 513){" + + " if(theTarget.getTopParent() != theTarget.getWurmId()){" + + " mover.getCommunicator().sendNormalServerMessage(\"Mailboxes cannot be used while loaded.\");" + + " return false;" + + " }" + + "}"; + Util.instrumentDeclared(thisClass, ctItem, "moveToItem", "getOwnerId", replace); + } - // - Enable creature custom colors - (Used for creating custom color creatures eg. Lilith) - // CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); - /*replace = "{ return true; }"; - Util.setBodyDeclared(thisClass, ctCreature, "hasCustomColor", replace);*/ - // - Increase the amount of checks for new unique spawns by 5x - // + // - Increase the amount of checks for new legendary creature to spawn - // CtClass ctServer = classPool.get("com.wurmonline.server.Server"); - replace = "for(int i = 0; i < 5; i++){" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctServer, "run", "checkDens", replace); + if (WyvernMods.increasedLegendaryCreatures) { + Util.setReason("Increase chances of a Legendary Creature spawning."); + replace = "for(int i = 0; i < "+String.valueOf(WyvernMods.increasedLegendaryFrequency)+"; i++){" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctServer, "run", "checkDens", replace); + } - // - Add Facebreyker to the list of spawnable uniques - // + // - Add Facebreyker to the list of spawnable legendary creatures - // CtClass ctDens = classPool.get("com.wurmonline.server.zones.Dens"); - replace = "com.wurmonline.server.zones.Dens.checkTemplate(2147483643, whileRunning);"; - Util.insertBeforeDeclared(thisClass, ctDens, "checkDens", replace); - //ctDens.getDeclaredMethod("checkDens").insertAt(0, "com.wurmonline.server.zones.Dens.checkTemplate(2147483643, whileRunning);"); + if (WyvernMods.allowFacebreykerNaturalSpawn) { + Util.setReason("Add Facebreyker to the natural legendary spawn list."); + replace = "com.wurmonline.server.zones.Dens.checkTemplate(2147483643, whileRunning);"; + Util.insertBeforeDeclared(thisClass, ctDens, "checkDens", replace); + } // - Announce player titles in the Server tab - // CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player"); - replace = "$_ = $proceed($$);" - + "if(!com.wurmonline.server.Servers.localServer.PVPSERVER && this.getPower() < 1){" - + " "+MiscChanges.class.getName()+".sendServerTabMessage(\"event\", this.getName()+\" just earned the title of \"+title.getName(this.isNotFemale())+\"!\", 200, 100, 0);" - + "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "addTitle", "sendNormalServerMessage", replace); + if (WyvernMods.announcePlayerTitles) { + Util.setReason("Announce player titles in the server tab."); + replace = "$_ = $proceed($$);" + + "if(!com.wurmonline.server.Servers.localServer.PVPSERVER && this.getPower() < 1){" + + " " + MiscChanges.class.getName() + ".sendServerTabMessage(\"event\", this.getName()+\" just earned the title of \"+title.getName(this.isNotFemale())+\"!\", 200, 100, 0);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "addTitle", "sendNormalServerMessage", replace); + } // - Make leather not suck even after it's able to be combined. - // CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems"); - replace = "if(com.wurmonline.server.behaviours.MethodsItems.getImproveTemplateId(target) != 72){" - + " $_ = $proceed($$);" - + "}else{" - + " $_ = false;" - + "}"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "isCombine", replace); + if (WyvernMods.improveCombinedLeather) { + Util.setReason("Allow leather to improve beyond QL after being combinable."); + replace = "if(com.wurmonline.server.behaviours.MethodsItems.getImproveTemplateId(target) != 72){" + + " $_ = $proceed($$);" + + "}else{" + + " $_ = false;" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "isCombine", replace); + } // - Check new improve materials - // - replace = "int temp = "+ItemMod.class.getName()+".getModdedImproveTemplateId($1);" - + "if(temp != -10){" - + " return temp;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctMethodsItems, "getImproveTemplateId", replace); + if (WyvernMods.allowModdedImproveTemplates) { + Util.setReason("Enable modded improve templates."); + replace = "int temp = " + ItemMod.class.getName() + ".getModdedImproveTemplateId($1);" + + "if(temp != -10){" + + " return temp;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctMethodsItems, "getImproveTemplateId", replace); + } // - Remove fatiguing actions requiring you to be on the ground - // CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); - CtConstructor[] ctActionConstructors = ctAction.getConstructors(); - for(CtConstructor constructor : ctActionConstructors) { - constructor.instrument(new ExprEditor() { - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("isFatigue")) { - m.replace("" + - "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " if(!com.wurmonline.server.behaviours.Actions.isActionDestroy(this.getNumber())){" + - " $_ = false;" + - " }else{" + - " $_ = $proceed($$);" + - " }" + - "}else{" + - " $_ = false;" + - "}"); - logger.info("Set isFatigue to false in action constructor."); + if (WyvernMods.fatigueActionOverride) { + CtConstructor[] ctActionConstructors = ctAction.getConstructors(); + for (CtConstructor constructor : ctActionConstructors) { + constructor.instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isFatigue")) { + m.replace("" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " if(!com.wurmonline.server.behaviours.Actions.isActionDestroy(this.getNumber())){" + + " $_ = false;" + + " }else{" + + " $_ = $proceed($$);" + + " }" + + "}else{" + + " $_ = false;" + + "}"); + logger.info("Set isFatigue to false in action constructor."); + } + } + }); + } + } + + if (WyvernMods.fixPortalIssues) { + Util.setReason("Fix Portal Issues."); + CtClass ctPortal = classPool.get("com.wurmonline.server.questions.PortalQuestion"); + Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "willLeaveServer", "$_ = true;"); + Util.setReason("Fix Portal Issues."); + Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "getKnowledge", "$_ = true;"); + } + + if (WyvernMods.disableMinimumShieldDamage) { + Util.setReason("Disable the minimum 0.01 damage on shield damage, allowing damage modifiers to rule."); + CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler"); + replace = "if($1 < 0.5f){" + + " $_ = $proceed((float) 0, (float) $2);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCombatHandler, "checkShield", "max", replace); + } + + if (WyvernMods.disableGMEmoteLimit) { + // - Allow GM's to bypass the 5 second emote sound limit. - // + Util.setReason("Allow GM's to bypass the 5 second emote sound limit."); + replace = "if(this.getPower() > 0){" + + " return true;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "mayEmote", replace); + } + + // - Make creatures wander slightly if they are shot from afar by an arrow - // + CtClass ctArrows = classPool.get("com.wurmonline.server.combat.Arrows"); + if (WyvernMods.creatureArcheryWander) { + Util.setReason("Make creatures wander slightly when archered."); + replace = "if(!defender.isPathing()){" + + " defender.startPathing(com.wurmonline.server.Server.rand.nextInt(100));" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctArrows, "addToHitCreature", "addAttacker", replace); + } + + if (WyvernMods.globalDeathTabs) { + Util.setReason("Broadcast death tabs to GL-Freedom."); + replace = MiscChanges.class.getName() + ".broadCastDeaths($1, $2);"; + Util.insertBeforeDeclared(thisClass, ctPlayers, "broadCastDeathInfo", replace); + } + + /* Disabled 1.9 - PvE Death Tabs are now part of vanilla. + Util.setReason("Broadcast player death tabs always."); + replace = MiscChanges.class.getName()+".broadCastDeathsPvE($0, $0.attackers);"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "modifyRanking", replace);*/ + + if (WyvernMods.disablePvPOnlyDeathTabs) { + Util.setReason("Disable PvP only death tabs."); + replace = "$_ = true;"; + Util.instrumentDeclared(thisClass, ctPlayers, "broadCastDeathInfo", "isThisAPvpServer", replace); + } + + if (WyvernMods.fixLibilaCrossingIssues) { + Util.setReason("Attempt to prevent libila from losing faith when crossing servers."); + CtClass ctIntraServerConnection = classPool.get("com.wurmonline.server.intra.IntraServerConnection"); + ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() { + @Override + public void edit(FieldAccess fieldAccess) throws CannotCompileException { + if (Objects.equals("PVPSERVER", fieldAccess.getFieldName())) { + fieldAccess.replace("$_ = false;"); + logger.info("Instrumented PVPSERVER = false for Libila faith transfers."); + } + } + }); + ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() { + @Override + public void edit(FieldAccess fieldAccess) throws CannotCompileException { + if (Objects.equals("HOMESERVER", fieldAccess.getFieldName())) { + fieldAccess.replace("$_ = false;"); + logger.info("Instrumented HOMESERVER = false for Libila faith transfers."); } } }); } - - Util.setReason("Fix Portal Issues."); - CtClass ctPortal = classPool.get("com.wurmonline.server.questions.PortalQuestion"); - Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "willLeaveServer", "$_ = true;"); - Util.setReason("Fix Portal Issues."); - Util.instrumentDeclared(thisClass, ctPortal, "sendQuestion", "getKnowledge", "$_ = true;"); - Util.setReason("Disable the minimum 0.01 damage on shield damage, allowing damage modifiers to rule."); - CtClass ctCombatHandler = classPool.get("com.wurmonline.server.creatures.CombatHandler"); - replace = "if($1 < 0.5f){" - + " $_ = $proceed((float) 0, (float) $2);" - + "}else{" - + " $_ = $proceed($$);" - + "}"; - Util.instrumentDeclared(thisClass, ctCombatHandler, "checkShield", "max", replace); + CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); + CtClass[] params4 = { + CtClass.doubleType, + CtClass.booleanType, + CtClass.floatType, + CtClass.booleanType, + CtClass.doubleType + }; + String desc4 = Descriptor.ofMethod(CtClass.voidType, params4); - // - Allow GM's to bypass the 5 second emote sound limit. - // - replace = "if(this.getPower() > 0){" - + " return true;" - + "}"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "mayEmote", replace); + if (WyvernMods.higherFoodAffinities) { + Util.setReason("Increase food affinity to give 30% increased skillgain instead of 10%."); + replace = "int timedAffinity = (com.wurmonline.server.skills.AffinitiesTimed.isTimedAffinity(pid, this.getNumber()) ? 2 : 0);" + + "advanceMultiplicator *= (double)(1.0f + (float)timedAffinity * 0.1f);" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctSkill, "alterSkill", desc4, "hasSleepBonus", replace); + } - // - Make creatures wander slightly if they are shot from afar by an arrow - // - CtClass ctArrows = classPool.get("com.wurmonline.server.combat.Arrows"); - replace = "if(!defender.isPathing()){" - + " defender.startPathing(com.wurmonline.server.Server.rand.nextInt(100));" - + "}" - + "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctArrows, "addToHitCreature", "addAttacker", replace); - - Util.setReason("Broadcast death tabs to GL-Freedom."); - replace = MiscChanges.class.getName()+".broadCastDeaths($1, $2);"; - Util.insertBeforeDeclared(thisClass, ctPlayers, "broadCastDeathInfo", replace); - - Util.setReason("Broadcast player death tabs always."); - replace = MiscChanges.class.getName()+".broadCastDeathsPvE($0, $0.attackers);"; - Util.insertBeforeDeclared(thisClass, ctPlayer, "modifyRanking", replace); - - Util.setReason("Disable PvP only death tabs."); - replace = "$_ = true;"; - Util.instrumentDeclared(thisClass, ctPlayers, "broadCastDeathInfo", "isThisAPvpServer", replace); - - Util.setReason("Attempt to prevent libila from losing faith when crossing servers."); - CtClass ctIntraServerConnection = classPool.get("com.wurmonline.server.intra.IntraServerConnection"); - ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() { - @Override - public void edit(FieldAccess fieldAccess) throws CannotCompileException { - if (Objects.equals("PVPSERVER", fieldAccess.getFieldName())){ - fieldAccess.replace("$_ = false;"); - logger.info("Instrumented PVPSERVER = false for Libila faith transfers."); - } - } - }); - ctIntraServerConnection.getDeclaredMethod("savePlayerToDisk").instrument(new ExprEditor() { - @Override - public void edit(FieldAccess fieldAccess) throws CannotCompileException { - if (Objects.equals("HOMESERVER", fieldAccess.getFieldName())){ - fieldAccess.replace("$_ = false;"); - logger.info("Instrumented HOMESERVER = false for Libila faith transfers."); - } - } - }); - - Util.setReason("Increase food affinity to give 30% increased skillgain instead of 10%."); - CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); - CtClass[] params4 = { - CtClass.doubleType, - CtClass.booleanType, - CtClass.floatType, - CtClass.booleanType, - CtClass.doubleType - }; - String desc4 = Descriptor.ofMethod(CtClass.voidType, params4); - replace = "int timedAffinity = (com.wurmonline.server.skills.AffinitiesTimed.isTimedAffinity(pid, this.getNumber()) ? 2 : 0);" - + "advanceMultiplicator *= (double)(1.0f + (float)timedAffinity * 0.1f);" - + "$_ = $proceed($$);"; - Util.instrumentDescribed(thisClass, ctSkill, "alterSkill", desc4, "hasSleepBonus", replace); - - Util.setReason("Double the rate at which charcoal piles produce items."); CtClass[] params5 = { CtClass.booleanType, CtClass.booleanType, CtClass.longType }; String desc5 = Descriptor.ofMethod(CtClass.booleanType, params5); - replace = "this.createDaleItems();" - + "decayed = this.setDamage(this.damage + 1.0f * this.getDamageModifier());" - + "$_ = $proceed($$);"; - Util.instrumentDescribed(thisClass, ctItem, "poll", desc5, "createDaleItems", replace); + if (WyvernMods.fasterCharcoalBurn) { + Util.setReason("Double the rate at which charcoal piles produce items."); + replace = "this.createDaleItems();" + + "decayed = this.setDamage(this.damage + 1.0f * this.getDamageModifier());" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctItem, "poll", desc5, "createDaleItems", replace); + } Util.setReason("Allow traders to display more than 9 items of a single type."); CtClass ctTradeHandler = classPool.get("com.wurmonline.server.creatures.TradeHandler"); - ctTradeHandler.getDeclaredMethod("addItemsToTrade").instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if(m.getMethodName().equals("size") && m.getLineNumber() > 200){ // I don't think the line number check matters, but I'm leaving it here anyway. - m.replace("$_ = 1;"); - logger.info("Instrumented size for trades to allow traders to show more than 9 items at a time."); + if (WyvernMods.uncapTraderItemCount) { + ctTradeHandler.getDeclaredMethod("addItemsToTrade").instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("size") && m.getLineNumber() > 200) { // I don't think the line number check matters, but I'm leaving it here anyway. + m.replace("$_ = 1;"); + logger.info("Instrumented size for trades to allow traders to show more than 9 items at a time."); + } } - } - }); + }); + } // -- Identify players making over 10 commands per second and causing the server log message -- // CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); - replace = "$_ = $proceed($$);" - + "if(this.player != null){" - + " logger.info(\"Potential player macro: \"+this.player.getName()+\" [\"+this.commandsThisSecond+\" commands]\");" - + "}"; - Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_ITEM_CREATION_LIST", "log", replace); + if (WyvernMods.logExcessiveActions) { + Util.setReason("Log excessive actions per second."); + replace = "$_ = $proceed($$);" + + "if(this.player != null){" + + " logger.info(\"Potential player macro: \"+this.player.getName()+\" [\"+this.commandsThisSecond+\" commands]\");" + + "}"; + Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_ITEM_CREATION_LIST", "log", replace); + } //1f+0.5f*(1f-Math.pow(2, -Math.pow((eff-1f), pow1)/pow2)) + /* Disabled in 1.9 - Fixed with Priest Update. Util.setReason("Fix 100+ quality or power making certain interaction broken."); replace = "{" + "double pow1 = 1.0;" @@ -549,7 +598,7 @@ public class MiscChanges { + "double newEff = $1 >= 1.0 ? 1.0+0.5*(1.0-Math.pow(2.0, -Math.pow(($1-1.0), pow1)/pow2)) : Math.max(0.05, 1.0 - (1.0 - $1) * (1.0 - $1));" + "return newEff;" + "}"; - Util.setBodyDeclared(thisClass, ctServer, "getBuffedQualityEffect", replace); + Util.setBodyDeclared(thisClass, ctServer, "getBuffedQualityEffect", replace);*/ // double advanceMultiplicator, boolean decay, float times, boolean useNewSystem, double skillDivider) CtClass[] params = { @@ -560,189 +609,220 @@ public class MiscChanges { CtClass.doubleType }; String desc = Descriptor.ofMethod(CtClass.voidType, params); - double minRate = 1.0D; - double maxRate = 8.0D; - double newPower = 2.5; - Util.setReason("Adjust skill rate to a new, dynamic rate system."); - replace = "double minRate = " + String.valueOf(minRate) + ";" + - "double maxRate = " + String.valueOf(maxRate) + ";" + - "double newPower = " + String.valueOf(newPower) + ";" + - "$1 = $1*(minRate+(maxRate-minRate)*Math.pow((100-this.knowledge)*0.01, newPower));"; - Util.insertBeforeDescribed(thisClass, ctSkill,"alterSkill", desc, replace); + if (WyvernMods.useDynamicSkillRate) { + double minRate = 1.0D; + double maxRate = 8.0D; + double newPower = 2.5; - Util.setReason("Reduce chance of lockpicks breaking."); - replace = "$_ = 40f + $proceed($$);"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "checkLockpickBreakage", "getCurrentQualityLevel", replace); + Util.setReason("Adjust skill rate to a new, dynamic rate system."); + replace = "double minRate = " + String.valueOf(minRate) + ";" + + "double maxRate = " + String.valueOf(maxRate) + ";" + + "double newPower = " + String.valueOf(newPower) + ";" + + "$1 = $1*(minRate+(maxRate-minRate)*Math.pow((100-this.knowledge)*0.01, newPower));"; + Util.insertBeforeDescribed(thisClass, ctSkill, "alterSkill", desc, replace); + } + if (WyvernMods.reduceLockpickBreaking) { + Util.setReason("Reduce chance of lockpicks breaking."); + replace = "$_ = 40f + $proceed($$);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "checkLockpickBreakage", "getCurrentQualityLevel", replace); + } + + // Allow Freedom players to absorb mycelium CtClass ctTileBehaviour = classPool.get("com.wurmonline.server.behaviours.TileBehaviour"); CtMethod[] ctGetBehavioursFors = ctTileBehaviour.getDeclaredMethods("getBehavioursFor"); - for(CtMethod method : ctGetBehavioursFors){ - method.instrument(new ExprEditor(){ - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getKingdomTemplateId")) { - m.replace("$_ = 3;"); - } - } - }); - } + if (WyvernMods.allowFreedomMyceliumAbsorb) { + for (CtMethod method : ctGetBehavioursFors) { + method.instrument(new ExprEditor() { + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getKingdomTemplateId")) { + m.replace("$_ = 3;"); + } + } + }); + } + } CtClass ctMethodsStructure = classPool.get("com.wurmonline.server.behaviours.MethodsStructure"); - Util.setReason("Allow players to construct larger houses."); - float carpentryMultiplier = 2f; - replace = "if(!com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $_ = $proceed($$)*"+String.valueOf(carpentryMultiplier)+";" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToExpandStructure", "getKnowledge", replace); - Util.setReason("Allow players to construct larger houses."); - Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToContractStructure", "getKnowledge", replace); + if (WyvernMods.largerHouses) { + Util.setReason("Allow players to construct larger houses."); + float carpentryMultiplier = 2f; + replace = "if(!com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = $proceed($$)*" + String.valueOf(carpentryMultiplier) + ";" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToExpandStructure", "getKnowledge", replace); + Util.setReason("Allow players to construct larger houses."); + Util.instrumentDeclared(thisClass, ctMethodsStructure, "hasEnoughSkillToContractStructure", "getKnowledge", replace); + } - Util.setReason("Reduce power of imbues."); - replace = "$_ = Math.max(-80d, -80d+$2);"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "smear", "max", replace); + if (WyvernMods.reduceImbuePower) { + Util.setReason("Reduce power of imbues."); + replace = "$_ = Math.max(-80d, -80d+$2);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "smear", "max", replace); + } - Util.setReason("Update vehicle speeds reliably."); - replace = "if($1 == 8){" + - " $_ = 0;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "checkVehicleSpeeds", "nextInt", replace); + if (WyvernMods.fixVehicleSpeeds) { + Util.setReason("Update vehicle speeds reliably."); + replace = "if($1 == 8){" + + " $_ = 0;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "checkVehicleSpeeds", "nextInt", replace); + } - Util.setReason("Reduce mailing costs by 90%."); - CtClass ctMailSendConfirmQuestion = classPool.get("com.wurmonline.server.questions.MailSendConfirmQuestion"); - replace = "$_ = $_ / 10;"; - Util.insertAfterDeclared(thisClass, ctMailSendConfirmQuestion, "getCostForItem", replace); + if (WyvernMods.reduceMailingCosts) { + Util.setReason("Reduce mailing costs by 90%."); + CtClass ctMailSendConfirmQuestion = classPool.get("com.wurmonline.server.questions.MailSendConfirmQuestion"); + replace = "$_ = $_ / 10;"; + Util.insertAfterDeclared(thisClass, ctMailSendConfirmQuestion, "getCostForItem", replace); + } - Util.setReason("Remove guard tower guards helping against certain types of enemies."); - CtClass ctGuardTower = classPool.get("com.wurmonline.server.kingdom.GuardTower"); - replace = "if($0.isUnique() || "+Titans.class.getName()+".isTitan($0) || "+RareSpawns.class.getName()+".isRareCreature($0)){" + - " $_ = false;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctGuardTower, "alertGuards", "isWithinTileDistanceTo", replace); + if (WyvernMods.guardTargetChanges) { + Util.setReason("Remove guard tower guards helping against certain types of enemies."); + CtClass ctGuardTower = classPool.get("com.wurmonline.server.kingdom.GuardTower"); + replace = "if($0.isUnique() || " + Titans.class.getName() + ".isTitan($0) || " + RareSpawns.class.getName() + ".isRareCreature($0)){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctGuardTower, "alertGuards", "isWithinTileDistanceTo", replace); + } // Enable Strongwall for Libila and other spells on PvE CtClass ctSpellGenerator = classPool.get("com.wurmonline.server.spells.SpellGenerator"); - ctSpellGenerator.getDeclaredMethod("createSpells").instrument(new ExprEditor() { - @Override - public void edit(FieldAccess fieldAccess) throws CannotCompileException { - if (Objects.equals("PVPSERVER", fieldAccess.getFieldName())) - fieldAccess.replace("$_ = true;"); - logger.info("Instrumented SpellGenerator PVPSERVER field to enable all spells."); - } - }); + if (WyvernMods.enableLibilaStrongwallPvE) { + ctSpellGenerator.getDeclaredMethod("createSpells").instrument(new ExprEditor() { + @Override + public void edit(FieldAccess fieldAccess) throws CannotCompileException { + if (Objects.equals("PVPSERVER", fieldAccess.getFieldName())) + fieldAccess.replace("$_ = true;"); + logger.info("Instrumented SpellGenerator PVPSERVER field to enable all spells."); + } + }); + } - Util.setReason("Make heated food never decay if cooked by a royal cook."); CtClass ctTempStates = classPool.get("com.wurmonline.server.items.TempStates"); - replace = "$_ = $proceed($$);" + - "if(chefMade){" + - " $0.setName(\"royal \"+$0.getName());" + - " $0.setHasNoDecay(true);" + - "}"; - Util.instrumentDeclared(thisClass, ctTempStates, "checkForChange", "setName", replace); - Util.setReason("Stop royal food decay."); - // Item parent, int parentTemp, boolean insideStructure, boolean deeded, boolean saveLastMaintained, boolean inMagicContainer, boolean inTrashbin - CtClass[] params11 = { - ctItem, - CtClass.intType, - CtClass.booleanType, - CtClass.booleanType, - CtClass.booleanType, - CtClass.booleanType, - CtClass.booleanType - }; - String desc11 = Descriptor.ofMethod(CtClass.booleanType, params11); - replace = "if($0.isFood() && $0.hasNoDecay()){" + - " $_ = false;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctItem, "poll", desc11, "setDamage", replace); + if (WyvernMods.royalCookNoFoodDecay) { + Util.setReason("Make heated food never decay if cooked by a royal cook."); + replace = "$_ = $proceed($$);" + + "if(chefMade){" + + " $0.setName(\"royal \"+$0.getName());" + + " $0.setHasNoDecay(true);" + + "}"; + Util.instrumentDeclared(thisClass, ctTempStates, "checkForChange", "setName", replace); - Util.setReason("Allow mayors to command abandoned vehicles off their deed."); - replace = "if("+MiscChanges.class.getName()+".checkMayorCommand($0, $1)){" + - " return true;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctItem, "mayCommand", replace); + Util.setReason("Stop royal food decay."); + // Item parent, int parentTemp, boolean insideStructure, boolean deeded, boolean saveLastMaintained, boolean inMagicContainer, boolean inTrashbin + CtClass[] params11 = { + ctItem, + CtClass.intType, + CtClass.booleanType, + CtClass.booleanType, + CtClass.booleanType, + CtClass.booleanType, + CtClass.booleanType + }; + String desc11 = Descriptor.ofMethod(CtClass.booleanType, params11); + replace = "if($0.isFood() && $0.hasNoDecay()){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctItem, "poll", desc11, "setDamage", replace); + } + + if (WyvernMods.mayorsCommandAbandonedVehicles) { + Util.setReason("Allow mayors to command abandoned vehicles off their deed."); + replace = "if(" + MiscChanges.class.getName() + ".checkMayorCommand($0, $1)){" + + " return true;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctItem, "mayCommand", replace); + } - Util.setReason("Modify timed affinity timer."); CtClass ctAffinitiesTimed = classPool.get("com.wurmonline.server.skills.AffinitiesTimed"); - replace = "$_ = "+MiscChanges.class.getName()+".getFoodOpulenceBonus($0);"; - Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "addTimedAffinityFromBonus", "getFoodComplexity", replace); - Util.setReason("Food affinity timer normalization."); - replace = "long time = "+WurmCalendar.class.getName()+".getCurrentTime();" + - "if($0.getExpires($1) == null){" + - " $_ = Long.valueOf(time);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "add", "getExpires", replace); + if (WyvernMods.opulenceFoodAffinityTimerIncrease) { + Util.setReason("Add opulence bonus to food affinity timers."); + replace = "$_ = " + MiscChanges.class.getName() + ".getFoodOpulenceBonus($0);"; + Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "addTimedAffinityFromBonus", "getFoodComplexity", replace); + } - Util.setReason("Make bed QL affect sleep bonus timer."); - CtClass ctPlayerInfo = classPool.get("com.wurmonline.server.players.PlayerInfo"); - replace = "secs = "+MiscChanges.class.getName()+".getBedBonus(secs, this.bed);" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctPlayerInfo, "calculateSleep", "setSleep", replace); + if (WyvernMods.disableFoodFirstBiteBonus) { + Util.setReason("Food affinity timer normalization."); + replace = "long time = " + WurmCalendar.class.getName() + ".getCurrentTime();" + + "if($0.getExpires($1) == null){" + + " $_ = Long.valueOf(time);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "add", "getExpires", replace); + } - /*Util.setReason("Fix intrateleport block bug."); - replace = "if($6.contains(\"blocked\")){" + - " logger.info(\"Detected a blocked movement, resetting position back to old.\");" + - " $1 = $0.getMovementScheme().xOld;" + - " $2 = $0.getMovementScheme().yOld;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctCreature, "intraTeleport", replace);*/ + if (WyvernMods.bedQualitySleepBonus) { + Util.setReason("Make bed QL affect sleep bonus timer."); + CtClass ctPlayerInfo = classPool.get("com.wurmonline.server.players.PlayerInfo"); + replace = "secs = " + MiscChanges.class.getName() + ".getBedBonus(secs, this.bed);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctPlayerInfo, "calculateSleep", "setSleep", replace); + } - Util.setReason("Allow royal smith to improve smithing items faster."); - replace = "if("+MiscChanges.class.getName()+".royalSmithImprove($1, improve)){" + - " $_ = $proceed($$) * 0.9f;" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "getImproveActionTime", replace); - Util.setReason("Allow royal smith to improve smithing items faster."); - Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "getImproveActionTime", replace); - Util.setReason("Allow royal smith to improve smithing items faster. Also make tempering use water enchants."); - replace = "if("+MiscChanges.class.getName()+".royalSmithImprove($1, improve)){" + - " $_ = $proceed($1, target) * 0.9f;" + - "}else{" + - " $_ = $proceed($1, target);" + - "}"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "temper", "getImproveActionTime", replace); + if (WyvernMods.royalSmithImproveFaster) { + Util.setReason("Allow royal smith to improve smithing items faster."); + replace = "if(" + MiscChanges.class.getName() + ".royalSmithImprove($1, improve)){" + + " $_ = $proceed($$) * 0.9f;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "getImproveActionTime", replace); + Util.setReason("Allow royal smith to improve smithing items faster."); + Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "getImproveActionTime", replace); + Util.setReason("Allow royal smith to improve smithing items faster. Also make tempering use water enchants."); + replace = "if(" + MiscChanges.class.getName() + ".royalSmithImprove($1, improve)){" + + " $_ = $proceed($1, target) * 0.9f;" + + "}else{" + + " $_ = $proceed($1, target);" + + "}"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "temper", "getImproveActionTime", replace); + } // Fix for body strength not working properly when mounted. (Bdew) - ctCreature.getMethod("getTraitMovePercent", "(Z)F").instrument(new ExprEditor() { - private boolean first = true; + if (WyvernMods.fixMountedBodyStrength) { + ctCreature.getMethod("getTraitMovePercent", "(Z)F").instrument(new ExprEditor() { + private boolean first = true; - @Override - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getStrengthSkill")) { - if (first) - m.replace("wmod = wmod * 3D; $_ = $proceed() * (this.isUnicorn()?3D:2D);"); - else - m.replace("$_ = $proceed() * (this.isUnicorn()?3D:2D);"); - first = false; + @Override + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getStrengthSkill")) { + if (first) + m.replace("wmod = wmod * 3D; $_ = $proceed() * (this.isUnicorn()?3D:2D);"); + else + m.replace("$_ = $proceed() * (this.isUnicorn()?3D:2D);"); + first = false; + } } - } - }); + }); + } - Util.setReason("Modify food fill percent."); - CtClass[] params12 = { - ctAction, - ctCreature, - ctItem, - CtClass.floatType - }; - String desc12 = Descriptor.ofMethod(CtClass.booleanType, params12); - replace = "$_ = $proceed($1, $2, $3, $4, "+MiscChanges.class.getName()+".getNewFoodFill(qlevel));"; - Util.instrumentDescribed(thisClass, ctMethodsItems, "eat", desc12, "modifyHunger", replace); + if (WyvernMods.adjustedFoodBiteFill) { + Util.setReason("Modify food fill percent."); + CtClass[] params12 = { + ctAction, + ctCreature, + ctItem, + CtClass.floatType + }; + String desc12 = Descriptor.ofMethod(CtClass.booleanType, params12); + replace = "$_ = $proceed($1, $2, $3, $4, " + MiscChanges.class.getName() + ".getNewFoodFill(qlevel));"; + Util.instrumentDescribed(thisClass, ctMethodsItems, "eat", desc12, "modifyHunger", replace); + } // Fix for butchering not giving skill gain when butchering too many items + /* Disabled in 1.9 - No longer necessary due to fishing changes. ctMethodsItems.getDeclaredMethod("filet").instrument(new ExprEditor() { private boolean first = true; @@ -757,7 +837,7 @@ public class MiscChanges { } } } - }); + });*/ // How to add a skill! /*CtClass ctSkillSystem = classPool.get("com.wurmonline.server.skills.SkillSystem"); @@ -765,171 +845,172 @@ public class MiscChanges { ctSkillSystemConstructor.insertAfter("com.wurmonline.server.skills.SkillSystem.addSkillTemplate(new "+SkillTemplate.class.getName()+"(10096, \"Battle Yoyos\", 4000.0f, new int[]{1022}, 1209600000l, (short) 4, true, true));");*/ - Util.setReason("Hook for rare material usage in improvement."); - replace = "if("+MiscChanges.class.getName()+".rollRarityImprove($0, usedWeight)){" + - " rarity = source.getRarity();" + - "}" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "setWeight", replace); + if (WyvernMods.rareMaterialImprove) { + Util.setReason("Hook for rare material usage in improvement."); + replace = "if(" + MiscChanges.class.getName() + ".rollRarityImprove($0, usedWeight)){" + + " rarity = source.getRarity();" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "setWeight", replace); + } - Util.setReason("Bad luck protection on rarity windows."); - replace = "if($1 == 3600){" + - " $_ = "+MiscChanges.class.getName()+".getRarityWindowChance(this.getWurmId());" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDeclared(thisClass, ctPlayer, "poll", "nextInt", replace); + if (WyvernMods.rarityWindowBadLuckProtection) { + Util.setReason("Bad luck protection on rarity windows."); + replace = "if($1 == 3600){" + + " $_ = " + MiscChanges.class.getName() + ".getRarityWindowChance(this.getWurmId());" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "poll", "nextInt", replace); + } CtClass ctSimpleCreationEntry = classPool.get("com.wurmonline.server.items.SimpleCreationEntry"); - ctSimpleCreationEntry.getDeclaredMethod("run").instrument(new ExprEditor() { - private boolean first = true; - @Override - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getRarity")) { - if (first) { - m.replace("byte newRarity = "+MiscChanges.class.getName()+".getNewCreationRarity(this, source, target, template);" + - "if(newRarity > 0){" + - " act.setRarity(newRarity);" + - "}" + - "$_ = $proceed($$);"); - logger.info("Replaced getRarity in SimpleCreationEntry to allow functional rare creations."); - first = false; + if (WyvernMods.rareCreationAdjustments) { + ctSimpleCreationEntry.getDeclaredMethod("run").instrument(new ExprEditor() { + private boolean first = true; + + @Override + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getRarity")) { + if (first) { + m.replace("byte newRarity = " + MiscChanges.class.getName() + ".getNewCreationRarity(this, source, target, template);" + + "if(newRarity > 0){" + + " act.setRarity(newRarity);" + + "}" + + "$_ = $proceed($$);"); + logger.info("Replaced getRarity in SimpleCreationEntry to allow functional rare creations."); + first = false; + } } } - } - }); + }); + } - Util.setReason("Make armour title benefits always occur."); - replace = "$_ = improve.getNumber();"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "getSkillId", replace); - Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "getSkillId", replace); + if (WyvernMods.alwaysArmourTitleBenefits) { + Util.setReason("Make armour title benefits always occur."); + replace = "$_ = improve.getNumber();"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "improveItem", "getSkillId", replace); + Util.setReason("Make armour title benefits always occur."); + Util.instrumentDeclared(thisClass, ctMethodsItems, "polishItem", "getSkillId", replace); + } - Util.setReason("Make it so sorceries can be used anywhere with a flat 3x3 altar."); CtClass ctAbilities = classPool.get("com.wurmonline.server.players.Abilities"); - replace = "$_ = 1;"; - Util.instrumentDeclared(thisClass, ctAbilities, "isInProperLocation", "getTemplateId", replace); - Util.setReason("Make the key of the heavens only usable on PvE"); - replace = "if($1.getTemplateId() == 794 && com.wurmonline.server.Servers.localServer.PVPSERVER){" + - " $2.getCommunicator().sendNormalServerMessage(\"The \"+$1.getName()+\" may not be used on Arena.\");" + - " return false;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctAbilities, "isInProperLocation", replace); + if (WyvernMods.tomeUsageAnyAltar) { + Util.setReason("Make it so sorceries can be used anywhere with a flat 3x3 altar."); + replace = "$_ = 1;"; + Util.instrumentDeclared(thisClass, ctAbilities, "isInProperLocation", "getTemplateId", replace); + } - Util.setReason("Make drinks less filling."); - CtClass[] params13 = { - ctAction, - ctCreature, - ctItem, - CtClass.floatType - }; - String desc13 = Descriptor.ofMethod(CtClass.booleanType, params13); - replace = "if(template != 128){" + - " $_ = $proceed($1, $2, $3*5);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "sendActionControl", replace); - replace = "if(template != 128){" + - " $_ = $proceed($1/5, $2, $3, $4, $5);" + - "}else{" + - " $_ = $proceed($$);" + - "}"; - Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "modifyThirst", replace); + if (WyvernMods.keyOfHeavensLoginOnly) { + Util.setReason("Make the key of the heavens only usable on PvE"); + replace = "if($1.getTemplateId() == 794 && com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $2.getCommunicator().sendNormalServerMessage(\"The \"+$1.getName()+\" must be used on the login server.\");" + + " return false;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctAbilities, "isInProperLocation", replace); + } - Util.setReason("Disable Gem Augmentation skill from converting."); - CtClass ctMethodsReligion = classPool.get("com.wurmonline.server.behaviours.MethodsReligion"); - replace = "$_ = $proceed($1, $2, true, $4);"; - Util.instrumentDeclared(thisClass, ctMethodsReligion, "listen", "skillCheck", replace); + if (WyvernMods.lessFillingDrinks) { + Util.setReason("Make drinks less filling."); + CtClass[] params13 = { + ctAction, + ctCreature, + ctItem, + CtClass.floatType + }; + String desc13 = Descriptor.ofMethod(CtClass.booleanType, params13); + replace = "if(template != 128){" + + " $_ = $proceed($1, $2, $3*5);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "sendActionControl", replace); + replace = "if(template != 128){" + + " $_ = $proceed($1/5, $2, $3, $4, $5);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDescribed(thisClass, ctMethodsItems, "drink", desc13, "modifyThirst", replace); + } - Util.setReason("Disable GM commands from displaying in /help unless the player is a GM."); - CtClass ctServerTweaksHandler = classPool.get("com.wurmonline.server.ServerTweaksHandler"); - replace = "if($1.getPower() < 1){" + - " return;" + - "}"; - Util.insertBeforeDeclared(thisClass, ctServerTweaksHandler, "sendHelp", replace); + if (WyvernMods.disableHelpGMCommands) { + Util.setReason("Disable GM commands from displaying in /help unless the player is a GM."); + CtClass ctServerTweaksHandler = classPool.get("com.wurmonline.server.ServerTweaksHandler"); + replace = "if($1.getPower() < 1){" + + " return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctServerTweaksHandler, "sendHelp", replace); + } - Util.setReason("Make damage less likely to interrupt actions during combat."); - replace = "$1 = $1/2;"; - Util.insertBeforeDeclared(thisClass, ctCreature, "maybeInterruptAction", replace); + if (WyvernMods.reduceActionInterruptOnDamage) { + Util.setReason("Make damage less likely to interrupt actions during combat."); + replace = "$1 = $1/2;"; + Util.insertBeforeDeclared(thisClass, ctCreature, "maybeInterruptAction", replace); + } - Util.setReason("Fix mission null pointer exception."); - CtClass ctEpicServerStatus = classPool.get("com.wurmonline.server.epic.EpicServerStatus"); - replace = "if(itemplates.size() < 1){" + - " com.wurmonline.server.epic.EpicServerStatus.setupMissionItemTemplates();" + - "}"; - Util.insertBeforeDeclared(thisClass, ctEpicServerStatus, "getRandomItemTemplateUsed", replace); + if (WyvernMods.fixMissionNullPointerException) { + Util.setReason("Fix mission null pointer exception."); + CtClass ctEpicServerStatus = classPool.get("com.wurmonline.server.epic.EpicServerStatus"); + replace = "if(itemplates.size() < 1){" + + " com.wurmonline.server.epic.EpicServerStatus.setupMissionItemTemplates();" + + "}"; + Util.insertBeforeDeclared(thisClass, ctEpicServerStatus, "getRandomItemTemplateUsed", replace); + } - /*Util.setReason("Fix bug causing high cast spells to reduce power."); - CtClass ctSpellEffect = classPool.get("com.wurmonline.server.spells.SpellEffect"); - replace = "{" + - " final float mod = 5.0f * (1.0f - java.lang.Math.min($0.getPower(), 100f) / 100.0f);" + - " $0.setPower(mod + $1);" + - "}"; - Util.setBodyDeclared(thisClass, ctSpellEffect, "improvePower", replace);*/ + if (WyvernMods.disableSmeltingPots) { + Util.setReason("Disable smelting pots from being used."); + CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); + CtClass[] params14 = { + ctAction, + ctCreature, + ctItem, + ctItem, + CtClass.shortType, + CtClass.floatType + }; + String desc14 = Descriptor.ofMethod(CtClass.booleanType, params14); + replace = "if($5 == 519){" + + " $2.getCommunicator().sendNormalServerMessage(\"Smelting is disabled.\");" + + " return true;" + + "}"; + Util.insertBeforeDescribed(thisClass, ctItemBehaviour, "action", desc14, replace); + } - Util.setReason("Disable smelting pots from being used."); - CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); - CtClass[] params14 = { - ctAction, - ctCreature, - ctItem, - ctItem, - CtClass.shortType, - CtClass.floatType - }; - String desc14 = Descriptor.ofMethod(CtClass.booleanType, params14); - replace = "if($5 == 519){" + - " $2.getCommunicator().sendNormalServerMessage(\"Smelting is disabled.\");" + - " return true;" + - "}"; - Util.insertBeforeDescribed(thisClass, ctItemBehaviour, "action", desc14, replace); - - /*Util.setReason("Fix title NPE from sorting."); - CtClass ctTitleCompoundQuestion = classPool.get("com.wurmonline.server.questions.TitleCompoundQuestion"); - replace = "titles = "+MiscChanges.class.getName()+".cleanTitles(titles);" + - "int i = 0;" + - "while(i < titles.length){" + - " logger.info(\"Title: \"+titles[i]);" + - " i++;" + - "}" + - "$_ = $proceed($$);"; - Util.instrumentDeclared(thisClass, ctTitleCompoundQuestion, "sendQuestion", "sort", replace);*/ - - /*Util.setReason("Remove buff bar spam from sorceries."); - replace = "$_ = false;"; - Util.instrumentDeclared(thisClass, ctAbilities, "sendEffectsToCreature", "hasAnyAbility", replace);*/ - - Util.setReason("Hide buff bar icons for sorceries."); - CtClass ctSpellEffectsEnum = classPool.get("com.wurmonline.server.creatures.SpellEffectsEnum"); - CtClass ctString = classPool.get("java.lang.String"); - CtClass[] params15 = { - ctSpellEffectsEnum, - CtClass.intType, - ctString - }; - String desc15 = Descriptor.ofMethod(CtClass.voidType, params15); - CtClass[] params16 = { - ctSpellEffectsEnum, - CtClass.intType - }; - String desc16 = Descriptor.ofMethod(CtClass.voidType, params16); - replace = "$_ = "+MiscChanges.class.getName()+".shouldSendBuff($0);"; - Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc15, "isSendToBuffBar", replace); - Util.setReason("Hide buff bar icons for sorceries."); - Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc16, "isSendToBuffBar", replace); + if (WyvernMods.hideSorceryBuffBar) { + Util.setReason("Hide buff bar icons for sorceries."); + CtClass ctSpellEffectsEnum = classPool.get("com.wurmonline.server.creatures.SpellEffectsEnum"); + CtClass ctString = classPool.get("java.lang.String"); + CtClass[] params15 = { + ctSpellEffectsEnum, + CtClass.intType, + ctString + }; + String desc15 = Descriptor.ofMethod(CtClass.voidType, params15); + CtClass[] params16 = { + ctSpellEffectsEnum, + CtClass.intType + }; + String desc16 = Descriptor.ofMethod(CtClass.voidType, params16); + replace = "$_ = " + MiscChanges.class.getName() + ".shouldSendBuff($0);"; + Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc15, "isSendToBuffBar", replace); + Util.setReason("Hide buff bar icons for sorceries."); + Util.instrumentDescribed(thisClass, ctCommunicator, "sendAddStatusEffect", desc16, "isSendToBuffBar", replace); + } // 1.9 Achievement fix [Bdew] - classPool.getCtClass("com.wurmonline.server.players.Achievements").getMethod("loadAllAchievements", "()V") - .instrument(new ExprEditor(){ - @Override - public void edit(MethodCall m) throws CannotCompileException { - if (m.getMethodName().equals("getTimestamp")) - m.replace("$_=com.wurmonline.server.utils.DbUtilities.getTimestampOrNull(rs.getString($1)); " + - "if ($_==null) $_=new java.sql.Timestamp(java.lang.System.currentTimeMillis());"); - } - }); + if (WyvernMods.sqlAchievementFix) { + classPool.getCtClass("com.wurmonline.server.players.Achievements").getMethod("loadAllAchievements", "()V") + .instrument(new ExprEditor() { + @Override + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getTimestamp")) + m.replace("$_=com.wurmonline.server.utils.DbUtilities.getTimestampOrNull(rs.getString($1)); " + + "if ($_==null) $_=new java.sql.Timestamp(java.lang.System.currentTimeMillis());"); + } + }); + } } catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/PlayerTitles.java b/src/main/java/mod/sin/wyvern/PlayerTitles.java index ff6ec7b..7bff2bb 100644 --- a/src/main/java/mod/sin/wyvern/PlayerTitles.java +++ b/src/main/java/mod/sin/wyvern/PlayerTitles.java @@ -1,32 +1,18 @@ package mod.sin.wyvern; -import com.wurmonline.server.DbConnector; import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.players.Player; -import com.wurmonline.server.players.PlayerInfo; import com.wurmonline.server.players.Titles; -import com.wurmonline.server.utils.DbUtilities; -import javassist.CtClass; -import javassist.CtPrimitiveType; -import javassist.bytecode.Descriptor; -import mod.enumbuster.EnumBuster; -import org.gotti.wurmunlimited.modloader.ReflectionUtil; -import org.gotti.wurmunlimited.modloader.classhooks.HookManager; -import org.gotti.wurmunlimited.modloader.classhooks.InvocationHandlerFactory; +import net.bdew.wurm.tools.server.ModTitles; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.sql.*; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; public class PlayerTitles { public static Logger logger = Logger.getLogger(PlayerTitles.class.getName()); - private static Titles.Title[] titleArray; // Player Title Maps protected static ArrayList donatorTitles = new ArrayList<>(); @@ -37,10 +23,10 @@ public class PlayerTitles { // Event Title ID's public static int TITAN_SLAYER = 10000; public static int SPECTRAL = 10001; - public static int PASTAMANCER = 10002; + //public static int PASTAMANCER = 10002; // Player Donation Title ID's - public static int PATRON = 19999; + /*public static int PATRON = 19999; public static int DONATOR = 20000; public static int PAZZA_FAVORITE_GM = 20001; public static int WARRIORGEN_THAT_GUY = 20002; @@ -53,138 +39,43 @@ public class PlayerTitles { 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 onItemTemplatesCreated(){ - interceptLoadTitles(); - EnumBuster buster = new EnumBuster<>(Titles.Title.class, Titles.Title.class); - // Random titles for fun - //PlayerTitles.createTitle(buster, "Game_Master", 2500, "Game Master", "Game Master", -1, Titles.TitleType.NORMAL); - //PlayerTitles.createTitle(buster, "Developer", 2501, "Developer", "Developer", -1, Titles.TitleType.NORMAL); - //PlayerTitles.createTitle(buster, "Pet_Me", 2502, "Pet Me", "Pet Me", -1, Titles.TitleType.NORMAL); + public static int ATTICUS_THE_GREAT_ILLUMINATY = 20012;*/ + public static void init(){ + for (WyvernMods.CustomTitle title : WyvernMods.customTitles){ + createTitle(title.getTitleId(), title.getMaleTitle(), title.getFemaleTitle(), title.getSkillId(), title.getType()); + } // Event Titles - createTitle(buster, "Titan_Slayer", TITAN_SLAYER, "Titanslayer", "Titanslayer", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Spectral", SPECTRAL, "Spectral", "Spectral", -1, Titles.TitleType.NORMAL); + createTitle(TITAN_SLAYER, "Titanslayer", "Titanslayer", -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(buster, "Pastamancer", PASTAMANCER, "Pastamancer", "Pastamancer", -1, Titles.TitleType.NORMAL); + //createTitle(PASTAMANCER, "Pastamancer", "Pastamancer", -1, "NORMAL"); // Donation Titles - createTitle(buster, "Patron", PATRON, "Patron", "Patron", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Donator", DONATOR, "Donator", "Donator", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Pazza_FavoriteGM", PAZZA_FAVORITE_GM, "Sindusks Favourite GM", "Sindusks Favourite GM", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Warriorgen_ThatGuy", WARRIORGEN_THAT_GUY, "That Guy", "That Guy", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Eternallove_WarriorgensWife", ETERNALLOVE_WARRIORGENS_WIFE, "Warriorgens Wife", "Warriorgens Wife", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Bambam_ThornOne", BAMBAM_THORN_ONE, "Thorn One", "Thorn One", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Svenja_CareDependant", SVENJA_CARE_DEPENDANT, "The care-dependent", "The care-dependent", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Alexia_TheTreasuring", ALEXIA_THE_TREASURING, "The Treasuring", "The Treasuring", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Reevi_ScienceGuy", REEVI_SCIENCE_GUY, "Science Guy", "Science Guy", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Genocide_GrandDesigner", GENOCIDE_GRAND_DESIGNER, "Grand Designer", "Grand Designer", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Seleas_CrazyCatLord", SELEAS_CRAZY_CAT_LORD, "The Crazy Cat Lord", "The Crazy Cat Lord", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Piratemax_Slave", PIRATEMAX_SLAVE, "Slave", "Slave", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Eltacolad_TrueTaco", ELTACOLAD_TRUE_TACO, "The One True Taco", "The One True Taco", -1, Titles.TitleType.NORMAL); - createTitle(buster, "Atticus_The_Great_Illuminaty", ATTICUS_THE_GREAT_ILLUMINATY, "The Great Illuminaty", "The Great Illuminaty", -1, Titles.TitleType.NORMAL); + /* 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())); - titleArray = Titles.Title.values(); } - private static void createTitle(EnumBuster buster, String enumName, int id, String titleMale, String titleFemale, int skillId, Titles.TitleType type) { - Titles.Title testTitle = buster.make(enumName, 0, new Class[]{Integer.TYPE, String.class, String.class, Integer.TYPE, Titles.TitleType.class}, new Object[]{id, titleMale, titleFemale, skillId, type}); - buster.addByValue(testTitle); - logger.log(Level.INFO, String.format("Created new title with ID #%d: %s [\"%s\", \"%s\"]", id, enumName, titleMale, titleFemale)); - } - - public static boolean hasTitle(Creature c, int titleId) { - if (c.isPlayer()) { - Titles.Title[] titles; - Titles.Title[] arrtitle = titles = ((Player)c).getTitles(); - int n = arrtitle.length; - int n2 = 0; - while (n2 < n) { - Titles.Title title = arrtitle[n2]; - if (title == null) { - throw new RuntimeException("We have NULL in titles collection, that is not nice at all!"); - } - if (title.getTitleId() == titleId) { - return true; - } - ++n2; - } - } else { - return true; - } - return false; - } - - private static void interceptLoadTitles() { - String descriptor = Descriptor.ofMethod((CtClass)CtPrimitiveType.voidType, (CtClass[])new CtClass[]{CtClass.longType}); - HookManager.getInstance().registerHook("com.wurmonline.server.players.DbPlayerInfo", "loadTitles", descriptor, new InvocationHandlerFactory(){ - - public InvocationHandler createInvocationHandler() { - return new InvocationHandler(){ - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - Object result; - block8 : { - ResultSet rs; - Connection dbcon; - PreparedStatement ps; - result = method.invoke(proxy, args); - PlayerInfo pi = (PlayerInfo)proxy; - Set titles = ReflectionUtil.getPrivateField(pi, ReflectionUtil.getField(pi.getClass(), "titles")); - titles.remove(null); - dbcon = null; - ps = null; - rs = null; - try { - try { - dbcon = DbConnector.getPlayerDbCon(); - ps = dbcon.prepareStatement("select TITLEID from TITLES where WURMID=?"); - ps.setLong(1, pi.getPlayerId()); - rs = ps.executeQuery(); - while (rs.next()) { - if (Titles.Title.getTitle(rs.getInt("TITLEID")) != null){ - continue; - } - titles.add(PlayerTitles.getTitle(rs.getInt("TITLEID"))); - } - } - catch (SQLException ex) { - logger.log(Level.INFO, "Failed to load titles for " + pi.getPlayerId(), ex); - DbUtilities.closeDatabaseObjects(ps, rs); - DbConnector.returnConnection(dbcon); - break block8; - } - } - catch (Throwable throwable) { - DbUtilities.closeDatabaseObjects(ps, rs); - DbConnector.returnConnection(dbcon); - throw throwable; - } - DbUtilities.closeDatabaseObjects(ps, rs); - DbConnector.returnConnection(dbcon); - } - return result; - } - }; - } - - }); - } - - public static Titles.Title getTitle(int titleAsInt) { - int i = 0; - while (i < titleArray.length) { - if (titleAsInt == titleArray[i].getTitleId()) { - return titleArray[i]; - } - ++i; - } - throw new RuntimeException("Could not find title: " + titleAsInt); + private static void createTitle(int id, String titleMale, String titleFemale, int skillId, String type) { + ModTitles.addTitle(id, titleMale, titleFemale, skillId, type); + logger.log(Level.INFO, String.format("Created new title with ID #%d: [\"%s\", \"%s\"]", id, titleMale, titleFemale)); } public static boolean hasCustomTitle(Creature creature){ @@ -203,22 +94,33 @@ public class PlayerTitles { } public static void awardCustomTitles(Player p){ String name = p.getName(); - if(donatorTitles.contains(name)){ - Titles.Title donator = getTitle(DONATOR); + for (int titleId : WyvernMods.awardTitles.keySet()){ + try { + Titles.Title theTitle = Titles.Title.getTitle(titleId); + ArrayList playerList = WyvernMods.awardTitles.get(titleId); + if (playerList.contains(name)){ + p.addTitle(theTitle); + } + }catch(Exception e){ + 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 = getTitle(PATRON); + Titles.Title patron = Titles.Title.getTitle(PATRON); p.addTitle(patron); } if(customTitles.containsKey(name)){ - Titles.Title customTitle = getTitle(customTitles.get(name)); + Titles.Title customTitle = Titles.Title.getTitle(customTitles.get(name)); p.addTitle(customTitle); - } + }*/ } public static void preInit(){ // Donations - donatorTitles.add("Pazza"); + /*donatorTitles.add("Pazza"); customTitles.put("Pazza", PAZZA_FAVORITE_GM); // Sindusks Favorite GM donatorTitles.add("Warriorgen"); @@ -258,6 +160,6 @@ public class PlayerTitles { customTitles.put("Atticus", ATTICUS_THE_GREAT_ILLUMINATY); // The Great Illuminaty // Other rewards - customTitles.put("Critias", PASTAMANCER); + customTitles.put("Critias", PASTAMANCER);*/ } } diff --git a/src/main/java/mod/sin/wyvern/QualityOfLife.java b/src/main/java/mod/sin/wyvern/QualityOfLife.java index 59bf52a..1201d80 100644 --- a/src/main/java/mod/sin/wyvern/QualityOfLife.java +++ b/src/main/java/mod/sin/wyvern/QualityOfLife.java @@ -87,7 +87,6 @@ public class QualityOfLife { final Class thisClass = QualityOfLife.class; String replace; - Util.setReason("Allow players to mine directly into vehicles."); CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); @@ -106,45 +105,35 @@ public class QualityOfLife { CtClass.floatType }; String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1); - replace = "$_ = null;" - + QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDescribed(thisClass, ctCaveWallBehaviour, "action", desc1, "putItemInfrontof", replace); + if (WyvernMods.mineCaveToVehicle) { + Util.setReason("Allow players to mine directly into vehicles."); + replace = "$_ = null;" + + QualityOfLife.class.getName() + ".vehicleHook(performer, $0);"; + Util.instrumentDescribed(thisClass, ctCaveWallBehaviour, "action", desc1, "putItemInfrontof", replace); + } - /*Util.setReason("Allow players to surface mine directly into vehicles."); CtClass ctTileRockBehaviour = classPool.get("com.wurmonline.server.behaviours.TileRockBehaviour"); - CtClass[] params2 = { - ctAction, - ctCreature, - ctItem, - CtClass.intType, - CtClass.intType, - CtClass.booleanType, - CtClass.intType, - CtClass.intType, - CtClass.shortType, - CtClass.floatType - }; - String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2); - replace = "$_ = $proceed($$);" + - QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDescribed(thisClass, ctTileRockBehaviour, "action", desc2, "setDataXY", replace);*/ + if (WyvernMods.mineSurfaceToVehicle) { + Util.setReason("Allow players to surface mine directly into vehicles."); + replace = "$_ = $proceed($$);" + + QualityOfLife.class.getName() + ".vehicleHook(performer, $0);"; + Util.instrumentDeclared(thisClass, ctTileRockBehaviour, "mine", "setDataXY", replace); + } - Util.setReason("Allow players to surface mine directly into vehicles."); - CtClass ctTileRockBehaviour = classPool.get("com.wurmonline.server.behaviours.TileRockBehaviour"); - replace = "$_ = $proceed($$);" + - QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDeclared(thisClass, ctTileRockBehaviour, "mine", "setDataXY", replace); - - Util.setReason("Allow players to chop logs directly into vehicles."); CtClass ctMethodsItems = classPool.get("com.wurmonline.server.behaviours.MethodsItems"); - replace = "$_ = null;" + - QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDeclared(thisClass, ctMethodsItems, "chop", "putItemInfrontof", replace); + if (WyvernMods.chopLogsToVehicle) { + Util.setReason("Allow players to chop logs directly into vehicles."); + replace = "$_ = null;" + + QualityOfLife.class.getName() + ".vehicleHook(performer, $0);"; + Util.instrumentDeclared(thisClass, ctMethodsItems, "chop", "putItemInfrontof", replace); + } - Util.setReason("Allow statuettes to be used when not gold/silver."); - String desc100 = Descriptor.ofMethod(CtClass.booleanType, new CtClass[]{}); - replace = "{ return this.template.holyItem; }"; - Util.setBodyDescribed(thisClass, ctItem, "isHolyItem", desc100, replace); + if (WyvernMods.statuetteAnyMaterial) { + Util.setReason("Allow statuettes to be used when not gold/silver."); + String desc100 = Descriptor.ofMethod(CtClass.booleanType, new CtClass[]{}); + replace = "{ return this.template.holyItem; }"; + Util.setBodyDescribed(thisClass, ctItem, "isHolyItem", desc100, replace); + } /* Disabled in Wurm Unlimited 1.9 - Priest Rework changes removed this restriction. @@ -153,30 +142,34 @@ public class QualityOfLife { replace = "$_ = false;"; Util.instrumentDeclared(thisClass, ctMethodsCreatures, "tame", "isPriest", replace);*/ - Util.setReason("Send gems, source crystals, flint, etc. into vehicle."); - CtClass[] params2 = { - CtClass.intType, - CtClass.intType, - CtClass.intType, - CtClass.intType, - ctCreature, - CtClass.doubleType, - CtClass.booleanType, - ctAction - }; - String desc2 = Descriptor.ofMethod(ctItem, params2); - replace = "$_ = null;" + - QualityOfLife.class.getName()+".vehicleHook(performer, $0);"; - Util.instrumentDescribed(thisClass, ctTileRockBehaviour, "createGem", desc2, "putItemInfrontof", replace); + if (WyvernMods.mineGemsToVehicle) { + Util.setReason("Send gems, source crystals, flint, etc. into vehicle."); + CtClass[] params2 = { + CtClass.intType, + CtClass.intType, + CtClass.intType, + CtClass.intType, + ctCreature, + CtClass.doubleType, + CtClass.booleanType, + ctAction + }; + String desc2 = Descriptor.ofMethod(ctItem, params2); + replace = "$_ = null;" + + QualityOfLife.class.getName() + ".vehicleHook(performer, $0);"; + Util.instrumentDescribed(thisClass, ctTileRockBehaviour, "createGem", desc2, "putItemInfrontof", replace); + } - CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player"); - ctPlayer.getMethod("poll", "()Z").instrument(new ExprEditor() { - @Override - public void edit(FieldAccess f) throws CannotCompileException { - if (f.getFieldName().equals("vehicle") && f.isReader()) - f.replace("$_ = -10L;"); - } - }); + if (WyvernMods.regenerateStaminaOnVehicleAnySlope) { + CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player"); + ctPlayer.getMethod("poll", "()Z").instrument(new ExprEditor() { + @Override + public void edit(FieldAccess f) throws CannotCompileException { + if (f.getFieldName().equals("vehicle") && f.isReader()) + f.replace("$_ = -10L;"); + } + }); + } } catch ( NotFoundException | IllegalArgumentException | ClassCastException e) { throw new HookException(e); diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java index feba667..8910dad 100644 --- a/src/main/java/mod/sin/wyvern/WyvernMods.java +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -1,21 +1,24 @@ package mod.sin.wyvern; -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.ByteBuffer; -import java.nio.file.Paths; -import java.util.Properties; -import java.util.logging.FileHandler; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.logging.SimpleFormatter; - import com.wurmonline.server.Message; +import com.wurmonline.server.TimeConstants; import com.wurmonline.server.creatures.Creature; import com.wurmonline.server.items.*; +import com.wurmonline.server.players.Player; +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import javassist.expr.ExprEditor; +import javassist.expr.MethodCall; +import mod.sin.actions.*; import mod.sin.actions.items.SorcerySplitAction; +import mod.sin.creatures.*; +import mod.sin.creatures.titans.*; +import mod.sin.lib.Prop; import mod.sin.lib.Util; +import mod.sin.wyvern.bestiary.MethodsBestiary; +import mod.sin.wyvern.mastercraft.Mastercraft; import org.gotti.wurmunlimited.modloader.ReflectionUtil; import org.gotti.wurmunlimited.modloader.classhooks.HookException; import org.gotti.wurmunlimited.modloader.classhooks.HookManager; @@ -24,28 +27,177 @@ import org.gotti.wurmunlimited.modsupport.actions.ModActions; import org.gotti.wurmunlimited.modsupport.creatures.ModCreatures; import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviours; -import com.wurmonline.server.TimeConstants; -import com.wurmonline.server.players.Player; - -import javassist.CannotCompileException; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.NotFoundException; -import javassist.expr.ExprEditor; -import javassist.expr.MethodCall; -import mod.sin.actions.*; -import mod.sin.creatures.*; -import mod.sin.creatures.titans.*; -import mod.sin.wyvern.bestiary.MethodsBestiary; -import mod.sin.wyvern.mastercraft.Mastercraft; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Properties; +import java.util.logging.Logger; public class WyvernMods implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCreatedListener, ServerStartedListener, ServerPollListener, PlayerLoginListener, ChannelMessageListener { private static Logger logger = Logger.getLogger(WyvernMods.class.getName()); public static boolean espCounter = false; public static boolean enableDepots = false; - - boolean bDebug = false; + + // Miscellaneous Changes Module Configuration + public static boolean enableMiscChangesModule = true; + public static boolean enableInfoTab = true; + public static String infoTabName = "Server"; + public static ArrayList infoTabLines = new ArrayList<>(); + public static boolean ignoreBridgeChecks = true; + public static boolean disableMailboxUsageWhileLoaded = true; + public static boolean increasedLegendaryCreatures = true; + public static int increasedLegendaryFrequency = 5; + public static boolean allowFacebreykerNaturalSpawn = true; + public static boolean announcePlayerTitles = true; + public static boolean improveCombinedLeather = true; + public static boolean allowModdedImproveTemplates = true; + public static boolean fatigueActionOverride = true; + public static boolean fixPortalIssues = true; + public static boolean disableMinimumShieldDamage = true; + public static boolean disableGMEmoteLimit = true; + public static boolean creatureArcheryWander = true; + public static boolean globalDeathTabs = true; + public static boolean disablePvPOnlyDeathTabs = true; + public static boolean fixLibilaCrossingIssues = true; + public static boolean higherFoodAffinities = true; + public static boolean fasterCharcoalBurn = true; + public static boolean uncapTraderItemCount = true; + public static boolean logExcessiveActions = true; + public static boolean useDynamicSkillRate = true; + public static boolean reduceLockpickBreaking = true; + public static boolean allowFreedomMyceliumAbsorb = true; + public static boolean largerHouses = true; + public static boolean reduceImbuePower = true; + public static boolean fixVehicleSpeeds = true; + public static boolean reduceMailingCosts = true; + public static boolean guardTargetChanges = true; + public static boolean enableLibilaStrongwallPvE = true; + public static boolean royalCookNoFoodDecay = true; + public static boolean mayorsCommandAbandonedVehicles = true; + public static boolean opulenceFoodAffinityTimerIncrease = true; + public static boolean disableFoodFirstBiteBonus = true; + public static boolean bedQualitySleepBonus = true; + public static boolean royalSmithImproveFaster = true; + public static boolean fixMountedBodyStrength = true; + public static boolean adjustedFoodBiteFill = true; + public static boolean rareMaterialImprove = true; + public static boolean rarityWindowBadLuckProtection = true; + public static boolean rareCreationAdjustments = true; + public static boolean alwaysArmourTitleBenefits = true; + public static boolean tomeUsageAnyAltar = true; + public static boolean keyOfHeavensLoginOnly = true; + public static boolean lessFillingDrinks = true; + public static boolean disableHelpGMCommands = true; + public static boolean reduceActionInterruptOnDamage = true; + public static boolean fixMissionNullPointerException = true; + public static boolean disableSmeltingPots = true; + public static boolean hideSorceryBuffBar = true; + public static boolean sqlAchievementFix = true; + + // Arena Module Configuration + public static boolean enableArenaModule = true; + public static boolean equipHorseGearByLeading = true; + public static boolean lockpickingImprovements = true; + public static boolean placeDeedsOutsideKingdomInfluence = true; + public static boolean disablePMKs = true; + public static boolean disablePlayerChampions = true; + public static boolean arenaAggression = true; + public static boolean enemyTitleHook = true; + public static boolean enemyPresenceOnAggression = true; + public static boolean disableFarwalkerItems = true; + public static boolean alwaysAllowAffinitySteal = true; + public static boolean adjustFightSkillGain = true; + public static boolean useAggressionForNearbyEnemies = true; + public static boolean disablePvPCorpseProtection = true; + public static boolean bypassHousePermissions = true; + public static boolean allowStealingAgainstDeityWishes = true; + public static boolean sameKingdomVehicleTheft = true; + public static boolean adjustMineDoorDamage = true; + public static boolean sameKingdomPermissionsAdjustments = true; + public static boolean disableCAHelpOnPvP = true; + public static boolean sameKingdomVillageWarfare = true; + public static boolean adjustHotARewards = true; + public static boolean capMaximumGuards = true; + public static boolean disableTowerConstruction = true; + public static boolean adjustLocalRange = true; + public static boolean disableKarmaTeleport = true; + public static boolean limitLeadCreatures = true; + public static boolean adjustBashTimer = true; + public static boolean discordRelayHotAMessages = true; + public static boolean allowAttackingSameKingdomGuards = true; + public static boolean fixGuardsAttackingThemselves = true; + public static boolean reducedMineDoorOpenTime = true; + public static boolean allowSameKingdomFightSkillGains = true; + public static boolean allowArcheringOnSameKingdomDeeds = true; + public static boolean sendNewSpawnQuestionOnPvP = true; + public static boolean sendArtifactDigsToDiscord = true; + public static boolean makeFreedomFavoredKingdom = true; + public static boolean crownInfluenceOnAggression = true; + public static boolean disableOWFL = true; + public static boolean resurrectionStonesProtectSkill = true; + public static boolean resurrectionStonesProtectFightSkill = true; + public static boolean resurrectionStonesProtectAffinities = true; + public static boolean bypassPlantedPermissionChecks = true; + + // Custom Titles Module Configuration + public static boolean enableCustomTitlesModule = true; + public static ArrayList customTitles = new ArrayList<>(); + public static HashMap> awardTitles = new HashMap<>(); + + // Anti-Cheat Module Configuration + public static boolean enableAntiCheatModule = true; + public static boolean enableSpoofHiddenOre = true; + public static boolean prospectingVision = true; + public static boolean mapSteamIds = true; + + // Quality Of Life Module Configuration + public static boolean enableQualityOfLifeModule = true; + public static boolean mineCaveToVehicle = true; + public static boolean mineSurfaceToVehicle = true; + public static boolean chopLogsToVehicle = true; + public static boolean statuetteAnyMaterial = true; + public static boolean mineGemsToVehicle = true; + public static boolean regenerateStaminaOnVehicleAnySlope = true; + + // Treasure Chest Loot Module Configuration + public static boolean enableTreasureChestLootModule = true; + + public static class CustomTitle{ + protected int titleId; + protected String maleTitle; + protected String femaleTitle; + protected int skillId; + protected String type; + public CustomTitle(int titleId, String maleTitle, String femaleTitle, int skillId, String type){ + this.titleId = titleId; + this.maleTitle = maleTitle; + this.femaleTitle = femaleTitle; + this.skillId = skillId; + if (type.equals("NORMAL") || type.equals("MINOR") || type.equals("MASTER") || type.equals("LEGENDARY")){ + this.type = type; + }else{ + logger.info("Failed to register proper custom title type \""+type+"\" for title ID "+titleId+". Defaulting to \"NORMAL\""); + this.type = "NORMAL"; + } + } + public int getTitleId(){ + return titleId; + } + public String getMaleTitle(){ + return maleTitle; + } + public String getFemaleTitle(){ + return femaleTitle; + } + public int getSkillId(){ + return skillId; + } + public String getType(){ + return type; + } + } public static boolean customCommandHandler(ByteBuffer byteBuffer, Player player) throws UnsupportedEncodingException{ byte[] tempStringArr = new byte[byteBuffer.get() & 255]; @@ -71,35 +223,331 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea } public void configure(Properties properties) { - this.bDebug = Boolean.parseBoolean(properties.getProperty("debug", Boolean.toString(this.bDebug))); - try { - String logsPath = Paths.get("mods", new String[0]) + "/logs/"; - File newDirectory = new File(logsPath); - if (!newDirectory.exists()) { - newDirectory.mkdirs(); - } - FileHandler fh = new FileHandler(String.valueOf(String.valueOf(logsPath)) + this.getClass().getSimpleName() + ".log", 10240000, 200, true); - if (this.bDebug) { - fh.setLevel(Level.INFO); - } else { - fh.setLevel(Level.WARNING); - } - fh.setFormatter(new SimpleFormatter()); - logger.addHandler(fh); - } - catch (IOException ie) { - System.err.println(String.valueOf(this.getClass().getName()) + ": Unable to add file handler to logger"); - } - //this.logger.log(Level.INFO, "Property: " + this.somevalue); - this.Debug("Debugging messages are enabled."); - } + Prop.properties = properties; - private void Debug(String x) { - if (this.bDebug) { - System.out.println(String.valueOf(this.getClass().getSimpleName()) + ": " + x); - System.out.flush(); - logger.log(Level.INFO, x); - } + // -- Configuration Setting -- // + + // Miscellaneous Changes Module + enableMiscChangesModule = Prop.getBooleanProperty("enableMiscChangesModule", enableMiscChangesModule); + enableInfoTab = Prop.getBooleanProperty("enableInfoTab", enableInfoTab); + infoTabName = Prop.getStringProperty("infoTabName", infoTabName); + ignoreBridgeChecks = Prop.getBooleanProperty("ignoreBridgeChecks", ignoreBridgeChecks); + disableMailboxUsageWhileLoaded = Prop.getBooleanProperty("disableMailboxUsageWhileLoaded", disableMailboxUsageWhileLoaded); + increasedLegendaryCreatures = Prop.getBooleanProperty("increasedLegendaryCreatures", increasedLegendaryCreatures); + increasedLegendaryFrequency = Prop.getIntegerProperty("increasedLegendaryFrequency", increasedLegendaryFrequency); + allowFacebreykerNaturalSpawn = Prop.getBooleanProperty("allowFacebreykerNaturalSpawn", allowFacebreykerNaturalSpawn); + announcePlayerTitles = Prop.getBooleanProperty("announcePlayerTitles", announcePlayerTitles); + improveCombinedLeather = Prop.getBooleanProperty("improveCombinedLeather", improveCombinedLeather); + allowModdedImproveTemplates = Prop.getBooleanProperty("allowModdedImproveTemplates", allowModdedImproveTemplates); + fatigueActionOverride = Prop.getBooleanProperty("fatigueActionOverride", fatigueActionOverride); + fixPortalIssues = Prop.getBooleanProperty("fixPortalIssues", fixPortalIssues); + disableMinimumShieldDamage = Prop.getBooleanProperty("disableMinimumShieldDamage", disableMinimumShieldDamage); + disableGMEmoteLimit = Prop.getBooleanProperty("disableGMEmoteLimit", disableGMEmoteLimit); + creatureArcheryWander = Prop.getBooleanProperty("creatureArcheryWander", creatureArcheryWander); + globalDeathTabs = Prop.getBooleanProperty("globalDeathTabs", globalDeathTabs); + disablePvPOnlyDeathTabs = Prop.getBooleanProperty("disablePvPOnlyDeathTabs", disablePvPOnlyDeathTabs); + fixLibilaCrossingIssues = Prop.getBooleanProperty("fixLibilaCrossingIssues", fixLibilaCrossingIssues); + higherFoodAffinities = Prop.getBooleanProperty("higherFoodAffinities", higherFoodAffinities); + fasterCharcoalBurn = Prop.getBooleanProperty("fasterCharcoalBurn", fasterCharcoalBurn); + uncapTraderItemCount = Prop.getBooleanProperty("uncapTraderItemCount", uncapTraderItemCount); + logExcessiveActions = Prop.getBooleanProperty("logExcessiveActions", logExcessiveActions); + useDynamicSkillRate = Prop.getBooleanProperty("useDynamicSkillRate", useDynamicSkillRate); + reduceLockpickBreaking = Prop.getBooleanProperty("reduceLockpickBreaking", reduceLockpickBreaking); + allowFreedomMyceliumAbsorb = Prop.getBooleanProperty("allowFreedomMyceliumAbsorb", allowFreedomMyceliumAbsorb); + largerHouses = Prop.getBooleanProperty("largerHouses", largerHouses); + reduceImbuePower = Prop.getBooleanProperty("reduceImbuePower", reduceImbuePower); + fixVehicleSpeeds = Prop.getBooleanProperty("fixVehicleSpeeds", fixVehicleSpeeds); + reduceMailingCosts = Prop.getBooleanProperty("reduceMailingCosts", reduceMailingCosts); + guardTargetChanges = Prop.getBooleanProperty("guardTargetChanges", guardTargetChanges); + enableLibilaStrongwallPvE = Prop.getBooleanProperty("enableLibilaStrongwallPvE", enableLibilaStrongwallPvE); + royalCookNoFoodDecay = Prop.getBooleanProperty("royalCookNoFoodDecay", royalCookNoFoodDecay); + mayorsCommandAbandonedVehicles = Prop.getBooleanProperty("mayorsCommandAbandonedVehicles", mayorsCommandAbandonedVehicles); + opulenceFoodAffinityTimerIncrease = Prop.getBooleanProperty("opulenceFoodAffinityTimerIncrease", opulenceFoodAffinityTimerIncrease); + disableFoodFirstBiteBonus = Prop.getBooleanProperty("disableFoodFirstBiteBonus", disableFoodFirstBiteBonus); + bedQualitySleepBonus = Prop.getBooleanProperty("bedQualitySleepBonus", bedQualitySleepBonus); + royalSmithImproveFaster = Prop.getBooleanProperty("royalSmithImproveFaster", royalSmithImproveFaster); + fixMountedBodyStrength = Prop.getBooleanProperty("fixMountedBodyStrength", fixMountedBodyStrength); + adjustedFoodBiteFill = Prop.getBooleanProperty("adjustedFoodBiteFill", adjustedFoodBiteFill); + rareMaterialImprove = Prop.getBooleanProperty("rareMaterialImprove", rareMaterialImprove); + rarityWindowBadLuckProtection = Prop.getBooleanProperty("rarityWindowBadLuckProtection", rarityWindowBadLuckProtection); + rareCreationAdjustments = Prop.getBooleanProperty("rareCreationAdjustments", rareCreationAdjustments); + alwaysArmourTitleBenefits = Prop.getBooleanProperty("alwaysArmourTitleBenefits", alwaysArmourTitleBenefits); + tomeUsageAnyAltar = Prop.getBooleanProperty("tomeUsageAnyAltar", tomeUsageAnyAltar); + keyOfHeavensLoginOnly = Prop.getBooleanProperty("keyOfHeavensLoginOnly", keyOfHeavensLoginOnly); + lessFillingDrinks = Prop.getBooleanProperty("lessFillingDrinks", lessFillingDrinks); + disableHelpGMCommands = Prop.getBooleanProperty("disableHelpGMCommands", disableHelpGMCommands); + reduceActionInterruptOnDamage = Prop.getBooleanProperty("reduceActionInterruptOnDamage", reduceActionInterruptOnDamage); + fixMissionNullPointerException = Prop.getBooleanProperty("fixMissionNullPointerException", fixMissionNullPointerException); + disableSmeltingPots = Prop.getBooleanProperty("disableSmeltingPots", disableSmeltingPots); + hideSorceryBuffBar = Prop.getBooleanProperty("hideSorceryBuffBar", hideSorceryBuffBar); + sqlAchievementFix = Prop.getBooleanProperty("sqlAchievementFix", sqlAchievementFix); + + // Arena Module + enableArenaModule = Prop.getBooleanProperty("enableArenaModule", enableArenaModule); + equipHorseGearByLeading = Prop.getBooleanProperty("equipHorseGearByLeading", equipHorseGearByLeading); + lockpickingImprovements = Prop.getBooleanProperty("lockpickingImprovements", lockpickingImprovements); + placeDeedsOutsideKingdomInfluence = Prop.getBooleanProperty("placeDeedsOutsideKingdomInfluence", placeDeedsOutsideKingdomInfluence); + disablePMKs = Prop.getBooleanProperty("disablePMKs", disablePMKs); + disablePlayerChampions = Prop.getBooleanProperty("disablePlayerChampions", disablePlayerChampions); + arenaAggression = Prop.getBooleanProperty("arenaAggression", arenaAggression); + enemyTitleHook = Prop.getBooleanProperty("enemyTitleHook", enemyTitleHook); + enemyPresenceOnAggression = Prop.getBooleanProperty("enemyPresenceOnAggression", enemyPresenceOnAggression); + disableFarwalkerItems = Prop.getBooleanProperty("disableFarwalkerItems", disableFarwalkerItems); + alwaysAllowAffinitySteal = Prop.getBooleanProperty("alwaysAllowAffinitySteal", alwaysAllowAffinitySteal); + adjustFightSkillGain = Prop.getBooleanProperty("adjustFightSkillGain", adjustFightSkillGain); + useAggressionForNearbyEnemies = Prop.getBooleanProperty("useAggressionForNearbyEnemies", useAggressionForNearbyEnemies); + disablePvPCorpseProtection = Prop.getBooleanProperty("disablePvPCorpseProtection", disablePvPCorpseProtection); + bypassHousePermissions = Prop.getBooleanProperty("bypassHousePermissions", bypassHousePermissions); + allowStealingAgainstDeityWishes = Prop.getBooleanProperty("allowStealingAgainstDeityWishes", allowStealingAgainstDeityWishes); + sameKingdomVehicleTheft = Prop.getBooleanProperty("sameKingdomVehicleTheft", sameKingdomVehicleTheft); + adjustMineDoorDamage = Prop.getBooleanProperty("adjustMineDoorDamage", adjustMineDoorDamage); + sameKingdomPermissionsAdjustments = Prop.getBooleanProperty("sameKingdomPermissionsAdjustments", sameKingdomPermissionsAdjustments); + disableCAHelpOnPvP = Prop.getBooleanProperty("disableCAHelpOnPvP", disableCAHelpOnPvP); + sameKingdomVillageWarfare = Prop.getBooleanProperty("sameKingdomVillageWarfare", sameKingdomVillageWarfare); + adjustHotARewards = Prop.getBooleanProperty("adjustHotARewards", adjustHotARewards); + capMaximumGuards = Prop.getBooleanProperty("capMaximumGuards", capMaximumGuards); + disableTowerConstruction = Prop.getBooleanProperty("disableTowerConstruction", disableTowerConstruction); + adjustLocalRange = Prop.getBooleanProperty("adjustLocalRange", adjustLocalRange); + disableKarmaTeleport = Prop.getBooleanProperty("disableKarmaTeleport", disableKarmaTeleport); + limitLeadCreatures = Prop.getBooleanProperty("limitLeadCreatures", limitLeadCreatures); + adjustBashTimer = Prop.getBooleanProperty("adjustBashTimer", adjustBashTimer); + discordRelayHotAMessages = Prop.getBooleanProperty("discordRelayHotAMessages", discordRelayHotAMessages); + allowAttackingSameKingdomGuards = Prop.getBooleanProperty("allowAttackingSameKingdomGuards", allowAttackingSameKingdomGuards); + fixGuardsAttackingThemselves = Prop.getBooleanProperty("fixGuardsAttackingThemselves", fixGuardsAttackingThemselves); + reducedMineDoorOpenTime = Prop.getBooleanProperty("reducedMineDoorOpenTime", reducedMineDoorOpenTime); + allowSameKingdomFightSkillGains = Prop.getBooleanProperty("allowSameKingdomFightSkillGains", allowSameKingdomFightSkillGains); + allowArcheringOnSameKingdomDeeds = Prop.getBooleanProperty("allowArcheringOnSameKingdomDeeds", allowArcheringOnSameKingdomDeeds); + sendNewSpawnQuestionOnPvP = Prop.getBooleanProperty("sendNewSpawnQuestionOnPvP", sendNewSpawnQuestionOnPvP); + sendArtifactDigsToDiscord = Prop.getBooleanProperty("sendArtifactDigsToDiscord", sendArtifactDigsToDiscord); + makeFreedomFavoredKingdom = Prop.getBooleanProperty("makeFreedomFavoredKingdom", makeFreedomFavoredKingdom); + crownInfluenceOnAggression = Prop.getBooleanProperty("crownInfluenceOnAggression", crownInfluenceOnAggression); + disableOWFL = Prop.getBooleanProperty("disableOWFL", disableOWFL); + resurrectionStonesProtectSkill = Prop.getBooleanProperty("resurrectionStonesProtectSkill", resurrectionStonesProtectSkill); + resurrectionStonesProtectFightSkill = Prop.getBooleanProperty("resurrectionStonesProtectFightSkill", resurrectionStonesProtectFightSkill); + resurrectionStonesProtectAffinities = Prop.getBooleanProperty("resurrectionStonesProtectAffinities", resurrectionStonesProtectAffinities); + bypassPlantedPermissionChecks = Prop.getBooleanProperty("bypassPlantedPermissionChecks", bypassPlantedPermissionChecks); + + // Custom Titles Module + enableCustomTitlesModule = Prop.getBooleanProperty("enableCustomTitlesModule", enableCustomTitlesModule); + + // Anti-Cheat Module + enableAntiCheatModule = Prop.getBooleanProperty("enableAntiCheatModule", enableAntiCheatModule); + enableSpoofHiddenOre = Prop.getBooleanProperty("enableSpoofHiddenOre", enableSpoofHiddenOre); + prospectingVision = Prop.getBooleanProperty("prospectingVision", prospectingVision); + mapSteamIds = Prop.getBooleanProperty("mapSteamIds", mapSteamIds); + + // Quality Of Life Module + enableQualityOfLifeModule = Prop.getBooleanProperty("enableQualityOfLifeModule", enableQualityOfLifeModule); + mineCaveToVehicle = Prop.getBooleanProperty("mineCaveToVehicle", mineCaveToVehicle); + mineSurfaceToVehicle = Prop.getBooleanProperty("mineSurfaceToVehicle", mineSurfaceToVehicle); + chopLogsToVehicle = Prop.getBooleanProperty("chopLogsToVehicle", chopLogsToVehicle); + statuetteAnyMaterial = Prop.getBooleanProperty("statuetteAnyMaterial", statuetteAnyMaterial); + mineGemsToVehicle = Prop.getBooleanProperty("mineGemsToVehicle", mineGemsToVehicle); + regenerateStaminaOnVehicleAnySlope = Prop.getBooleanProperty("regenerateStaminaOnVehicleAnySlope", regenerateStaminaOnVehicleAnySlope); + + // Treasure Chest Loot Module + enableTreasureChestLootModule = Prop.getBooleanProperty("enableTreasureChestLootModule", enableTreasureChestLootModule); + + // Multiple-option Configuration Parsing + // This handles all the configurations that allow multiple different configurations to be applied. + for (String name : properties.stringPropertyNames()) { + try { + String value = properties.getProperty(name); + switch (name) { + case "debug": + case "classname": + case "classpath": + case "sharedClassLoader": + case "depend.requires": + case "depend.import": + case "depend.suggests": + break; //ignore + default: + if (name.startsWith("infoTabLine")) { + infoTabLines.add(value); + }else if (name.startsWith("addCustomTitle")) { + String[] values = value.split(","); + if(values.length > 5 || values.length < 5){ + logger.warning("Error parsing Custom Title: Invalid amount of arguments for following property: "+value); + } + int titleId = Integer.valueOf(values[0]); + String maleTitle = values[1]; + String femaleTitle = values[2]; + int skillId = Integer.valueOf(values[3]); + String titleType = values[4]; + customTitles.add(new CustomTitle(titleId, maleTitle, femaleTitle, skillId, titleType)); + }else if (name.startsWith("awardTitle")) { + String[] values = value.split(","); + if(values.length < 2){ + logger.warning("Error parsing Award Title: Invalid amount of arguments for following property: "+value); + } + int titleId = Integer.valueOf(values[0]); + ArrayList playerList; + if (awardTitles.containsKey(titleId)){ + // Has an entry already, add to the existing list. + playerList = awardTitles.get(titleId); + }else{ + // No entry, should create a new array and add it to the map + playerList = new ArrayList<>(); + } + for (int i = 1; i < values.length; i++){ + if(playerList.contains(values[i])){ + logger.warning("Duplicate player entry for single title: "+values[i]+" for title "+titleId+"."); + }else{ + playerList.add(values[i]); + } + } + awardTitles.put(titleId, playerList); + } + } + } catch (Exception e) { + logger.severe("Error processing property " + name); + e.printStackTrace(); + } + } + + // -- Configuration Print -- // + logger.info("Miscellaneous Changes Module: "+enableMiscChangesModule); + if(enableMiscChangesModule) { + logger.info("Information Tab: " + enableInfoTab); + if (enableInfoTab) { + logger.info("> Information Tab Name: " + infoTabName); + for (String tabLine : infoTabLines) { + logger.info("> Information Tab Line: " + tabLine); + } + } + logger.info("Ignore Bridge Checks: " + ignoreBridgeChecks); + logger.info("Disable Mailbox Usage While Loaded: " + disableMailboxUsageWhileLoaded); + logger.info("Increased Legendary Creatures: " + increasedLegendaryCreatures); + logger.info("Increased Legendary Frequency: " + increasedLegendaryFrequency + "x"); + logger.info("Allow Facebreyker Natural Spawn: " + allowFacebreykerNaturalSpawn); + logger.info("Announce Player Titles: " + announcePlayerTitles); + logger.info("Improve Combined Leather: " + improveCombinedLeather); + logger.info("Allow Modded Improve Templates: " + allowModdedImproveTemplates); + logger.info("Fatigue Action Override: " + fatigueActionOverride); + logger.info("Fix Portal Issues: " + fixPortalIssues); + logger.info("Disable Minimum Shield Damage: " + disableMinimumShieldDamage); + logger.info("Disable GM Emote Limit: " + disableGMEmoteLimit); + logger.info("Creature Archery Wander: " + creatureArcheryWander); + logger.info("Global Death Tabs: " + globalDeathTabs); + logger.info("Disable PvP Only Death Tabs: " + disablePvPOnlyDeathTabs); + logger.info("Fix Libila Crossing Issues: " + fixLibilaCrossingIssues); + logger.info("Higher Food Affinities: " + higherFoodAffinities); + logger.info("Faster Charcoal Burn: " + fasterCharcoalBurn); + logger.info("Uncap Trader Item Count: " + uncapTraderItemCount); + logger.info("Log Excessive Actions: " + logExcessiveActions); + logger.info("Use Dynamic Skill Rate: " + useDynamicSkillRate); + logger.info("Reduce Lockpick Breaking: " + reduceLockpickBreaking); + logger.info("Allow Freedom Mycelium Absorb: " + allowFreedomMyceliumAbsorb); + logger.info("Larger Houses: " + largerHouses); + logger.info("Reduce Imbue Power: " + reduceImbuePower); + logger.info("Fix Vehicle Speeds: " + fixVehicleSpeeds); + logger.info("Reduce Mailing Costs: " + reduceMailingCosts); + logger.info("Guard Target Changes: " + guardTargetChanges); + logger.info("Enable Libila Strongwall on PvE: " + enableLibilaStrongwallPvE); + logger.info("Royal Cook No Food Decay: " + royalCookNoFoodDecay); + logger.info("Mayors Command Abandoned Vehicles: " + mayorsCommandAbandonedVehicles); + logger.info("Opulence Food Affinity Timer Increase: " + opulenceFoodAffinityTimerIncrease); + logger.info("Disable Food First Bite Bonus: " + disableFoodFirstBiteBonus); + logger.info("Bed Quality Sleep Bonus: " + bedQualitySleepBonus); + logger.info("Royal Smith Improve Faster: " + royalSmithImproveFaster); + logger.info("Fix Mounted Body Strength: " + fixMountedBodyStrength); + logger.info("Adjusted Food Bite Fill: " + adjustedFoodBiteFill); + logger.info("Rare Material Improve: " + rareMaterialImprove); + logger.info("Rarity Window Bad Luck Protection: " + rarityWindowBadLuckProtection); + logger.info("Rare Creation Adjustments: " + rareCreationAdjustments); + logger.info("Always Armour Title Benefits: " + alwaysArmourTitleBenefits); + logger.info("Tome Usage Any Altar: " + tomeUsageAnyAltar); + logger.info("Key Of Heavens Login Only: " + keyOfHeavensLoginOnly); + logger.info("Less Filling Drinks: " + lessFillingDrinks); + logger.info("Disable Help GM Commands: " + disableHelpGMCommands); + logger.info("Reduce Action Interrupt On Damage: " + reduceActionInterruptOnDamage); + logger.info("Fix Mission Null Pointer Exception: " + fixMissionNullPointerException); + logger.info("Disable Smelting Pots: " + disableSmeltingPots); + logger.info("Hide Sorcery Buff Bar: " + hideSorceryBuffBar); + logger.info("SQL Achievement Fix: " + sqlAchievementFix); + } + + logger.info("Arena Module: "+enableArenaModule); + if(enableArenaModule) { + logger.info("Equip Horse Gear By Leading: " + equipHorseGearByLeading); + logger.info("Lockpicking Improvements: "+lockpickingImprovements); + logger.info("Place Deeds Outside Kingdom Influence: "+placeDeedsOutsideKingdomInfluence); + logger.info("Disable PMK's: "+disablePMKs); + logger.info("Disable Player Champions: "+disablePlayerChampions); + logger.info("Arena Aggression: "+arenaAggression); + logger.info("Enemy Title Hook: "+enemyTitleHook); + logger.info("Enemy Presence On Aggression: "+enemyPresenceOnAggression); + logger.info("Disable Farwalker Items: "+disableFarwalkerItems); + logger.info("Always Allow Affinity Steal: "+alwaysAllowAffinitySteal); + logger.info("Adjust Fight Skill Gain: "+adjustFightSkillGain); + logger.info("Use Aggression For Nearby Enemies: "+useAggressionForNearbyEnemies); + logger.info("Disable PvP Corpse Protection: "+disablePvPCorpseProtection); + logger.info("Bypass House Permissions: "+bypassHousePermissions); + logger.info("Allow Stealing Against Deity Wishes: "+allowStealingAgainstDeityWishes); + logger.info("Same Kingdom Vehicle Theft: "+sameKingdomVehicleTheft); + logger.info("Adjust Mine Door Damage: "+adjustMineDoorDamage); + logger.info("Same Kingdom Permission Adjustments: "+sameKingdomPermissionsAdjustments); + logger.info("Disable CA Help On PvP: "+disableCAHelpOnPvP); + logger.info("Same Kingdom Village Warfare: "+sameKingdomVillageWarfare); + logger.info("Adjust HotA Rewards: "+adjustHotARewards); + logger.info("Cap Maximum Guards: "+capMaximumGuards); + logger.info("Disable Tower Construction: "+disableTowerConstruction); + logger.info("Adjust Local Range: "+adjustLocalRange); + logger.info("Disable Karma Teleport: "+disableKarmaTeleport); + logger.info("Limit Lead Creatures: "+limitLeadCreatures); + logger.info("Adjust Bash Timer: "+adjustBashTimer); + logger.info("Discord Relay HotA Messages: "+discordRelayHotAMessages); + logger.info("Allow Attacking Same Kingdom Guards: "+allowAttackingSameKingdomGuards); + logger.info("Fix Guards Attacking Themselves: "+fixGuardsAttackingThemselves); + logger.info("Reduced Mine Door Open Time: "+reducedMineDoorOpenTime); + logger.info("Allow Same Kingdom Fight Skill Gains: "+allowSameKingdomFightSkillGains); + logger.info("Allow Archering On Same Kingdom Deeds: "+allowArcheringOnSameKingdomDeeds); + logger.info("Send New Spawn Question On PvP: "+sendNewSpawnQuestionOnPvP); + logger.info("Send Artifact Digs To Discord: "+sendArtifactDigsToDiscord); + logger.info("Make Freedom Favored Kingdom: "+makeFreedomFavoredKingdom); + logger.info("Crown Influence On Aggression: "+crownInfluenceOnAggression); + logger.info("Disable Open World Full Loot: "+disableOWFL); + logger.info("Resurrection Stones Protect Skill: "+resurrectionStonesProtectSkill); + logger.info("Resurrection Stones Protect Fight Skill: "+resurrectionStonesProtectFightSkill); + logger.info("Resurrection Stones Protect Affinities: "+resurrectionStonesProtectAffinities); + logger.info("Bypass Planted Permission Checks: "+bypassPlantedPermissionChecks); + } + + logger.info("Custom Titles Module: "+enableCustomTitlesModule); + if (enableCustomTitlesModule){ + for (CustomTitle title : customTitles){ + logger.info(String.format("Custom Title ID #%d: %s / %s for skill ID #%d of type %s.", + title.getTitleId(), title.getMaleTitle(), title.getFemaleTitle(), title.getSkillId(), title.getType())); + } + for (int titleId : awardTitles.keySet()){ + logger.info(String.format("Awarding Title ID #%d to players: %s", + titleId, awardTitles.get(titleId).toString())); + } + } + + logger.info("Anti-Cheat Module: "+enableAntiCheatModule); + if (enableAntiCheatModule){ + logger.info("Spoof Hidden Ore: "+enableSpoofHiddenOre); + if (enableSpoofHiddenOre){ + logger.info("Prospecting Vision: "+prospectingVision); + } + logger.info("Map Steam IDs: "+mapSteamIds); + } + + logger.info("Quality Of Life Module: "+enableQualityOfLifeModule); + if (enableQualityOfLifeModule){ + logger.info("Mine Cave To Vehicle: "+mineCaveToVehicle); + logger.info("Mine Surface To Vehicle: "+mineSurfaceToVehicle); + logger.info("Chop Logs To Vehicle: "+chopLogsToVehicle); + logger.info("Statuette Any Material: "+statuetteAnyMaterial); + logger.info("Mine Gems To Vehicle: "+mineGemsToVehicle); + logger.info("Regenerate Stamina On Vehicle Any Slope: "+regenerateStaminaOnVehicleAnySlope); + } + + logger.info("Treasure Chest Loot Module: "+enableTreasureChestLootModule); + + //this.logger.log(Level.INFO, "Property: " + this.somevalue); } public static void handleExamine(Creature performer, Item target) { @@ -122,29 +570,54 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea public void preInit() { logger.info("Pre-Initializing."); try { - ModActions.init(); - //Bounty.preInit(this); - TreasureChests.preInit(); - MiscChanges.preInit(); - Arena.preInit(); + ModActions.init(); // Initialize ModActions from Modloader + + // Misc Changes Module Pre-Init + if (enableMiscChangesModule) { + MiscChanges.preInit(); + } + + // Arena Module Pre-Init + if (enableArenaModule) { + Arena.preInit(); + } + + // Custom Titles Module Pre-Init + if (enableCustomTitlesModule) { + PlayerTitles.preInit(); + } + + // Anti-Cheat Module Pre-Init + if (enableAntiCheatModule) { + AntiCheat.preInit(); + } + + // Quality Of Life Module Pre-Init + if (enableQualityOfLifeModule) { + QualityOfLife.preInit(); + } + + // Treasure Chest Loot Module Pre-Init + if (enableTreasureChestLootModule) { + TreasureChests.preInit(); + } + Titans.preInit(); RareSpawns.preInit(); - PlayerTitles.preInit(); TeleportHandler.preInit(); MethodsBestiary.preInit(); MissionCreator.preInit(); - CombatChanges.preInit(); SkillChanges.preInit(); MeditationPerks.preInit(); MountedChanges.preInit(); EconomicChanges.preInit(); - QualityOfLife.preInit(); Bloodlust.preInit(); - AntiCheat.preInit(); Mastercraft.preInit(); - //Mastercraft.addNewTitles(); SupplyDepots.preInit(); KeyEvent.preInit(); + CombatChanges.preInit(); + + // Gem Augmentation is not complete. //GemAugmentation.preInit(); Class thisClass = WyvernMods.class; @@ -175,6 +648,9 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea @Override public void init() { logger.info("Initializing."); + if (WyvernMods.enableCustomTitlesModule) { + PlayerTitles.init(); + } ModCreatures.init(); ModVehicleBehaviours.init(); @@ -247,7 +723,7 @@ implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCrea logger.info("Creating Cache items."); Caches.createItems(); logger.info("Initiating Title changes."); - PlayerTitles.onItemTemplatesCreated(); + //PlayerTitles.onItemTemplatesCreated(); try { logger.info("Editing existing item templates."); ItemMod.modifyItems(); diff --git a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java index 27cba1b..683cb25 100644 --- a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java +++ b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java @@ -10,6 +10,7 @@ import com.wurmonline.server.items.ItemFactory; import com.wurmonline.server.items.ItemTemplate; import com.wurmonline.server.items.NoSuchTemplateException; import com.wurmonline.server.players.Player; +import com.wurmonline.server.players.Titles; import mod.piddagoras.duskombat.DamageEngine; import mod.sin.armour.SpectralHide; import mod.sin.creatures.Reaper; @@ -106,7 +107,7 @@ public class PlayerBounty { fightStrength = "legendary"; } player.getCommunicator().sendSafeServerMessage("The spirit recognizes you as a "+fightStrength+" warrior, and rewards you accordingly."); - player.addTitle(PlayerTitles.getTitle(PlayerTitles.SPECTRAL)); + player.addTitle(Titles.Title.getTitle(PlayerTitles.SPECTRAL)); }catch (NoSuchTemplateException | FailedException e) { e.printStackTrace(); } @@ -145,7 +146,7 @@ public class PlayerBounty { player.getInventory().insertItem(riftCache, true); } if(Titans.isTitan(mob)){ - player.addTitle(PlayerTitles.getTitle(PlayerTitles.TITAN_SLAYER)); + player.addTitle(Titles.Title.getTitle(PlayerTitles.TITAN_SLAYER)); Item affinityOrb = ItemFactory.createItem(AffinityOrb.templateId, 99f, mob.getName()); player.getInventory().insertItem(affinityOrb, true); Item titanCache = ItemFactory.createItem(TitanCache.templateId, 99f, mob.getName());