From 7f3733295f0982d562774b2340276778d2d540de Mon Sep 17 00:00:00 2001 From: Sindusk Date: Sat, 31 Mar 2018 13:23:16 -0400 Subject: [PATCH] Initial Commit --- .gitignore | 1 + .idea/compiler.xml | 9 + .idea/gradle.xml | 16 + ...com_github_Sindusk_sindusklibrary_v1_0.xml | 9 + ...org_gotti_wurmunlimited_common_2613165.xml | 9 + ...org_gotti_wurmunlimited_server_2613165.xml | 9 + ...nlimited_server_modlauncher_0_33_beta1.xml | 11 + ...dle__org_javassist_javassist_3_20_0_GA.xml | 11 + .idea/misc.xml | 6 + .idea/modules.xml | 10 + .idea/modules/WyvernMods_main.iml | 18 + .idea/modules/WyvernMods_test.iml | 20 + .idea/vcs.xml | 6 + .settings/org.eclipse.jdt.core.prefs | 106 ++ .settings/org.eclipse.m2e.core.prefs | 4 + WyvernMods.iml | 13 + bin/.gitignore | 2 + build.gradle | 31 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 51017 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 +++ gradlew.bat | 90 ++ pom.xml | 19 + .../mod/sin/actions/ArenaEscapeAction.java | 134 ++ .../mod/sin/actions/ArenaTeleportAction.java | 135 ++ .../mod/sin/actions/ReceiveMailAction.java | 150 +++ .../mod/sin/actions/UnequipAllAction.java | 118 ++ .../sin/actions/VillageTeleportAction.java | 122 ++ .../sin/actions/items/AffinityOrbAction.java | 129 ++ .../actions/items/ArenaCacheOpenAction.java | 124 ++ .../actions/items/ArrowPackUnpackAction.java | 164 +++ .../items/ChaosCrystalInfuseAction.java | 167 +++ .../actions/items/CrystalCombineAction.java | 137 ++ .../sin/actions/items/DepthDrillAction.java | 179 +++ .../items/DisintegrationRodAction.java | 129 ++ .../sin/actions/items/EnchantOrbAction.java | 135 ++ .../items/EnchantersCrystalInfuseAction.java | 187 +++ .../EternalReservoirCheckFuelAction.java | 123 ++ .../items/EternalReservoirRefuelAction.java | 130 ++ .../sin/actions/items/FriyanTabletAction.java | 127 ++ .../sin/actions/items/SealedMapAction.java | 126 ++ .../sin/actions/items/SoulstealAction.java | 152 +++ .../sin/actions/items/SupplyDepotAction.java | 139 ++ .../sin/actions/items/TreasureBoxAction.java | 142 ++ .../items/TreasureCacheOpenAction.java | 123 ++ .../java/mod/sin/armour/Glimmerscale.java | 60 + .../java/mod/sin/armour/GlimmerscaleBoot.java | 71 + .../mod/sin/armour/GlimmerscaleGlove.java | 71 + .../mod/sin/armour/GlimmerscaleHelmet.java | 71 + .../java/mod/sin/armour/GlimmerscaleHose.java | 71 + .../mod/sin/armour/GlimmerscaleSleeve.java | 71 + .../java/mod/sin/armour/GlimmerscaleVest.java | 71 + .../java/mod/sin/armour/SpectralBoot.java | 63 + src/main/java/mod/sin/armour/SpectralCap.java | 64 + .../java/mod/sin/armour/SpectralGlove.java | 63 + .../java/mod/sin/armour/SpectralHide.java | 43 + .../java/mod/sin/armour/SpectralHose.java | 74 ++ .../java/mod/sin/armour/SpectralJacket.java | 73 ++ .../java/mod/sin/armour/SpectralSleeve.java | 63 + src/main/java/mod/sin/creatures/Avenger.java | 75 ++ src/main/java/mod/sin/creatures/Bison.java | 67 + src/main/java/mod/sin/creatures/Charger.java | 116 ++ .../java/mod/sin/creatures/Facebreyker.java | 72 + .../java/mod/sin/creatures/ForestSpider.java | 80 ++ src/main/java/mod/sin/creatures/Giant.java | 84 ++ .../java/mod/sin/creatures/HornedPony.java | 114 ++ .../java/mod/sin/creatures/LargeBoar.java | 80 ++ .../java/mod/sin/creatures/LavaFiend.java | 43 + .../java/mod/sin/creatures/MacroSlayer.java | 63 + src/main/java/mod/sin/creatures/Reaper.java | 64 + .../java/mod/sin/creatures/RobZombie.java | 51 + src/main/java/mod/sin/creatures/SolDemon.java | 46 + .../java/mod/sin/creatures/SpectralDrake.java | 64 + .../java/mod/sin/creatures/SpiritTroll.java | 80 ++ src/main/java/mod/sin/creatures/Worg.java | 77 ++ .../java/mod/sin/creatures/WyvernBlack.java | 121 ++ .../java/mod/sin/creatures/WyvernGreen.java | 114 ++ .../java/mod/sin/creatures/WyvernRed.java | 110 ++ .../java/mod/sin/creatures/WyvernWhite.java | 117 ++ .../java/mod/sin/creatures/titans/Ifrit.java | 70 + .../mod/sin/creatures/titans/IfritFiend.java | 67 + .../mod/sin/creatures/titans/IfritSpider.java | 67 + .../java/mod/sin/creatures/titans/Lilith.java | 70 + .../sin/creatures/titans/LilithWraith.java | 67 + .../sin/creatures/titans/LilithZombie.java | 67 + src/main/java/mod/sin/items/AffinityOrb.java | 46 + src/main/java/mod/sin/items/ArenaCache.java | 45 + .../java/mod/sin/items/ArenaSupplyDepot.java | 51 + .../java/mod/sin/items/ArrowPackHunting.java | 62 + src/main/java/mod/sin/items/ArrowPackWar.java | 62 + src/main/java/mod/sin/items/ChaosCrystal.java | 52 + .../java/mod/sin/items/CoinDecoration.java | 65 + .../java/mod/sin/items/CorpseDecoration.java | 65 + src/main/java/mod/sin/items/DepthDrill.java | 62 + .../java/mod/sin/items/DisintegrationRod.java | 43 + src/main/java/mod/sin/items/EnchantOrb.java | 43 + .../java/mod/sin/items/EnchantersCrystal.java | 52 + .../java/mod/sin/items/EternalReservoir.java | 72 + src/main/java/mod/sin/items/FriyanTablet.java | 48 + src/main/java/mod/sin/items/HugeCrate.java | 68 + .../mod/sin/items/MassStorageBehaviour.java | 54 + .../java/mod/sin/items/MassStorageUnit.java | 87 ++ src/main/java/mod/sin/items/SealedMap.java | 45 + .../mod/sin/items/SkeletonDecoration.java | 62 + src/main/java/mod/sin/items/Soul.java | 45 + .../java/mod/sin/items/StatuetteBreyk.java | 68 + .../mod/sin/items/StatuetteCyberhusky.java | 68 + src/main/java/mod/sin/items/TreasureBox.java | 46 + .../mod/sin/items/caches/AnimalCache.java | 45 + .../mod/sin/items/caches/ArmourCache.java | 45 + .../mod/sin/items/caches/ArtifactCache.java | 45 + .../mod/sin/items/caches/CrystalCache.java | 45 + .../mod/sin/items/caches/DragonCache.java | 45 + .../java/mod/sin/items/caches/GemCache.java | 45 + .../java/mod/sin/items/caches/MoonCache.java | 45 + .../mod/sin/items/caches/PotionCache.java | 45 + .../java/mod/sin/items/caches/RiftCache.java | 45 + .../java/mod/sin/items/caches/ToolCache.java | 45 + .../sin/items/caches/TreasureMapCache.java | 45 + .../mod/sin/items/caches/WeaponCache.java | 45 + src/main/java/mod/sin/weapons/BattleYoyo.java | 70 + src/main/java/mod/sin/weapons/Club.java | 70 + .../java/mod/sin/weapons/Eviscerator.java | 71 + src/main/java/mod/sin/weapons/Knuckles.java | 80 ++ src/main/java/mod/sin/weapons/Warhammer.java | 72 + .../mod/sin/weapons/heads/WarhammerHead.java | 74 ++ .../mod/sin/weapons/titan/MaartensMight.java | 52 + .../mod/sin/weapons/titan/RaffehsRage.java | 52 + .../weapons/titan/VindictivesVengeance.java | 52 + .../mod/sin/weapons/titan/WilhelmsWrath.java | 52 + src/main/java/mod/sin/wyvern/AntiCheat.java | 230 ++++ src/main/java/mod/sin/wyvern/Bounty.java | 244 ++++ src/main/java/mod/sin/wyvern/Caches.java | 423 ++++++ src/main/java/mod/sin/wyvern/Crystals.java | 130 ++ src/main/java/mod/sin/wyvern/ItemMod.java | 419 ++++++ src/main/java/mod/sin/wyvern/MiscChanges.java | 943 +++++++++++++ .../java/mod/sin/wyvern/Soulstealing.java | 92 ++ .../java/mod/sin/wyvern/TreasureChests.java | 382 ++++++ src/main/java/mod/sin/wyvern/WyvernMods.java | 322 +++++ src/main/java/mod/sin/wyvern/arena/Arena.java | 1166 +++++++++++++++++ .../mod/sin/wyvern/arena/SupplyDepots.java | 211 +++ .../sin/wyvern/bestiary/MethodsBestiary.java | 470 +++++++ .../mod/sin/wyvern/bounty/LootBounty.java | 572 ++++++++ .../mod/sin/wyvern/bounty/PlayerBounty.java | 221 ++++ .../mod/sin/wyvern/invasion/Invasion.java | 48 + .../sin/wyvern/invasion/InvasionEvent.java | 41 + .../sin/wyvern/mastercraft/BytecodeTools.java | 494 +++++++ .../wyvern/mastercraft/ExtendTitleEnum.java | 223 ++++ .../sin/wyvern/mastercraft/Mastercraft.java | 242 ++++ .../java/mod/sin/wyvern/util/ItemUtil.java | 123 ++ 150 files changed, 16109 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/libraries/Gradle__com_github_Sindusk_sindusklibrary_v1_0.xml create mode 100644 .idea/libraries/Gradle__org_gotti_wurmunlimited_common_2613165.xml create mode 100644 .idea/libraries/Gradle__org_gotti_wurmunlimited_server_2613165.xml create mode 100644 .idea/libraries/Gradle__org_gotti_wurmunlimited_server_modlauncher_0_33_beta1.xml create mode 100644 .idea/libraries/Gradle__org_javassist_javassist_3_20_0_GA.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/modules/WyvernMods_main.iml create mode 100644 .idea/modules/WyvernMods_test.iml create mode 100644 .idea/vcs.xml create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.m2e.core.prefs create mode 100644 WyvernMods.iml create mode 100644 bin/.gitignore create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 pom.xml create mode 100644 src/main/java/mod/sin/actions/ArenaEscapeAction.java create mode 100644 src/main/java/mod/sin/actions/ArenaTeleportAction.java create mode 100644 src/main/java/mod/sin/actions/ReceiveMailAction.java create mode 100644 src/main/java/mod/sin/actions/UnequipAllAction.java create mode 100644 src/main/java/mod/sin/actions/VillageTeleportAction.java create mode 100644 src/main/java/mod/sin/actions/items/AffinityOrbAction.java create mode 100644 src/main/java/mod/sin/actions/items/ArenaCacheOpenAction.java create mode 100644 src/main/java/mod/sin/actions/items/ArrowPackUnpackAction.java create mode 100644 src/main/java/mod/sin/actions/items/ChaosCrystalInfuseAction.java create mode 100644 src/main/java/mod/sin/actions/items/CrystalCombineAction.java create mode 100644 src/main/java/mod/sin/actions/items/DepthDrillAction.java create mode 100644 src/main/java/mod/sin/actions/items/DisintegrationRodAction.java create mode 100644 src/main/java/mod/sin/actions/items/EnchantOrbAction.java create mode 100644 src/main/java/mod/sin/actions/items/EnchantersCrystalInfuseAction.java create mode 100644 src/main/java/mod/sin/actions/items/EternalReservoirCheckFuelAction.java create mode 100644 src/main/java/mod/sin/actions/items/EternalReservoirRefuelAction.java create mode 100644 src/main/java/mod/sin/actions/items/FriyanTabletAction.java create mode 100644 src/main/java/mod/sin/actions/items/SealedMapAction.java create mode 100644 src/main/java/mod/sin/actions/items/SoulstealAction.java create mode 100644 src/main/java/mod/sin/actions/items/SupplyDepotAction.java create mode 100644 src/main/java/mod/sin/actions/items/TreasureBoxAction.java create mode 100644 src/main/java/mod/sin/actions/items/TreasureCacheOpenAction.java create mode 100644 src/main/java/mod/sin/armour/Glimmerscale.java create mode 100644 src/main/java/mod/sin/armour/GlimmerscaleBoot.java create mode 100644 src/main/java/mod/sin/armour/GlimmerscaleGlove.java create mode 100644 src/main/java/mod/sin/armour/GlimmerscaleHelmet.java create mode 100644 src/main/java/mod/sin/armour/GlimmerscaleHose.java create mode 100644 src/main/java/mod/sin/armour/GlimmerscaleSleeve.java create mode 100644 src/main/java/mod/sin/armour/GlimmerscaleVest.java create mode 100644 src/main/java/mod/sin/armour/SpectralBoot.java create mode 100644 src/main/java/mod/sin/armour/SpectralCap.java create mode 100644 src/main/java/mod/sin/armour/SpectralGlove.java create mode 100644 src/main/java/mod/sin/armour/SpectralHide.java create mode 100644 src/main/java/mod/sin/armour/SpectralHose.java create mode 100644 src/main/java/mod/sin/armour/SpectralJacket.java create mode 100644 src/main/java/mod/sin/armour/SpectralSleeve.java create mode 100644 src/main/java/mod/sin/creatures/Avenger.java create mode 100644 src/main/java/mod/sin/creatures/Bison.java create mode 100644 src/main/java/mod/sin/creatures/Charger.java create mode 100644 src/main/java/mod/sin/creatures/Facebreyker.java create mode 100644 src/main/java/mod/sin/creatures/ForestSpider.java create mode 100644 src/main/java/mod/sin/creatures/Giant.java create mode 100644 src/main/java/mod/sin/creatures/HornedPony.java create mode 100644 src/main/java/mod/sin/creatures/LargeBoar.java create mode 100644 src/main/java/mod/sin/creatures/LavaFiend.java create mode 100644 src/main/java/mod/sin/creatures/MacroSlayer.java create mode 100644 src/main/java/mod/sin/creatures/Reaper.java create mode 100644 src/main/java/mod/sin/creatures/RobZombie.java create mode 100644 src/main/java/mod/sin/creatures/SolDemon.java create mode 100644 src/main/java/mod/sin/creatures/SpectralDrake.java create mode 100644 src/main/java/mod/sin/creatures/SpiritTroll.java create mode 100644 src/main/java/mod/sin/creatures/Worg.java create mode 100644 src/main/java/mod/sin/creatures/WyvernBlack.java create mode 100644 src/main/java/mod/sin/creatures/WyvernGreen.java create mode 100644 src/main/java/mod/sin/creatures/WyvernRed.java create mode 100644 src/main/java/mod/sin/creatures/WyvernWhite.java create mode 100644 src/main/java/mod/sin/creatures/titans/Ifrit.java create mode 100644 src/main/java/mod/sin/creatures/titans/IfritFiend.java create mode 100644 src/main/java/mod/sin/creatures/titans/IfritSpider.java create mode 100644 src/main/java/mod/sin/creatures/titans/Lilith.java create mode 100644 src/main/java/mod/sin/creatures/titans/LilithWraith.java create mode 100644 src/main/java/mod/sin/creatures/titans/LilithZombie.java create mode 100644 src/main/java/mod/sin/items/AffinityOrb.java create mode 100644 src/main/java/mod/sin/items/ArenaCache.java create mode 100644 src/main/java/mod/sin/items/ArenaSupplyDepot.java create mode 100644 src/main/java/mod/sin/items/ArrowPackHunting.java create mode 100644 src/main/java/mod/sin/items/ArrowPackWar.java create mode 100644 src/main/java/mod/sin/items/ChaosCrystal.java create mode 100644 src/main/java/mod/sin/items/CoinDecoration.java create mode 100644 src/main/java/mod/sin/items/CorpseDecoration.java create mode 100644 src/main/java/mod/sin/items/DepthDrill.java create mode 100644 src/main/java/mod/sin/items/DisintegrationRod.java create mode 100644 src/main/java/mod/sin/items/EnchantOrb.java create mode 100644 src/main/java/mod/sin/items/EnchantersCrystal.java create mode 100644 src/main/java/mod/sin/items/EternalReservoir.java create mode 100644 src/main/java/mod/sin/items/FriyanTablet.java create mode 100644 src/main/java/mod/sin/items/HugeCrate.java create mode 100644 src/main/java/mod/sin/items/MassStorageBehaviour.java create mode 100644 src/main/java/mod/sin/items/MassStorageUnit.java create mode 100644 src/main/java/mod/sin/items/SealedMap.java create mode 100644 src/main/java/mod/sin/items/SkeletonDecoration.java create mode 100644 src/main/java/mod/sin/items/Soul.java create mode 100644 src/main/java/mod/sin/items/StatuetteBreyk.java create mode 100644 src/main/java/mod/sin/items/StatuetteCyberhusky.java create mode 100644 src/main/java/mod/sin/items/TreasureBox.java create mode 100644 src/main/java/mod/sin/items/caches/AnimalCache.java create mode 100644 src/main/java/mod/sin/items/caches/ArmourCache.java create mode 100644 src/main/java/mod/sin/items/caches/ArtifactCache.java create mode 100644 src/main/java/mod/sin/items/caches/CrystalCache.java create mode 100644 src/main/java/mod/sin/items/caches/DragonCache.java create mode 100644 src/main/java/mod/sin/items/caches/GemCache.java create mode 100644 src/main/java/mod/sin/items/caches/MoonCache.java create mode 100644 src/main/java/mod/sin/items/caches/PotionCache.java create mode 100644 src/main/java/mod/sin/items/caches/RiftCache.java create mode 100644 src/main/java/mod/sin/items/caches/ToolCache.java create mode 100644 src/main/java/mod/sin/items/caches/TreasureMapCache.java create mode 100644 src/main/java/mod/sin/items/caches/WeaponCache.java create mode 100644 src/main/java/mod/sin/weapons/BattleYoyo.java create mode 100644 src/main/java/mod/sin/weapons/Club.java create mode 100644 src/main/java/mod/sin/weapons/Eviscerator.java create mode 100644 src/main/java/mod/sin/weapons/Knuckles.java create mode 100644 src/main/java/mod/sin/weapons/Warhammer.java create mode 100644 src/main/java/mod/sin/weapons/heads/WarhammerHead.java create mode 100644 src/main/java/mod/sin/weapons/titan/MaartensMight.java create mode 100644 src/main/java/mod/sin/weapons/titan/RaffehsRage.java create mode 100644 src/main/java/mod/sin/weapons/titan/VindictivesVengeance.java create mode 100644 src/main/java/mod/sin/weapons/titan/WilhelmsWrath.java create mode 100644 src/main/java/mod/sin/wyvern/AntiCheat.java create mode 100644 src/main/java/mod/sin/wyvern/Bounty.java create mode 100644 src/main/java/mod/sin/wyvern/Caches.java create mode 100644 src/main/java/mod/sin/wyvern/Crystals.java create mode 100644 src/main/java/mod/sin/wyvern/ItemMod.java create mode 100644 src/main/java/mod/sin/wyvern/MiscChanges.java create mode 100644 src/main/java/mod/sin/wyvern/Soulstealing.java create mode 100644 src/main/java/mod/sin/wyvern/TreasureChests.java create mode 100644 src/main/java/mod/sin/wyvern/WyvernMods.java create mode 100644 src/main/java/mod/sin/wyvern/arena/Arena.java create mode 100644 src/main/java/mod/sin/wyvern/arena/SupplyDepots.java create mode 100644 src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java create mode 100644 src/main/java/mod/sin/wyvern/bounty/LootBounty.java create mode 100644 src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java create mode 100644 src/main/java/mod/sin/wyvern/invasion/Invasion.java create mode 100644 src/main/java/mod/sin/wyvern/invasion/InvasionEvent.java create mode 100644 src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java create mode 100644 src/main/java/mod/sin/wyvern/mastercraft/ExtendTitleEnum.java create mode 100644 src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java create mode 100644 src/main/java/mod/sin/wyvern/util/ItemUtil.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..a8d902c --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..ba1ec5c --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Gradle__com_github_Sindusk_sindusklibrary_v1_0.xml b/.idea/libraries/Gradle__com_github_Sindusk_sindusklibrary_v1_0.xml new file mode 100644 index 0000000..d8a69ce --- /dev/null +++ b/.idea/libraries/Gradle__com_github_Sindusk_sindusklibrary_v1_0.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Gradle__org_gotti_wurmunlimited_common_2613165.xml b/.idea/libraries/Gradle__org_gotti_wurmunlimited_common_2613165.xml new file mode 100644 index 0000000..828f123 --- /dev/null +++ b/.idea/libraries/Gradle__org_gotti_wurmunlimited_common_2613165.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Gradle__org_gotti_wurmunlimited_server_2613165.xml b/.idea/libraries/Gradle__org_gotti_wurmunlimited_server_2613165.xml new file mode 100644 index 0000000..5cf5c19 --- /dev/null +++ b/.idea/libraries/Gradle__org_gotti_wurmunlimited_server_2613165.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Gradle__org_gotti_wurmunlimited_server_modlauncher_0_33_beta1.xml b/.idea/libraries/Gradle__org_gotti_wurmunlimited_server_modlauncher_0_33_beta1.xml new file mode 100644 index 0000000..019d815 --- /dev/null +++ b/.idea/libraries/Gradle__org_gotti_wurmunlimited_server_modlauncher_0_33_beta1.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Gradle__org_javassist_javassist_3_20_0_GA.xml b/.idea/libraries/Gradle__org_javassist_javassist_3_20_0_GA.xml new file mode 100644 index 0000000..fdd8716 --- /dev/null +++ b/.idea/libraries/Gradle__org_javassist_javassist_3_20_0_GA.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..84da703 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..ad87626 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules/WyvernMods_main.iml b/.idea/modules/WyvernMods_main.iml new file mode 100644 index 0000000..63a6697 --- /dev/null +++ b/.idea/modules/WyvernMods_main.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules/WyvernMods_test.iml b/.idea/modules/WyvernMods_test.iml new file mode 100644 index 0000000..c2109e4 --- /dev/null +++ b/.idea/modules/WyvernMods_test.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..81001c9 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,106 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=info +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=info +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=info +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=error +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=info +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/WyvernMods.iml b/WyvernMods.iml new file mode 100644 index 0000000..8d9127d --- /dev/null +++ b/WyvernMods.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100644 index 0000000..ec58449 --- /dev/null +++ b/bin/.gitignore @@ -0,0 +1,2 @@ +/mod/ +/org/ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..9aa4a10 --- /dev/null +++ b/build.gradle @@ -0,0 +1,31 @@ +apply plugin: 'java' + +group "mod.sin" +version "1.0" + +repositories { + mavenCentral() + maven { url "http://gotti.no-ip.org/maven/repository" } + maven { url 'https://jitpack.io' } +} + +dependencies { + compile 'org.gotti.wurmunlimited:server-modlauncher:0.33-beta1' + compile 'com.github.Sindusk:sindusklibrary:v1.0' +} + +jar { + archiveName "${project.name}.jar" +} + + +task dist(type: Zip) { + into("mods", { + into(project.name, { + from jar + }) + from fileTree(dir: 'mods', include: '*') + }) + + archiveName "${project.name}-${project.version}.zip" +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..b7612167031001b7b84baf2a959e8ea8ad03c011 GIT binary patch literal 51017 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

N(DARnfPMFG|;(rIGZH1uB1rN;y7UlJ8 znb!RwO#5WS_%cPPlwSw94PTKP64}}J!~E1}ch9``2jvUrB*#@up8L&*`tqgq ztTAS@^33w-5hFZAH&{j)?l0<)9X(d`N|yLk!E=iT%PD-FTJ!|hqyj%RFFP`SaL;|_ z$(+VYhKm)K@Oe~+eZK(6ElQNdfimBrdKjeVl57_7p^|)jrzt|wyRonj$j9Bji!


f)EE4q$t9yObmyG04W0z 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 t|KH7qPwVTc?c*oWQQiM74F8)Y \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5c9dead --- /dev/null +++ b/pom.xml @@ -0,0 +1,19 @@ + + 4.0.0 + WyvernMods + WyvernMods + 0.0.1-SNAPSHOT + + src + + + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/ArenaEscapeAction.java b/src/main/java/mod/sin/actions/ArenaEscapeAction.java new file mode 100644 index 0000000..3ba9b7e --- /dev/null +++ b/src/main/java/mod/sin/actions/ArenaEscapeAction.java @@ -0,0 +1,134 @@ +package mod.sin.actions; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Server; +import com.wurmonline.server.ServerEntry; +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.players.Player; + +public class ArenaEscapeAction implements ModAction { + private static Logger logger = Logger.getLogger(ArenaEscapeAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public ArenaEscapeAction() { + logger.log(Level.WARNING, "ArenaEscapeAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Escape the Arena", + "escaping", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && (object.getTemplateId() == ItemList.bodyBody || object.getTemplateId() == ItemList.bodyHand) && Servers.localServer.PVPSERVER) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(!Servers.localServer.PVPSERVER){ + performer.getCommunicator().sendNormalServerMessage("You must be in the Arena in order to escape it!"); + return true; + } + if(performer.isStealth()){ + performer.getCommunicator().sendNormalServerMessage("You cannot escape while stealthed."); + return true; + } + if(performer.getEnemyPresense() > 0 || performer.isFighting()){ + performer.getCommunicator().sendNormalServerMessage("Nearby enemies prevent your escape. Clear the area and try again."); + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You prepare your body and mind to transfer to another realm."); + act.setTimeLeft(1200); + performer.sendActionControl("Preparing", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + ServerEntry targetserver = Servers.localServer.serverWest; + if(targetserver == null){ + performer.getCommunicator().sendNormalServerMessage("Error: Something went wrong [TARGETSERVER=NULL]."); + return true; + } + if (!targetserver.isAvailable(performer.getPower(), true)) { + performer.getCommunicator().sendNormalServerMessage(targetserver.name + " is not currently available."); + return true; + } + performer.getCommunicator().sendNormalServerMessage("You successfully escape the arena."); + performer.getCommunicator().sendNormalServerMessage("You transfer to " + targetserver.name + "."); + Server.getInstance().broadCastAction(performer.getName() + " transfers to " + targetserver.name + ".", performer, 5); + int tilex = targetserver.SPAWNPOINTJENNX; + int tiley = targetserver.SPAWNPOINTJENNY; + ((Player)performer).sendTransfer(Server.getInstance(), targetserver.INTRASERVERADDRESS, Integer.parseInt(targetserver.INTRASERVERPORT), targetserver.INTRASERVERPASSWORD, targetserver.id, tilex, tiley, true, false, performer.getKingdomId()); + ((Player)performer).transferCounter = 30; + return true; + } + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/ArenaTeleportAction.java b/src/main/java/mod/sin/actions/ArenaTeleportAction.java new file mode 100644 index 0000000..e98d661 --- /dev/null +++ b/src/main/java/mod/sin/actions/ArenaTeleportAction.java @@ -0,0 +1,135 @@ +package mod.sin.actions; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Server; +import com.wurmonline.server.ServerEntry; +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.players.Player; + +public class ArenaTeleportAction implements ModAction { + private static Logger logger = Logger.getLogger(ArenaTeleportAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public ArenaTeleportAction() { + logger.log(Level.WARNING, "ArenaTeleport()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Teleport to Arena", + "preparing for combat", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && (object.getTemplateId() == ItemList.bodyBody || object.getTemplateId() == ItemList.bodyHand) && Servers.localServer.id == 567) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(Servers.localServer.id != 567){ + performer.getCommunicator().sendNormalServerMessage("You cannot enter the arena from here."); + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You sit and begin to transfer your mind."); + act.setTimeLeft(600); + performer.sendActionControl("Transferring", true, act.getTimeLeft()); + }else if(act.currentSecond() == 10){ + performer.getCommunicator().sendAlertServerMessage("You are about to enter a PvP environment.", (byte) 3); + }else if(act.currentSecond() == 20){ + performer.getCommunicator().sendNormalServerMessage("Death will leave your corpse and return you here. Anyone may loot your corpse in the arena.", (byte) 3); + }else if(act.currentSecond() == 30){ + performer.getCommunicator().sendNormalServerMessage("Upon transfer, you will be placed in a random location. This could be safely outside of danger, or directly on a group of enemies.", (byte) 3); + }else if(act.currentSecond() == 40){ + performer.getCommunicator().sendNormalServerMessage("You can equip creatures such as horses by simply leading them. Taming is not required in the Arena.", (byte) 3); + }else if(act.currentSecond() == 55){ + performer.getCommunicator().sendNormalServerMessage("It appears you have accepted these conditions. Transferring to the arena. Good luck.", (byte) 3); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + ServerEntry targetserver = Servers.localServer.serverEast; + if(targetserver == null){ + performer.getCommunicator().sendNormalServerMessage("Error: Something went wrong [TARGETSERVER=NULL]."); + return true; + } + if (!targetserver.isAvailable(performer.getPower(), true)) { + performer.getCommunicator().sendNormalServerMessage(targetserver.name + " is not currently available."); + return true; + } + performer.getCommunicator().sendNormalServerMessage("You transfer to " + targetserver.name + "."); + Server.getInstance().broadCastAction(performer.getName() + " transfers to " + targetserver.name + ".", performer, 5); + int tilex = 128+Server.rand.nextInt(768); + int tiley = 128+Server.rand.nextInt(768); + ((Player)performer).sendTransfer(Server.getInstance(), targetserver.INTRASERVERADDRESS, Integer.parseInt(targetserver.INTRASERVERPORT), targetserver.INTRASERVERPASSWORD, targetserver.id, tilex, tiley, true, false, performer.getKingdomId()); + ((Player)performer).transferCounter = 30; + return true; + } + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/ReceiveMailAction.java b/src/main/java/mod/sin/actions/ReceiveMailAction.java new file mode 100644 index 0000000..f133384 --- /dev/null +++ b/src/main/java/mod/sin/actions/ReceiveMailAction.java @@ -0,0 +1,150 @@ +package mod.sin.actions; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.NoSuchItemException; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.WurmMail; +import com.wurmonline.server.players.Player; + +public class ReceiveMailAction implements ModAction { + private static Logger logger = Logger.getLogger(ReceiveMailAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public ReceiveMailAction() { + logger.log(Level.WARNING, "ReceiveMailAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Receive all mail", + "receiving", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && object.isMailBox() && object.getSpellCourierBonus() > 0f) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + if(performer instanceof Player){ + Player player = (Player) performer; + if (!target.isMailBox()){ + player.getCommunicator().sendSafeServerMessage("You can only receive mail at a mailbox."); + return true; + } + if(target.getSpellCourierBonus() <= 0f){ + player.getCommunicator().sendSafeServerMessage("The mailbox must be enchanted before receiving mail."); + return true; + } + if(!performer.isWithinDistanceTo(target.getPosX(), target.getPosY(), target.getPosZ(), 4.0f)){ + player.getCommunicator().sendSafeServerMessage("You must be closer to collect mail."); + return true; + } + if(!target.isEmpty(false)){ + player.getCommunicator().sendSafeServerMessage("Empty the mailbox first."); + return true; + } + Set mailset = WurmMail.getSentMailsFor(performer.getWurmId(), 100); + if(mailset.isEmpty()){ + player.getCommunicator().sendSafeServerMessage("You have no mail to collect."); + return true; + } + Iterator it = mailset.iterator(); + WurmMail m; + HashSet itemset = new HashSet(); + while(it.hasNext()){ + m = it.next(); + if(m.rejected || m.price > 0){ + continue; + } + try { + itemset.add(Items.getItem(m.itemId)); + } catch (NoSuchItemException e) { + e.printStackTrace(); + } + } + if(!itemset.isEmpty()){ + player.getCommunicator().sendSafeServerMessage("The "+itemset.size()+" items that were sent via mail are now available."); + for (Item item : itemset) { + Item[] contained4 = item.getAllItems(true); + for (int c4 = 0; c4 < contained4.length; ++c4) { + contained4[c4].setMailed(false); + contained4[c4].setLastOwnerId(performer.getWurmId()); + } + WurmMail.removeMail(item.getWurmId()); + target.insertItem(item, true); + item.setLastOwnerId(performer.getWurmId()); + item.setMailed(false); + logger.log(Level.INFO, performer.getName() + " received " + item.getName() + " " + item.getWurmId()); + } + } + }else{ + logger.info("Somehow a non-player activated an Affinity Orb..."); + } + return true; + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/UnequipAllAction.java b/src/main/java/mod/sin/actions/UnequipAllAction.java new file mode 100644 index 0000000..04c44b0 --- /dev/null +++ b/src/main/java/mod/sin/actions/UnequipAllAction.java @@ -0,0 +1,118 @@ +package mod.sin.actions; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.NoSuchItemException; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.behaviours.AutoEquipMethods; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; + +public class UnequipAllAction implements ModAction { + private static Logger logger = Logger.getLogger(UnequipAllAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public UnequipAllAction() { + logger.log(Level.WARNING, "UnequipAllAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Unequip all armour", + "unequipping", + new int[0] + //new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + try { + if(performer instanceof Player && object != null && object.getParentOrNull() != null && object.getParent().isBodyPart() && object.getParent().getOwnerId() == performer.getWurmId()) { + return Arrays.asList(actionEntry); + } + } catch (NoSuchItemException e) { + e.printStackTrace(); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + if(performer instanceof Player){ + try { + Player player = (Player) performer; + if (target.getParent() == null){ + player.getCommunicator().sendSafeServerMessage("You cannot unequip an item that isn't equipped."); + return true; + } + if (target.getParent().getOwnerId() != player.getWurmId()){ + player.getCommunicator().sendSafeServerMessage("You cannot unequip an item that you do not own."); + return true; + } + for(Item equip : player.getBody().getAllItems()){ + if(equip.isArmour()){ + AutoEquipMethods.unequip(equip, player); + } + } + } catch (NoSuchItemException e1) { + e1.printStackTrace(); + } + }else{ + logger.info("Somehow a non-player activated an Affinity Orb..."); + } + return true; + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/VillageTeleportAction.java b/src/main/java/mod/sin/actions/VillageTeleportAction.java new file mode 100644 index 0000000..6af0a93 --- /dev/null +++ b/src/main/java/mod/sin/actions/VillageTeleportAction.java @@ -0,0 +1,122 @@ +package mod.sin.actions; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.players.Player; + +public class VillageTeleportAction implements ModAction { + private static Logger logger = Logger.getLogger(VillageTeleportAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public VillageTeleportAction() { + logger.log(Level.WARNING, "VillageTeleportAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Village Teleport", + "teleporting", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && (object.getTemplateId() == ItemList.bodyBody || object.getTemplateId() == ItemList.bodyHand) && !Servers.localServer.PVPSERVER && performer.getCitizenVillage() != null) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(Servers.localServer.PVPSERVER){ + performer.getCommunicator().sendNormalServerMessage("You cannot use Village Teleport on a PvP server."); + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You prepare to transport yourself to another location."); + act.setTimeLeft(600); + performer.sendActionControl("Teleporting", true, act.getTimeLeft()); + }else if(performer.isFighting()){ + performer.getCommunicator().sendAlertServerMessage("Your teleport was interrupted by entering combat."); + return true; + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + Player player = (Player) performer; + if(player.getCitizenVillage() != null){ + act.stop(false); + int tilex = player.getCitizenVillage().getTokenX()*4; + int tiley = player.getCitizenVillage().getTokenY()*4; + player.setTeleportPoints(tilex+2.0f, tiley+2.0f, 0, 0); + if(player.startTeleporting()){ + player.getCommunicator().sendNormalServerMessage("You feel a slight tingle in your spine."); + player.getCommunicator().sendTeleport(false); + } + } + return true; + } + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/AffinityOrbAction.java b/src/main/java/mod/sin/actions/items/AffinityOrbAction.java new file mode 100644 index 0000000..5351259 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/AffinityOrbAction.java @@ -0,0 +1,129 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.Affinities; +import com.wurmonline.server.skills.Affinity; +import com.wurmonline.server.skills.SkillSystem; + +import mod.sin.items.AffinityOrb; + +public class AffinityOrbAction implements ModAction { + private static Logger logger = Logger.getLogger(AffinityOrbAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public AffinityOrbAction() { + logger.log(Level.WARNING, "AffinityOrbAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Gain affinity", + "infusing", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && object.getTemplateId() == AffinityOrb.templateId) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + if(performer instanceof Player){ + Player player = (Player) performer; + if (target.getTemplate().getTemplateId() != AffinityOrb.templateId){ + player.getCommunicator().sendSafeServerMessage("You must use an Affinity Orb to be infused."); + return true; + } + int skillNum = SkillSystem.getRandomSkillNum(); + Affinity[] affs = Affinities.getAffinities(player.getWurmId()); + boolean found = false; + while (!found) { + boolean hasAffinity = false; + for (Affinity affinity : affs) { + if (affinity.getSkillNumber() != skillNum) continue; + hasAffinity = true; + if (affinity.getNumber() >= 5) break; + Affinities.setAffinity(player.getWurmId(), skillNum, affinity.getNumber() + 1, false); + String skillString = SkillSystem.getNameFor(skillNum); + found = true; + Items.destroyItem(target.getWurmId()); + player.getCommunicator().sendSafeServerMessage("Vynora infuses you with an affinity for " + skillString + "!"); + break; + } + if (!found && !hasAffinity) { + String skillString = SkillSystem.getNameFor(skillNum); + Affinities.setAffinity(player.getWurmId(), skillNum, 1, false); + Items.destroyItem(target.getWurmId()); + player.getCommunicator().sendSafeServerMessage("Vynora infuses you with an affinity for " + skillString + "!"); + found = true; + } + skillNum = SkillSystem.getRandomSkillNum(); + } + }else{ + logger.info("Somehow a non-player activated an Affinity Orb..."); + } + return true; + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/ArenaCacheOpenAction.java b/src/main/java/mod/sin/actions/items/ArenaCacheOpenAction.java new file mode 100644 index 0000000..ce7c40b --- /dev/null +++ b/src/main/java/mod/sin/actions/items/ArenaCacheOpenAction.java @@ -0,0 +1,124 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; + +import mod.sin.items.ArenaCache; +import mod.sin.wyvern.arena.SupplyDepots; + +public class ArenaCacheOpenAction implements ModAction { + private static Logger logger = Logger.getLogger(ArenaCacheOpenAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public ArenaCacheOpenAction() { + logger.log(Level.WARNING, "ArenaCacheOpenAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Open cache", + "opening", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && object.getTemplateId() == ArenaCache.templateId) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(target.getTemplate().getTemplateId() != ArenaCache.templateId){ + performer.getCommunicator().sendNormalServerMessage("That is not a cache."); + return true; + } + if(target.getLastOwnerId() != performer.getWurmId() && target.getOwnerId() != performer.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You must own the "+target.getName()+" to open it."); + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to open a "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " begins opening "+performer.getHisHerItsString()+" "+target.getName()+".", performer, 5); + act.setTimeLeft(50); + performer.sendActionControl("Opening", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + performer.getCommunicator().sendNormalServerMessage("You open your "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " opens "+performer.getHisHerItsString()+" "+target.getName()+".", performer, 5); + logger.info("Player "+performer.getName()+" opened arena cache."); + SupplyDepots.giveCacheReward(performer); + Items.destroyItem(target.getWurmId()); + return true; + } + }else{ + logger.info("Somehow a non-player activated a Treasure Box..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/ArrowPackUnpackAction.java b/src/main/java/mod/sin/actions/items/ArrowPackUnpackAction.java new file mode 100644 index 0000000..c3c2396 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/ArrowPackUnpackAction.java @@ -0,0 +1,164 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemSpellEffects; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.spells.SpellEffect; + +import mod.sin.items.ArrowPackHunting; +import mod.sin.items.ArrowPackWar; + +public class ArrowPackUnpackAction implements ModAction { + private static Logger logger = Logger.getLogger(ArrowPackUnpackAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public ArrowPackUnpackAction() { + logger.log(Level.WARNING, "ArrowPackUnpackAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Unpack arrows", + "unpacking", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && (object.getTemplateId() == ArrowPackHunting.templateId || object.getTemplateId() == ArrowPackWar.templateId)) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(target.getTemplate().getTemplateId() != ArrowPackHunting.templateId && target.getTemplate().getTemplateId() != ArrowPackWar.templateId){ + performer.getCommunicator().sendNormalServerMessage("That is not an arrow pack."); + return true; + } + if(target.getLastOwnerId() != performer.getWurmId() && target.getOwnerId() != performer.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You must own the arrow pack to unpack it."); + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to unpack your arrows."); + Server.getInstance().broadCastAction(performer.getName() + " begins unpacking "+performer.getHisHerItsString()+" arrows.", performer, 5); + act.setTimeLeft(50); + performer.sendActionControl("Unpacking", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + int arrowTemplate = ItemList.arrowHunting; + if(target.getTemplate().getTemplateId() == ArrowPackWar.templateId){ + arrowTemplate = ItemList.arrowWar; + } + float quality = target.getCurrentQualityLevel(); + if(target.getRarity() > 0){ + quality = Math.min(100f, target.getCurrentQualityLevel()+target.getRarity()); + } + HashMap spellEffects = new HashMap(); + ItemSpellEffects effs = target.getSpellEffects(); + if(effs != null){ + for(SpellEffect eff : effs.getEffects()){ + if(eff.getPower() > 0){ + spellEffects.put(eff.type, eff.getPower()); + } + } + } + Item quiver = ItemFactory.createItem(ItemList.quiver, quality, performer.getName()); + performer.getInventory().insertItem(quiver, true); + Item arrow; + int i = 0; + while(i < 40){ + arrow = ItemFactory.createItem(arrowTemplate, quality, performer.getName()); + arrow.setRarity(target.getRarity()); + if(!spellEffects.isEmpty()){ + for(byte b : spellEffects.keySet()){ + ItemSpellEffects arrowEffs = arrow.getSpellEffects(); + if (arrowEffs == null) { + arrowEffs = new ItemSpellEffects(arrow.getWurmId()); + } + SpellEffect arrowEff = new SpellEffect(arrow.getWurmId(), b, spellEffects.get(b), 20000000); + arrowEffs.addSpellEffect(arrowEff); + } + } + quiver.insertItem(arrow); + i++; + } + performer.getCommunicator().sendNormalServerMessage("You unpack your arrows into a usable quiver."); + Server.getInstance().broadCastAction(performer.getName() + " unpacks "+performer.getHisHerItsString()+" arrows into a quiver.", performer, 5); + Items.destroyItem(target.getWurmId()); + return true; + } + }else{ + logger.info("Somehow a non-player activated a Arrow Pack Unpack..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/ChaosCrystalInfuseAction.java b/src/main/java/mod/sin/actions/items/ChaosCrystalInfuseAction.java new file mode 100644 index 0000000..3eb0d9c --- /dev/null +++ b/src/main/java/mod/sin/actions/items/ChaosCrystalInfuseAction.java @@ -0,0 +1,167 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.behaviours.Actions; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.items.WurmColor; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.SkillList; + +import mod.sin.items.ChaosCrystal; +import mod.sin.wyvern.Crystals; + +public class ChaosCrystalInfuseAction implements ModAction { + private static Logger logger = Logger.getLogger(ChaosCrystalInfuseAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public ChaosCrystalInfuseAction() { + logger.log(Level.WARNING, "ChaosCrystalInfuseAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Infuse", + "infusing", + new int[]{ Actions.ACTION_TYPE_NOMOVE } + //new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + if(performer instanceof Player && source != null && object != null && source.getTemplateId() == ChaosCrystal.templateId && object.isRepairable()){ + return Arrays.asList(actionEntry); + } + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // With activated object + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(source.getTemplate().getTemplateId() != ChaosCrystal.templateId){ + performer.getCommunicator().sendNormalServerMessage("You must use a chaos crystal to infuse an item."); + return true; + } + if(!target.isRepairable()){ + performer.getCommunicator().sendNormalServerMessage("You cannot infuse that item."); + return true; + } + if(Crystals.shouldCancelInfusion(performer, source, target)){ + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to infuse the "+target.getName()+ " with the "+source.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " begins infusing with a "+source.getName()+".", performer, 5); + act.setTimeLeft(300); + performer.sendActionControl("Infusing", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + double diff = Crystals.getInfusionDifficulty(performer, source, target); + double power = performer.getSkills().getSkill(SkillList.ARCHAEOLOGY).skillCheck(diff, source, 0d, false, 1); + if(power > 90){ + performer.getCommunicator().sendNormalServerMessage("You handle the crystals expertly and infuse the "+target.getName()+ ", increasing its rarity!"); + target.setRarity(source.getRarity()); + Items.destroyItem(source.getWurmId()); + }else if(power > 60){ + if(target.isMetal() && Server.rand.nextBoolean()){ + performer.getCommunicator().sendNormalServerMessage("You carefully infuse the metal "+target.getName()+ ", changing its material!"); + byte[] mats = {Materials.MATERIAL_ADAMANTINE, Materials.MATERIAL_BRASS, Materials.MATERIAL_BRONZE, Materials.MATERIAL_COPPER, + Materials.MATERIAL_GLIMMERSTEEL, Materials.MATERIAL_GOLD, Materials.MATERIAL_IRON, Materials.MATERIAL_IRON, Materials.MATERIAL_LEAD, + Materials.MATERIAL_SERYLL, Materials.MATERIAL_SILVER, Materials.MATERIAL_STEEL, Materials.MATERIAL_TIN, Materials.MATERIAL_ZINC}; + target.setMaterial(mats[Server.rand.nextInt(mats.length)]); + }else if(target.isWood() && Server.rand.nextBoolean()){ + performer.getCommunicator().sendNormalServerMessage("You carefully infuse the wooden "+target.getName()+ ", changing its material!"); + byte[] mats = {Materials.MATERIAL_WOOD_APPLE, Materials.MATERIAL_WOOD_BIRCH, Materials.MATERIAL_WOOD_BLUEBERRY, Materials.MATERIAL_WOOD_CAMELLIA, + Materials.MATERIAL_WOOD_CEDAR, Materials.MATERIAL_WOOD_CHERRY, Materials.MATERIAL_WOOD_CHESTNUT, Materials.MATERIAL_WOOD_FIR, + Materials.MATERIAL_WOOD_GRAPE, Materials.MATERIAL_WOOD_HAZELNUT, Materials.MATERIAL_WOOD_IVY, Materials.MATERIAL_WOOD_LAVENDER, + Materials.MATERIAL_WOOD_LEMON, Materials.MATERIAL_WOOD_LINDEN, Materials.MATERIAL_WOOD_LINGONBERRY, Materials.MATERIAL_WOOD_MAPLE, + Materials.MATERIAL_WOOD_OAK, Materials.MATERIAL_WOOD_OLEANDER, Materials.MATERIAL_WOOD_OLIVE, Materials.MATERIAL_WOOD_ORANGE, + Materials.MATERIAL_WOOD_PINE, Materials.MATERIAL_WOOD_RASPBERRY, Materials.MATERIAL_WOOD_ROSE, Materials.MATERIAL_WOOD_THORN, + Materials.MATERIAL_WOOD_WALNUT, Materials.MATERIAL_WOOD_WILLOW}; + target.setMaterial(mats[Server.rand.nextInt(mats.length)]); + }else{ + performer.getCommunicator().sendNormalServerMessage("You carefully infuse the "+target.getName()+ ", changing its color."); + target.setColor(WurmColor.createColor(Server.rand.nextInt(255), Server.rand.nextInt(255), Server.rand.nextInt(255))); + } + Items.destroyItem(source.getWurmId()); + }else if(power > 30){ + performer.getCommunicator().sendNormalServerMessage("You safely infuse the "+target.getName()+ ", chaotically changing it its weight."); + target.setWeight((int) (target.getWeightGrams()*Server.rand.nextFloat()*2f), false); + Items.destroyItem(source.getWurmId()); + }else if(power > 0){ + performer.getCommunicator().sendNormalServerMessage("You barely manage to infuse the "+target.getName()+ ", chaotically changing its quality."); + target.setQualityLevel(Server.rand.nextFloat()*100f); + Items.destroyItem(source.getWurmId()); + }else if(power > -20){ + performer.getCommunicator().sendNormalServerMessage("You fail to infuse the "+target.getName()+ ", damaging to the "+source.getName()+" in the process."); + source.setDamage((float) (source.getDamage()-(power))); + }else if(power > -40){ + performer.getCommunicator().sendNormalServerMessage("You horribly fail to infuse the "+target.getName()+ ", destroying the "+source.getName()+" and heavily damaging the "+target.getName()+"."); + target.setDamage((float) (target.getDamage()-(power))); + Items.destroyItem(source.getWurmId()); + }else{ + if(target.getMaterial() == Materials.MATERIAL_SERYLL){ + performer.getCommunicator().sendNormalServerMessage("The infusion fails catastrophically, destroying the "+source.getName()+"! However, the "+target.getName()+"'s material prevents its utter destruction."); + target.setDamage((float) (target.getDamage()-power)); + Items.destroyItem(source.getWurmId()); + }else{ + performer.getCommunicator().sendNormalServerMessage("The infusion fails catastrophically, destroying the "+source.getName()+" and "+target.getName()+"!"); + Items.destroyItem(source.getWurmId()); + Items.destroyItem(target.getWurmId()); + } + } + return true; + } + }else{ + logger.info("Somehow a non-player activated a custom item ("+source.getTemplateId()+")..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/CrystalCombineAction.java b/src/main/java/mod/sin/actions/items/CrystalCombineAction.java new file mode 100644 index 0000000..d9b1ce6 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/CrystalCombineAction.java @@ -0,0 +1,137 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.behaviours.Actions; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.Skill; +import com.wurmonline.server.skills.SkillList; + +import mod.sin.wyvern.Crystals; + +public class CrystalCombineAction implements ModAction { + private static Logger logger = Logger.getLogger(CrystalCombineAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public CrystalCombineAction() { + logger.log(Level.WARNING, "CrystalCombineAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Combine", + "combining", + new int[]{ Actions.ACTION_TYPE_NOMOVE } + //new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + if(performer instanceof Player && source != null && object != null && Crystals.isCrystal(source) && Crystals.isCrystal(object) && source != object && source.getTemplateId() == object.getTemplateId()){ + return Arrays.asList(actionEntry); + } + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // With activated object + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(Crystals.shouldCancelCombine(performer, source, target)){ + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to combine the crystals together."); + Server.getInstance().broadCastAction(performer.getName() + " begins combining crystals.", performer, 5); + Skill artifacts = performer.getSkills().getSkill(SkillList.ARCHAEOLOGY); + int time = Actions.getSlowActionTime(performer, artifacts, source, 0d); + act.setTimeLeft(time); + performer.sendActionControl("Combining", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + double diff = (source.getCurrentQualityLevel()+target.getCurrentQualityLevel())*0.5d; + diff += source.getRarity()*(Servers.localServer.PVPSERVER ? 25 : 15); + diff -= performer.getSoulDepth().getKnowledge(); + if(Servers.localServer.PVPSERVER){ // Added difficulty to account for PvP epic curve: + diff *= 1.4f; + } + double power = performer.getSkills().getSkill(SkillList.ARCHAEOLOGY).skillCheck(diff, source, 0d, false, 1); + if(power > 0){ + performer.getCommunicator().sendNormalServerMessage("You successfully combine the crystals!"); + Server.getInstance().broadCastAction(performer.getName() + " successfully combines the crystals!", performer, 5); + if(source.getCurrentQualityLevel() + target.getCurrentQualityLevel() > 100f){ + float newQuality = (source.getCurrentQualityLevel() + target.getCurrentQualityLevel()) - 100f; + performer.getCommunicator().sendNormalServerMessage("The crystals combine and change, creating a more powerful component."); + Items.destroyItem(source.getWurmId()); + target.setQualityLevel(newQuality); + target.setDamage(0); + target.setRarity((byte) (target.getRarity()+1)); + }else{ + performer.getCommunicator().sendNormalServerMessage("The crystals combine together and reinforce."); + target.setQualityLevel(source.getCurrentQualityLevel() + target.getCurrentQualityLevel()); + target.setDamage(0); + Items.destroyItem(source.getWurmId()); + } + return true; + }else{ + performer.getCommunicator().sendNormalServerMessage("You fail to combine the crystals, damaging them both."); + float dam1 = (float) (Server.rand.nextFloat()*power*0.2f); + float dam2 = (float) (Server.rand.nextFloat()*power*0.2f); + source.setDamage((float) (source.getDamage()-dam1)); + target.setDamage((float) (target.getDamage()-dam2)); + } + return true; + } + }else{ + logger.info("Somehow a non-player activated a custom item ("+source.getTemplateId()+")..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/DepthDrillAction.java b/src/main/java/mod/sin/actions/items/DepthDrillAction.java new file mode 100644 index 0000000..505b4f5 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/DepthDrillAction.java @@ -0,0 +1,179 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.behaviours.Actions; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.NoSuchSkillException; +import com.wurmonline.server.skills.SkillList; + +import mod.sin.items.DepthDrill; + +public class DepthDrillAction implements ModAction { + private static Logger logger = Logger.getLogger(DepthDrillAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public DepthDrillAction() { + logger.log(Level.WARNING, "DepthDrillAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Drill", + "drilling", + new int[] { Actions.ACTION_TYPE_NOMOVE } + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item object, int tilex, int tiley, boolean onSurface, boolean corner, int tile) + { + if(performer instanceof Player && object != null && object.getTemplateId() == DepthDrill.templateId){ + return Arrays.asList(actionEntry); + } + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // With activated object + @Override + public boolean action(Action action, Creature performer, Item source, int tilex, int tiley, boolean onSurface, boolean corner, int tile, short num, float counter) + { + try{ + if(performer instanceof Player){ + if (source.getTemplate().getTemplateId() != DepthDrill.templateId){ + performer.getCommunicator().sendNormalServerMessage("You must use a depth drill to drill."); + return true; + } + if (!performer.isWithinDistanceTo(tilex * 4, tiley * 4, performer.getPositionZ(), 4)) { + performer.getCommunicator().sendNormalServerMessage("You are too far away to drill."); + action.stop(true); + return true; + } + + int surfaceHeight = Tiles.decodeHeight(Server.surfaceMesh.getTile(tilex, tiley)); + int rockHeight = Tiles.decodeHeight(Server.rockMesh.getTile(tilex, tiley)); + int delta = surfaceHeight - rockHeight; + if (counter == 1.0f) { + if (delta == 0) { + performer.getCommunicator().sendNormalServerMessage("The ground here is too hard and the drill makes no progress."); + action.stop(false); + return true; + } + performer.getCommunicator().sendNormalServerMessage("You start to drill into the ground."); + Server.getInstance().broadCastAction(performer.getName() + " starts to drill into the ground.", performer, 5); + action.setTimeLeft(Actions.getSlowActionTime(performer, performer.getSkills().getSkill(SkillList.DIGGING), source, 1)); + performer.sendActionControl("Drilling", true, action.getTimeLeft()); + } else if (counter * 10.0f > performer.getCurrentAction().getTimeLeft()) { + performer.getCommunicator().sendNormalServerMessage("The rock here is " + delta + " deep."); + performer.getSkills().getSkill(SkillList.DIGGING).skillCheck(10d, 0d, false, 1); + performer.getSkills().getSkill(SkillList.PROSPECT).skillCheck(10d, 0d, false, 1); + sendOres(performer, tilex, tiley); + return true; + } + }else{ + logger.info("Somehow a non-player activated a "+source.getTemplate().getName()+"."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + private void sendOres(Creature performer, int x, int y) throws NoSuchSkillException { + double prospecting = performer.getSkills().getSkill(SkillList.PROSPECT).getRealKnowledge(); + if (prospecting < 30) return; + double mining = performer.getSkills().getSkill(SkillList.MINING).getRealKnowledge(); + + Set ores = new HashSet<>(); + int distance = (int) Math.floor(Math.pow(prospecting+mining, 0.38D)); + + for (int dx = distance*-1; dx < distance; dx++) { + for (int dy = distance*-1; dy < distance; dy++) { + int type = Tiles.decodeType(Server.caveMesh.getTile(x + dx, y + dy)) & 0xFF; + + if (type == Tiles.TILE_TYPE_CAVE_WALL_SLATE && prospecting > 40) { + ores.add("slate"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_MARBLE && prospecting > 40) { + ores.add("marble"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_ORE_GOLD && prospecting > 60) { + ores.add("gold"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_ORE_SILVER && prospecting > 50) { + ores.add("silver"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_ORE_ADAMANTINE && prospecting > 70) { + ores.add("adamantine"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_ORE_GLIMMERSTEEL && prospecting > 80) { + ores.add("glimmersteel"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_ORE_IRON) { + ores.add("iron"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_ORE_COPPER) { + ores.add("copper"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_ORE_LEAD) { + ores.add("lead"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_ORE_ZINC) { + ores.add("zinc"); + } else if (type == Tiles.TILE_TYPE_CAVE_WALL_ORE_TIN) { + ores.add("tin"); + } + } + } + logger.info("Player "+performer.getName()+" uses depth drill at "+x+", "+y+" and prospects "+ores.toString()+" in the ground."); + + Iterator it = ores.iterator(); + if (ores.size() == 1) { + performer.getCommunicator().sendNormalServerMessage("You find traces of " + it.next() + " in the dirt."); + } else if (ores.size() > 1) { + String s = "You find traces of "; + for (int i = 0; i < ores.size() - 1; i++) { + if (i == ores.size() - 2) { + s += it.next(); + } else { + s += it.next() + ", "; + } + } + s += " and " + it.next() + " in the dirt."; + + performer.getCommunicator().sendNormalServerMessage(s); + } + } + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/DisintegrationRodAction.java b/src/main/java/mod/sin/actions/items/DisintegrationRodAction.java new file mode 100644 index 0000000..5f15efb --- /dev/null +++ b/src/main/java/mod/sin/actions/items/DisintegrationRodAction.java @@ -0,0 +1,129 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Items; +import com.wurmonline.server.Players; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.behaviours.Actions; +import com.wurmonline.server.behaviours.TileRockBehaviour; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; + +import mod.sin.items.DisintegrationRod; + +public class DisintegrationRodAction implements ModAction { + private static Logger logger = Logger.getLogger(DisintegrationRodAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public DisintegrationRodAction() { + logger.log(Level.WARNING, "DisintegrationRodAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Use", + "disintegrating", + new int[] { // {1, 4, 25, 9, 18, 21, 41, 43, 5, 49, 50} - Mining + Actions.ACTION_TYPE_SHOW_ON_SELECT_BAR, + Actions.ACTION_TYPE_IGNORERANGE + } + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item subject, int tilex, int tiley, boolean onSurface, int tile, int dir) + { + if(performer instanceof Player && subject != null && subject.getTemplateId() == DisintegrationRod.templateId && Tiles.isSolidCave(Tiles.decodeType(tile))){ + return Arrays.asList(actionEntry); + } + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // With activated object + @Override + public boolean action(Action act, Creature performer, Item source, int tilex, int tiley, boolean onSurface, int heightOffset, int tile, short action, float counter) + { + try{ + if(performer instanceof Player){ + int newTile = Server.caveMesh.getTile(tilex, tiley); + if(source.getTemplate().getTemplateId() != DisintegrationRod.templateId){ + performer.getCommunicator().sendSafeServerMessage("You must use a Disintegration Rod to do this."); + return true; + } + byte type = Tiles.decodeType(newTile); + if (Tiles.isSolidCave(type)) { + int resource = Server.getCaveResource(tilex, tiley); + int dir = (int)(act.getTarget() >> 48) & 255; + boolean destroyRod = true; + + // Don't allow disintegration of reinforced caves + if ((type & 0xFF) == Tiles.TILE_TYPE_CAVE_WALL_REINFORCED) { + destroyRod = false; + performer.getCommunicator().sendSafeServerMessage("The reinforced wall is too strong and doesn't get affected by the rod."); + } else if (resource <= 1000 && TileRockBehaviour.createInsideTunnel(tilex, tiley, newTile, performer, 145, dir, true, act)) { + //Server.caveMesh.setTile(tilex, tiley, Tiles.encode(Tiles.decodeHeight(tile), Tiles.Tile.TILE_CAVE.id, Tiles.decodeData(tile))); + Players.getInstance().sendChangedTile(tilex, tiley, false, false); + performer.getCommunicator().sendSafeServerMessage("You use the " + source.getTemplate().getName()+" on the "+Tiles.getTile(Tiles.decodeType(newTile)).tiledesc.toLowerCase()+" and it breaks!"); + } else if ((type & 0xFF) != Tiles.TILE_TYPE_CAVE_WALL && resource > 1000){ + Server.setCaveResource(tilex, tiley, resource-1000); + Players.getInstance().sendChangedTile(tilex, tiley, false, false); + performer.getCommunicator().sendSafeServerMessage("You use the " + source.getTemplate().getName()+" on the "+Tiles.getTile(Tiles.decodeType(newTile)).tiledesc.toLowerCase()+", but it is only weakened!"); + } else if ((type & 0xFF) == Tiles.TILE_TYPE_CAVE_WALL && TileRockBehaviour.createInsideTunnel(tilex, tiley, newTile, performer, 145, dir, true, act)) { + Players.getInstance().sendChangedTile(tilex, tiley, false, false); + performer.getCommunicator().sendSafeServerMessage("The rock is powerless against the "+source.getTemplate().getName()+"!"); + } else if (!TileRockBehaviour.createInsideTunnel(tilex, tiley, newTile, performer, 145, dir, true, act)) { + performer.getCommunicator().sendSafeServerMessage("The wall is not stable enough."); + destroyRod = false; + } // else if + if (destroyRod) { + Items.destroyItem(source.getWurmId()); + } + }else{ + logger.info("Disintegration rod attempted to be used on non-solid cave at "+tilex+", "+tiley); + } + } else { + logger.info("Somehow a non-player activated a "+source.getTemplate().getName()+"."); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return true; + } // catch + } + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/EnchantOrbAction.java b/src/main/java/mod/sin/actions/items/EnchantOrbAction.java new file mode 100644 index 0000000..f6df48f --- /dev/null +++ b/src/main/java/mod/sin/actions/items/EnchantOrbAction.java @@ -0,0 +1,135 @@ +package mod.sin.actions.items; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modloader.ReflectionUtil; +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemSpellEffects; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.Skill; +import com.wurmonline.server.spells.Spell; +import com.wurmonline.server.spells.SpellEffect; +import com.wurmonline.server.spells.Spells; + +import mod.sin.items.EnchantOrb; + +public class EnchantOrbAction implements ModAction { + private static Logger logger = Logger.getLogger(EnchantOrbAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public EnchantOrbAction() { + logger.log(Level.WARNING, "EnchantOrbAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Transfer enchant", + "transferring", + new int[0] + //new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + if(performer instanceof Player && source != null && object != null && source.getTemplateId() == EnchantOrb.templateId && source != object){ + return Arrays.asList(actionEntry); + } + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // With activated object + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + if(performer instanceof Player){ + Player player = (Player) performer; + if(source.getTemplate().getTemplateId() != EnchantOrb.templateId){ + player.getCommunicator().sendNormalServerMessage("You must use an Enchant Orb to transfer enchants."); + return true; + } + if(source.getWurmId() == target.getWurmId()){ + player.getCommunicator().sendNormalServerMessage("You cannot enchant the orb with itself!"); + return true; + } + ItemSpellEffects effs = source.getSpellEffects(); + if(effs == null || effs.getEffects().length == 0){ + player.getCommunicator().sendNormalServerMessage("The "+source.getTemplate().getName()+" has no enchants."); + return true; + } + if(!Spell.mayBeEnchanted(target)){ + player.getCommunicator().sendNormalServerMessage("The "+target.getTemplate().getName()+" may not be enchanted."); + } + ItemSpellEffects teffs = target.getSpellEffects(); + if(teffs == null){ + teffs = new ItemSpellEffects(target.getWurmId()); + } + for(SpellEffect eff : effs.getEffects()){ + Spell spell = Spells.getEnchantment(eff.type); + boolean canEnchant = Spell.mayBeEnchanted(target); + byte type = eff.type; + if(spell == null){ + logger.info("Error: Enchant for "+eff.type+" doesn't exist."); + continue; + } + if(canEnchant){ + try { + Method m = spell.getClass().getDeclaredMethod("precondition", Skill.class, Creature.class, Item.class); + canEnchant = ReflectionUtil.callPrivateMethod(spell, m, player.getChannelingSkill(), performer, target); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) { + e.printStackTrace(); + } + } + if(canEnchant){ + SpellEffect newEff = new SpellEffect(target.getWurmId(), type, eff.getPower(), 20000000); + teffs.addSpellEffect(newEff); + Items.destroyItem(source.getWurmId()); + player.getCommunicator().sendSafeServerMessage("The "+eff.getName()+" transfers to the "+target.getTemplate().getName()+"."); + } + } + }else{ + logger.info("Somehow a non-player activated an Enchant Orb..."); + } + return true; + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/EnchantersCrystalInfuseAction.java b/src/main/java/mod/sin/actions/items/EnchantersCrystalInfuseAction.java new file mode 100644 index 0000000..864e4a2 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/EnchantersCrystalInfuseAction.java @@ -0,0 +1,187 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.behaviours.Actions; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemSpellEffects; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.SkillList; +import com.wurmonline.server.spells.SpellEffect; +import com.wurmonline.shared.constants.Enchants; + +import mod.sin.items.EnchantersCrystal; +import mod.sin.wyvern.Crystals; + +public class EnchantersCrystalInfuseAction implements ModAction { + private static Logger logger = Logger.getLogger(EnchantersCrystalInfuseAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public EnchantersCrystalInfuseAction() { + logger.log(Level.WARNING, "EnchantersCrystalInfuseAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Infuse", + "infusing", + new int[]{ Actions.ACTION_TYPE_NOMOVE } + //new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + if(performer instanceof Player && source != null && object != null && source.getTemplateId() == EnchantersCrystal.templateId && object.getTemplateId() != EnchantersCrystal.templateId){ + return Arrays.asList(actionEntry); + } + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // With activated object + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(source.getTemplate().getTemplateId() != EnchantersCrystal.templateId){ + performer.getCommunicator().sendNormalServerMessage("You must use an enchanters crystal to infuse an item."); + return true; + } + if(Crystals.shouldCancelEnchantersInfusion(performer, target)){ + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to infuse the "+target.getName()+ " with the "+source.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " begins infusing with a "+source.getName()+".", performer, 5); + act.setTimeLeft(300); + performer.sendActionControl("Infusing", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + double diff = Crystals.getEnchantersInfusionDifficulty(performer, source, target); + double power = -100; + int i = source.getRarity(); + while(i >= 0){ + power = Math.max(power, performer.getSkills().getSkill(SkillList.ARCHAEOLOGY).skillCheck(diff, source, 0d, false, 1)); + i--; + } + ItemSpellEffects effs = target.getSpellEffects(); + if(power > 90){ + byte ench = Crystals.getNewRandomEnchant(target); + if(ench != -10){ + performer.getCommunicator().sendNormalServerMessage("You handle the crystals expertly and infuse the "+target.getName()+ ", adding a new enchant!"); + SpellEffect eff = new SpellEffect(target.getWurmId(), ench, (float)power*Server.rand.nextFloat(), 20000000); + effs.addSpellEffect(eff); + Items.destroyItem(source.getWurmId()); + }else{ + logger.info("Failed to find a valid enchant to add to item "+target.getName()+" for player "+performer.getName()+"!"); + performer.getCommunicator().sendNormalServerMessage("Nothing happens!"); + } + }else if(power > 75){ + performer.getCommunicator().sendNormalServerMessage("You very carefully infuse the metal "+target.getName()+ ", increasing its magical properties!"); + for(SpellEffect eff : effs.getEffects()){ + eff.setPower(eff.getPower()+(eff.getPower()*Server.rand.nextFloat()*0.2f)); + } + Items.destroyItem(source.getWurmId()); + }else if(power > 60){ + performer.getCommunicator().sendNormalServerMessage("You carefully infuse the "+target.getName()+ ", changing one of its magical properties!"); + SpellEffect oldEff = effs.getEffects()[Server.rand.nextInt(effs.getEffects().length)]; + float oldPower = oldEff.getPower(); + if(oldEff.type == Enchants.BUFF_BLOODTHIRST){ + oldPower *= 0.01f; + } + effs.removeSpellEffect(oldEff.type); + byte ench = Crystals.getNewRandomEnchant(target); + if(ench != -10){ + SpellEffect eff = new SpellEffect(target.getWurmId(), ench, oldPower, 20000000); + effs.addSpellEffect(eff); + }else{ + performer.getCommunicator().sendNormalServerMessage("However, something goes wrong and the "+target.getName()+ " instead loses the property!"); + } + Items.destroyItem(source.getWurmId()); + }else if(power > 40){ + performer.getCommunicator().sendNormalServerMessage("You manage to infuse the "+target.getName()+ ", destroying a magical property but increasing the rest."); + SpellEffect oldEff = effs.getEffects()[Server.rand.nextInt(effs.getEffects().length)]; + effs.removeSpellEffect(oldEff.type); + if(effs.getEffects().length >= 1){ + for(SpellEffect eff : effs.getEffects()){ + eff.setPower(eff.getPower()+(eff.getPower()*Server.rand.nextFloat()*0.2f)); + } + }else{ + performer.getCommunicator().sendNormalServerMessage("However, the "+target.getName()+ " does not have any other properties, and the effect is wasted!"); + } + Items.destroyItem(source.getWurmId()); + }else if(power > 0){ + performer.getCommunicator().sendNormalServerMessage("You barely manage to infuse the "+target.getName()+ ", shifting its magical properties."); + for(SpellEffect eff : effs.getEffects()){ + eff.setPower(eff.getPower()+((eff.getPower()*Server.rand.nextFloat()*0.4f) * (Server.rand.nextBoolean() ? 1 : -1))); + } + Items.destroyItem(source.getWurmId()); + }else if(power > -30){ + performer.getCommunicator().sendNormalServerMessage("You barely fail to infuse the "+target.getName()+ ", reducing the power of its magical properties."); + for(SpellEffect eff : effs.getEffects()){ + eff.setPower(eff.getPower()-(eff.getPower()*Server.rand.nextFloat()*0.2f)); + } + Items.destroyItem(source.getWurmId()); + }else if(power > -60){ + performer.getCommunicator().sendNormalServerMessage("You horribly fail to infuse the "+target.getName()+ ", removing one of its magical properties."); + SpellEffect oldEff = effs.getEffects()[Server.rand.nextInt(effs.getEffects().length)]; + effs.removeSpellEffect(oldEff.type); + Items.destroyItem(source.getWurmId()); + }else{ + performer.getCommunicator().sendNormalServerMessage("The infusion fails catastrophically, destroying all the magic on the "+target.getName()+"!"); + for(SpellEffect eff : effs.getEffects()){ + effs.removeSpellEffect(eff.type); + } + Items.destroyItem(source.getWurmId()); + } + return true; + } + }else{ + logger.info("Somehow a non-player activated a custom item ("+source.getTemplateId()+")..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/EternalReservoirCheckFuelAction.java b/src/main/java/mod/sin/actions/items/EternalReservoirCheckFuelAction.java new file mode 100644 index 0000000..6a0248c --- /dev/null +++ b/src/main/java/mod/sin/actions/items/EternalReservoirCheckFuelAction.java @@ -0,0 +1,123 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; + +import mod.sin.items.EternalReservoir; + +public class EternalReservoirCheckFuelAction implements ModAction { + private static Logger logger = Logger.getLogger(EternalReservoirCheckFuelAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public EternalReservoirCheckFuelAction() { + logger.log(Level.WARNING, "EternalReservoirFuelCheckAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Check fuel", + "checking", + new int[0] + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && object.getTemplateId() == EternalReservoir.templateId) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(target.getTemplateId() != EternalReservoir.templateId){ + performer.getCommunicator().sendNormalServerMessage("That is not an eternal reservoir."); + return true; + } + if(!performer.isWithinDistanceTo(target, 9)){ + performer.getCommunicator().sendNormalServerMessage("You are too far away to check the fuel."); + return true; + } + int fuel = target.getData1(); + if(fuel < 30){ + performer.getCommunicator().sendNormalServerMessage("The "+target.getName()+" has no souls, and is inactive."); + }else if(fuel < 1000){ + performer.getCommunicator().sendNormalServerMessage("The "+target.getName()+" is very low on souls."); + }else if(fuel < 5000){ + performer.getCommunicator().sendNormalServerMessage("The "+target.getName()+" has some souls, but yearns for more."); + }else if(fuel < 10000){ + performer.getCommunicator().sendNormalServerMessage("The "+target.getName()+" has a good amount of souls."); + }else if(fuel < 50000){ + performer.getCommunicator().sendNormalServerMessage("The "+target.getName()+" has plenty of souls."); + }else{ + performer.getCommunicator().sendNormalServerMessage("The "+target.getName()+" is absolutely flooded with souls, and will last a long time."); + } + return true; + }else{ + logger.info("Somehow a non-player activated a Eternal Reservoir..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/EternalReservoirRefuelAction.java b/src/main/java/mod/sin/actions/items/EternalReservoirRefuelAction.java new file mode 100644 index 0000000..08c5de3 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/EternalReservoirRefuelAction.java @@ -0,0 +1,130 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.behaviours.Actions; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.Skill; +import mod.sin.items.Soul; +import mod.sin.items.EternalReservoir; + +public class EternalReservoirRefuelAction implements ModAction { + private static Logger logger = Logger.getLogger(EternalReservoirRefuelAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public EternalReservoirRefuelAction() { + logger.log(Level.WARNING, "SoulForgeRefuelAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Feed soul", + "feeding", + new int[]{ + Actions.ACTION_TYPE_IGNORERANGE + } + + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + if(performer instanceof Player && source != null && object != null && source.getTemplateId() == Soul.templateId && object.getTemplateId() == EternalReservoir.templateId){ + return Arrays.asList(actionEntry); + } + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // With activated object + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + Player player = (Player) performer; + if(target.getTemplate().getTemplateId() != EternalReservoir.templateId){ + player.getCommunicator().sendNormalServerMessage("That is not an eternal reservoir."); + return true; + } + if(source.getTemplate().getTemplateId() != Soul.templateId){ + player.getCommunicator().sendNormalServerMessage("You can only use souls to refuel the eternal reservoir."); + return true; + } + if(!performer.isWithinDistanceTo(target, 5)){ + player.getCommunicator().sendNormalServerMessage("You are too far away to fuel the reservoir."); + return true; + } + Skill stealing = null; + Skill soulStrength = null; + int time = 100; + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to feed the "+source.getName()+" to the "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " begins to feed a "+source.getName()+" to the "+target.getName()+".", performer, 5); + stealing = performer.getStealSkill(); + time = Actions.getSlowActionTime(performer, stealing, source, 0d); + act.setTimeLeft(time); + performer.sendActionControl("Feeding", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + soulStrength = performer.getSoulStrength(); + double power = soulStrength.skillCheck(25f-(source.getCurrentQualityLevel()*0.2f), source, 0f, false, 1); + if(power > 0){ + target.setData1((int) (target.getData1()+power)); + performer.getCommunicator().sendNormalServerMessage("You feed the "+source.getName()+" to the "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " feeds a "+source.getName()+" to the "+target.getName()+".", performer, 5); + }else{ + performer.getCommunicator().sendNormalServerMessage("You fail to feed the "+source.getName()+" to the "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " fails to feed a "+source.getName()+" to the "+target.getName()+".", performer, 5); + } + Items.destroyItem(source.getWurmId()); + return true; + } + }else{ + logger.info("Somehow a non-player activated an Enchant Orb..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/FriyanTabletAction.java b/src/main/java/mod/sin/actions/items/FriyanTabletAction.java new file mode 100644 index 0000000..9bdcb68 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/FriyanTabletAction.java @@ -0,0 +1,127 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.behaviours.Actions; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; + +import mod.sin.items.FriyanTablet; + +public class FriyanTabletAction implements ModAction { + private static Logger logger = Logger.getLogger(FriyanTabletAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public FriyanTabletAction() { + logger.log(Level.WARNING, "FriyanTabletAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Read", + "reading", + new int[] { Actions.ACTION_TYPE_NOMOVE } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && object.getTemplateId() == FriyanTablet.templateId) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if (target.getTemplate().getTemplateId() != FriyanTablet.templateId){ + performer.getCommunicator().sendNormalServerMessage("You cannot read that."); + return true; + } + if (!performer.isWithinDistanceTo(target.getPosX(), target.getPosY(), performer.getPositionZ(), 4)) { + performer.getCommunicator().sendNormalServerMessage("You are too far away to read."); + act.stop(true); + return true; + } + if (counter == 1.0f) { + performer.getCommunicator().sendNormalServerMessage("You start to read the "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " begins reading the "+target.getName()+".", performer, 5); + act.setTimeLeft(200); + performer.sendActionControl("Reading", true, act.getTimeLeft()); + } else if (counter * 10.0f > performer.getCurrentAction().getTimeLeft()) { + if(performer.getDeity() != null && performer.getFaith() > 0){ + performer.modifyFaith(Math.max(0.1f, Server.rand.nextFloat()/2f)); + performer.getCommunicator().sendNormalServerMessage("You are enthralled by the knowledge of the Kaen scholar. You feel closer to god than ever!"); + Items.destroyItem(target.getWurmId()); + }else{ + performer.getCommunicator().sendNormalServerMessage("You don't seem to learn anything. You don't believe in the gods."); + } + return true; + } + }else{ + logger.info("Somehow a non-player activated a "+target.getTemplate().getName()+"."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/SealedMapAction.java b/src/main/java/mod/sin/actions/items/SealedMapAction.java new file mode 100644 index 0000000..8980606 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/SealedMapAction.java @@ -0,0 +1,126 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.pveplands.treasurehunting.Treasuremap; +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; + +import mod.sin.items.SealedMap; + +public class SealedMapAction implements ModAction { + private static Logger logger = Logger.getLogger(SealedMapAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public SealedMapAction() { + logger.log(Level.WARNING, "TreasureCacheOpenAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Unseal", + "unsealing", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && object.getTemplateId() == SealedMap.templateId) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(target.getTemplateId() != SealedMap.templateId){ + performer.getCommunicator().sendNormalServerMessage("That is not a sealed map."); + return true; + } + if(target.getLastOwnerId() != performer.getWurmId() && target.getOwnerId() != performer.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You must own the "+target.getName()+" to open it."); + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to unseal the "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " begins unseal "+performer.getHisHerItsString()+" "+target.getName()+".", performer, 5); + act.setTimeLeft(50); + performer.sendActionControl("Unsealing", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + performer.getCommunicator().sendNormalServerMessage("You unseal your "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " unseals "+performer.getHisHerItsString()+" "+target.getName()+".", performer, 5); + logger.info("Player "+performer.getName()+" unsealed "+target.getName()+" at quality "+target.getCurrentQualityLevel()+" and rarity "+target.getRarity()); + target.setData1(100); + Item map = Treasuremap.CreateTreasuremap(performer, target, null, null, true); + performer.getInventory().insertItem(map, true); + Items.destroyItem(target.getWurmId()); + return true; + } + }else{ + logger.info("Somehow a non-player activated a Treasure Box..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/SoulstealAction.java b/src/main/java/mod/sin/actions/items/SoulstealAction.java new file mode 100644 index 0000000..33daaa7 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/SoulstealAction.java @@ -0,0 +1,152 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.behaviours.Actions; +import com.wurmonline.server.behaviours.Methods; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTemplate; +import com.wurmonline.server.creatures.CreatureTemplateFactory; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.Skill; +import mod.sin.items.Soul; + +public class SoulstealAction implements ModAction { + private static Logger logger = Logger.getLogger(SoulstealAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public SoulstealAction() { + logger.log(Level.WARNING, "SoulstealAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Soulsteal", + "soulstealing", + new int[]{ + Actions.ACTION_TYPE_IGNORERANGE + } + + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + if(performer instanceof Player && source != null && object != null && source.getTemplateId() == ItemList.sacrificialKnife && object.getTemplateId() == ItemList.corpse){ + return Arrays.asList(actionEntry); + } + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // With activated object + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + Player player = (Player) performer; + if(source.getTemplate().getTemplateId() != ItemList.sacrificialKnife){ + player.getCommunicator().sendNormalServerMessage("You must use a sacrifical knife to steal souls."); + return true; + } + if(target.getTemplate().getTemplateId() != ItemList.corpse){ + player.getCommunicator().sendNormalServerMessage("You can only steal the soul from a corpse."); + return true; + } + if(target.getData1() == 1 && (target.getLastOwnerId() != performer.getWurmId()) && !Servers.isThisAPvpServer()) { + player.getCommunicator().sendNormalServerMessage(Action.NOT_ALLOWED_ACTION_ON_FREEDOM_MESSAGE); + return true; + } + if(target.isButchered()){ + player.getCommunicator().sendNormalServerMessage("The corpse has been butchered and there is no soul left."); + return true; + } + if (target.getTopParentOrNull() != performer.getInventory() && !Methods.isActionAllowed(performer, (short) 120, target)) { + player.getCommunicator().sendNormalServerMessage("You are not allowed to soulsteal that."); + return true; + } + if(!performer.isWithinDistanceTo(target, 5)){ + player.getCommunicator().sendNormalServerMessage("You are too far away to steal that soul."); + return true; + } + Skill stealing = null; + int time = 100; + CreatureTemplate template = null; + if(counter == 1.0f){ + template = CreatureTemplateFactory.getInstance().getTemplate(target.getData1()); + performer.getCommunicator().sendNormalServerMessage("You begin to steal the soul of the "+template.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " begins to steal the "+template.getName()+" soul.", performer, 5); + stealing = performer.getStealSkill(); + time = Actions.getStandardActionTime(performer, stealing, source, 0d); + act.setTimeLeft(time); + performer.sendActionControl("Soulstealing", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + template = CreatureTemplateFactory.getInstance().getTemplate(target.getData1()); + stealing = performer.getStealSkill(); + double power = stealing.skillCheck(40f-(template.getBaseCombatRating()*0.4f), source, 0f, false, 1); + if(power > 0){ + Item soul = ItemFactory.createItem(Soul.templateId, (float) power, performer.getName()); + soul.setName("Soul of "+template.getName()); + performer.getInventory().insertItem(soul, true); + performer.getCommunicator().sendNormalServerMessage("You obtain the soul of the "+template.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " obtains the soul of the "+template.getName()+".", performer, 5); + }else{ + performer.getCommunicator().sendNormalServerMessage("You fail to steal the soul of the "+template.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " fails to steal the soul of the "+template.getName()+".", performer, 5); + } + source.setDamage(source.getDamage()+(0.001f*source.getDamageModifier())); + Items.destroyItem(target.getWurmId()); + return true; + } + }else{ + logger.info("Somehow a non-player activated an Enchant Orb..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/SupplyDepotAction.java b/src/main/java/mod/sin/actions/items/SupplyDepotAction.java new file mode 100644 index 0000000..db85588 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/SupplyDepotAction.java @@ -0,0 +1,139 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.players.Player; + +import mod.sin.items.ArenaCache; +import mod.sin.items.ArenaSupplyDepot; +import mod.sin.wyvern.MiscChanges; +import mod.sin.wyvern.arena.SupplyDepots; + +public class SupplyDepotAction implements ModAction { + private static Logger logger = Logger.getLogger(SupplyDepotAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public SupplyDepotAction() { + logger.log(Level.WARNING, "SupplyDepotAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Capture depot", + "capturing", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && object.getTemplateId() == ArenaSupplyDepot.templateId) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(target.getTemplate().getTemplateId() != ArenaSupplyDepot.templateId){ + performer.getCommunicator().sendNormalServerMessage("That is not a supply depot."); + return true; + } + if(!performer.isWithinDistanceTo(target, 5)){ + performer.getCommunicator().sendNormalServerMessage("You must be closer to capture the depot."); + return true; + } + if(!Items.exists(target)){ + performer.getCommunicator().sendNormalServerMessage("The supply depot has already been captured."); + return true; + } + if(performer.getFightingSkill().getKnowledge() < 25f){ + performer.getCommunicator().sendNormalServerMessage("You must have at least 25 fighting skill to capture a depot."); + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to capture the depot."); + Server.getInstance().broadCastAction(performer.getName() + " begins capturing the depot.", performer, 50); + act.setTimeLeft(2400); + performer.sendActionControl("Capturing", true, act.getTimeLeft()); + SupplyDepots.maybeBroadcastOpen(performer); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + Item inv = performer.getInventory(); + Item cache = ItemFactory.createItem(ArenaCache.templateId, 90+(10*Server.rand.nextFloat()), ""); + inv.insertItem(cache, true); + performer.getCommunicator().sendSafeServerMessage("You have successfully captured the depot!"); + Server.getInstance().broadCastAction(performer.getName() + " successfully captures the depot!", performer, 50); + MiscChanges.sendImportantMessage(performer, performer.getName()+" has claimed an Arena depot!", 255, 128, 0); + SupplyDepots.removeSupplyDepot(target); + Items.destroyItem(target.getWurmId()); + return true; + } + }else{ + logger.info("Somehow a non-player activated a Arrow Pack Unpack..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/TreasureBoxAction.java b/src/main/java/mod/sin/actions/items/TreasureBoxAction.java new file mode 100644 index 0000000..e03eae9 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/TreasureBoxAction.java @@ -0,0 +1,142 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; + +import mod.sin.items.TreasureBox; +import mod.sin.wyvern.TreasureChests; + +public class TreasureBoxAction implements ModAction { + private static Logger logger = Logger.getLogger(TreasureBoxAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public TreasureBoxAction() { + logger.log(Level.WARNING, "TreasureBoxAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Open treasure", + "opening", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && object.getTemplateId() == TreasureBox.templateId) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(target.getTemplate().getTemplateId() != TreasureBox.templateId){ + performer.getCommunicator().sendNormalServerMessage("That is not a treasure box."); + return true; + } + if(target.getLastOwnerId() != performer.getWurmId() && target.getOwnerId() != performer.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You must own the treasure box to open it."); + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to open a treasure box."); + Server.getInstance().broadCastAction(performer.getName() + " begins opening "+performer.getHisHerItsString()+" treasure.", performer, 5); + act.setTimeLeft(50); + performer.sendActionControl("Opening", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + int aux; + if(target.getRarity() >= 3){ + aux = (int) (Server.rand.nextFloat()*target.getQualityLevel()*0.1f)+90; + }else if(target.getRarity() >= 2){ + aux = (int) (Server.rand.nextFloat()*target.getQualityLevel()*0.3f)+70; + }else if(target.getRarity() >= 1){ + aux = (int) (Server.rand.nextFloat()*target.getQualityLevel()*0.5f)+50; + }else{ + aux = (int) (Server.rand.nextFloat()*target.getQualityLevel()); + } + if(aux >= 90){ + performer.getCommunicator().sendNormalServerMessage("You open your treasure box containing fantastic treasures!"); + Server.getInstance().broadCastAction(performer.getName() + " opens "+performer.getHisHerItsString()+" treasure box, containing fantastic treasures!", performer, 5); + }else if(aux >= 60){ + performer.getCommunicator().sendNormalServerMessage("You open your treasure box containing supreme treasures!"); + Server.getInstance().broadCastAction(performer.getName() + " opens "+performer.getHisHerItsString()+" treasure box, containing supreme treasures!", performer, 5); + }else{ + performer.getCommunicator().sendNormalServerMessage("You open your treasure box containing rare treasures."); + Server.getInstance().broadCastAction(performer.getName() + " opens "+performer.getHisHerItsString()+" treasure box, containing rare treasures.", performer, 5); + } + logger.info("Player "+performer.getName()+" opened treasure box with power "+aux+"."); + TreasureChests.newFillTreasureChest(performer.getInventory(), aux); + Items.destroyItem(target.getWurmId()); + return true; + } + }else{ + logger.info("Somehow a non-player activated a Treasure Box..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/actions/items/TreasureCacheOpenAction.java b/src/main/java/mod/sin/actions/items/TreasureCacheOpenAction.java new file mode 100644 index 0000000..674ee67 --- /dev/null +++ b/src/main/java/mod/sin/actions/items/TreasureCacheOpenAction.java @@ -0,0 +1,123 @@ +package mod.sin.actions.items; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ActionPerformer; +import org.gotti.wurmunlimited.modsupport.actions.BehaviourProvider; +import org.gotti.wurmunlimited.modsupport.actions.ModAction; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.behaviours.Action; +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Player; + +import mod.sin.wyvern.Caches; + +public class TreasureCacheOpenAction implements ModAction { + private static Logger logger = Logger.getLogger(TreasureCacheOpenAction.class.getName()); + + private final short actionId; + private final ActionEntry actionEntry; + + public TreasureCacheOpenAction() { + logger.log(Level.WARNING, "TreasureCacheOpenAction()"); + + actionId = (short) ModActions.getNextActionId(); + actionEntry = ActionEntry.createEntry( + actionId, + "Open cache", + "opening", + new int[] { 6 /* ACTION_TYPE_NOMOVE */ } // 6 /* ACTION_TYPE_NOMOVE */, 48 /* ACTION_TYPE_ENEMY_ALWAYS */, 36 /* ACTION_TYPE_ALWAYS_USE_ACTIVE_ITEM */ + ); + ModActions.registerAction(actionEntry); + } + + + @Override + public BehaviourProvider getBehaviourProvider() + { + return new BehaviourProvider() { + // Menu with activated object + @Override + public List getBehavioursFor(Creature performer, Item source, Item object) + { + return this.getBehavioursFor(performer, object); + } + + // Menu without activated object + @Override + public List getBehavioursFor(Creature performer, Item object) + { + if(performer instanceof Player && object != null && Caches.isTreasureCache(object)) { + return Arrays.asList(actionEntry); + } + + return null; + } + }; + } + + @Override + public ActionPerformer getActionPerformer() + { + return new ActionPerformer() { + + @Override + public short getActionId() { + return actionId; + } + + // Without activated object + @Override + public boolean action(Action act, Creature performer, Item target, short action, float counter) + { + try{ + if(performer instanceof Player){ + if(!Caches.isTreasureCache(target)){ + performer.getCommunicator().sendNormalServerMessage("That is not a treasure cache."); + return true; + } + if(target.getLastOwnerId() != performer.getWurmId() && target.getOwnerId() != performer.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You must own the "+target.getName()+" to open it."); + return true; + } + if(counter == 1.0f){ + performer.getCommunicator().sendNormalServerMessage("You begin to open the "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " begins opening "+performer.getHisHerItsString()+" "+target.getName()+".", performer, 5); + act.setTimeLeft(50); + performer.sendActionControl("Opening", true, act.getTimeLeft()); + }else if(counter * 10f > performer.getCurrentAction().getTimeLeft()){ + performer.getCommunicator().sendNormalServerMessage("You open your "+target.getName()+"."); + Server.getInstance().broadCastAction(performer.getName() + " opens "+performer.getHisHerItsString()+" "+target.getName()+".", performer, 5); + logger.info("Player "+performer.getName()+" opened "+target.getName()+" at quality "+target.getCurrentQualityLevel()+" and rarity "+target.getRarity()); + Caches.openCache(performer, target); + Items.destroyItem(target.getWurmId()); + return true; + } + }else{ + logger.info("Somehow a non-player activated a Treasure Box..."); + } + return false; + }catch(Exception e){ + e.printStackTrace(); + return true; + } + } + + @Override + public boolean action(Action act, Creature performer, Item source, Item target, short action, float counter) + { + return this.action(act, performer, target, action, counter); + } + + + }; // ActionPerformer + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/armour/Glimmerscale.java b/src/main/java/mod/sin/armour/Glimmerscale.java new file mode 100644 index 0000000..3d4e2b5 --- /dev/null +++ b/src/main/java/mod/sin/armour/Glimmerscale.java @@ -0,0 +1,60 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class Glimmerscale { + private static Logger logger = Logger.getLogger(Glimmerscale.class.getName()); + public static int templateId; + private String name = "glimmerscale"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("item.mod.glimmerscale.scale"); + itemBuilder.name(name, "glimmerscales", "Legendary scales, made from the careful combination of dragon scales and glimmersteel."); + itemBuilder.descriptions("excellent", "good", "ok", "poor"); + itemBuilder.itemTypes(new short[]{ // {22, 146, 46, 113, 157} - Addy Lump + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_BULK, + ItemTypes.ITEM_TYPE_COMBINE, + ItemTypes.ITEM_TYPE_NOT_MISSION + }); + itemBuilder.imageNumber((short) 554); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(10, 30, 30); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.resource.scales.dragon."); + itemBuilder.difficulty(60.0f); + itemBuilder.weightGrams(400); + itemBuilder.material(Materials.MATERIAL_UNDEFINED); + itemBuilder.value(200000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + // CreationEntryCreator.createSimpleEntry(10041, 220, 47, 223, true, true, 0.0f, false, false, CreationCategories.RESOURCES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_METALLURGY, ItemList.dragonScale, ItemList.glimmerSteelBar, + templateId, true, true, 0.0f, true, false, CreationCategories.RESOURCES); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/GlimmerscaleBoot.java b/src/main/java/mod/sin/armour/GlimmerscaleBoot.java new file mode 100644 index 0000000..a1ca29a --- /dev/null +++ b/src/main/java/mod/sin/armour/GlimmerscaleBoot.java @@ -0,0 +1,71 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class GlimmerscaleBoot implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(GlimmerscaleBoot.class.getName()); + public static int templateId; + private String name = "glimmerscale boot"; + public void createTemplate() throws IOException{ + /*ItemTemplateCreator.createItemTemplate(473, 3, "drake hide jacket", "drake hide jackets", "excellent", "good", "ok", "poor", + * "A jacket made from finest drake hide with brass husks.", + * new short[]{108, 44, 23, 4, 99}, + * 1060, 1, 0, 29030400, 2, 40, 40, -10, new byte[]{2}, + * "model.armour.torso.dragon.", 70.0f, 600, 16, 100000, true, 9); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.glimmerscale.boot"); + itemBuilder.name(name, "glimmerscale boots", "A glimmerscale boot."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1025); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{15, 16}); + itemBuilder.modelName("model.armour.foot.dragon.scale.leather."); + itemBuilder.difficulty(72.0f); + itemBuilder.weightGrams(2000); + itemBuilder.material(Materials.MATERIAL_GLIMMERSTEEL); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_ARMOUR_PLATE, ItemList.anvilLarge, Glimmerscale.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/GlimmerscaleGlove.java b/src/main/java/mod/sin/armour/GlimmerscaleGlove.java new file mode 100644 index 0000000..39877cc --- /dev/null +++ b/src/main/java/mod/sin/armour/GlimmerscaleGlove.java @@ -0,0 +1,71 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class GlimmerscaleGlove implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(GlimmerscaleGlove.class.getName()); + public static int templateId; + private String name = "glimmerscale glove"; + public void createTemplate() throws IOException{ + /*ItemTemplateCreator.createItemTemplate(473, 3, "drake hide jacket", "drake hide jackets", "excellent", "good", "ok", "poor", + * "A jacket made from finest drake hide with brass husks.", + * new short[]{108, 44, 23, 4, 99}, + * 1060, 1, 0, 29030400, 2, 40, 40, -10, new byte[]{2}, + * "model.armour.torso.dragon.", 70.0f, 600, 16, 100000, true, 9); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.glimmerscale.glove"); + itemBuilder.name(name, "glimmerscale gloves", "A glimmerscale glove."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1024); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{13, 14}); + itemBuilder.modelName("model.armour.hand.dragon.scale.leather."); + itemBuilder.difficulty(70.0f); + itemBuilder.weightGrams(1200); + itemBuilder.material(Materials.MATERIAL_GLIMMERSTEEL); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_ARMOUR_PLATE, ItemList.anvilLarge, Glimmerscale.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/GlimmerscaleHelmet.java b/src/main/java/mod/sin/armour/GlimmerscaleHelmet.java new file mode 100644 index 0000000..b43f2c1 --- /dev/null +++ b/src/main/java/mod/sin/armour/GlimmerscaleHelmet.java @@ -0,0 +1,71 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class GlimmerscaleHelmet implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(GlimmerscaleHelmet.class.getName()); + public static int templateId; + private String name = "glimmerscale helmet"; + public void createTemplate() throws IOException{ + /*ItemTemplateCreator.createItemTemplate(473, 3, "drake hide jacket", "drake hide jackets", "excellent", "good", "ok", "poor", + * "A jacket made from finest drake hide with brass husks.", + * new short[]{108, 44, 23, 4, 99}, + * 1060, 1, 0, 29030400, 2, 40, 40, -10, new byte[]{2}, + * "model.armour.torso.dragon.", 70.0f, 600, 16, 100000, true, 9); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.glimmerscale.helmet"); + itemBuilder.name(name, "glimmerscale helmets", "A horned helmet made of glimmerscale."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 968); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{1, 28}); + itemBuilder.modelName("model.armour.head.greathelmHornedOfGold."); + itemBuilder.difficulty(76.0f); + itemBuilder.weightGrams(2500); + itemBuilder.material(Materials.MATERIAL_GLIMMERSTEEL); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_ARMOUR_PLATE, ItemList.anvilLarge, Glimmerscale.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/GlimmerscaleHose.java b/src/main/java/mod/sin/armour/GlimmerscaleHose.java new file mode 100644 index 0000000..97143c4 --- /dev/null +++ b/src/main/java/mod/sin/armour/GlimmerscaleHose.java @@ -0,0 +1,71 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class GlimmerscaleHose implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(GlimmerscaleHose.class.getName()); + public static int templateId; + private String name = "glimmerscale leggings"; + public void createTemplate() throws IOException{ + /*ItemTemplateCreator.createItemTemplate(473, 3, "drake hide jacket", "drake hide jackets", "excellent", "good", "ok", "poor", + * "A jacket made from finest drake hide with brass husks.", + * new short[]{108, 44, 23, 4, 99}, + * 1060, 1, 0, 29030400, 2, 40, 40, -10, new byte[]{2}, + * "model.armour.torso.dragon.", 70.0f, 600, 16, 100000, true, 9); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.glimmerscale.hose"); + itemBuilder.name(name, "glimmerscale leggings", "A set of glimmerscale leggings."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1021); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{34}); + itemBuilder.modelName("model.armour.leg.dragon.scale.leather."); + itemBuilder.difficulty(78.0f); + itemBuilder.weightGrams(3200); + itemBuilder.material(Materials.MATERIAL_GLIMMERSTEEL); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_ARMOUR_PLATE, ItemList.anvilLarge, Glimmerscale.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/GlimmerscaleSleeve.java b/src/main/java/mod/sin/armour/GlimmerscaleSleeve.java new file mode 100644 index 0000000..7c165cb --- /dev/null +++ b/src/main/java/mod/sin/armour/GlimmerscaleSleeve.java @@ -0,0 +1,71 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class GlimmerscaleSleeve implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(GlimmerscaleSleeve.class.getName()); + public static int templateId; + private String name = "glimmerscale sleeve"; + public void createTemplate() throws IOException{ + /*ItemTemplateCreator.createItemTemplate(473, 3, "drake hide jacket", "drake hide jackets", "excellent", "good", "ok", "poor", + * "A jacket made from finest drake hide with brass husks.", + * new short[]{108, 44, 23, 4, 99}, + * 1060, 1, 0, 29030400, 2, 40, 40, -10, new byte[]{2}, + * "model.armour.torso.dragon.", 70.0f, 600, 16, 100000, true, 9); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.glimmerscale.sleeve"); + itemBuilder.name(name, "glimmerscale sleeves", "A glimmerscale sleeve."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1022); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{3, 4}); + itemBuilder.modelName("model.armour.sleeve.dragon.scale.leather."); + itemBuilder.difficulty(74.0f); + itemBuilder.weightGrams(1800); + itemBuilder.material(Materials.MATERIAL_GLIMMERSTEEL); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_ARMOUR_PLATE, ItemList.anvilLarge, Glimmerscale.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/GlimmerscaleVest.java b/src/main/java/mod/sin/armour/GlimmerscaleVest.java new file mode 100644 index 0000000..231b9a1 --- /dev/null +++ b/src/main/java/mod/sin/armour/GlimmerscaleVest.java @@ -0,0 +1,71 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class GlimmerscaleVest implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(GlimmerscaleVest.class.getName()); + public static int templateId; + private String name = "glimmerscale vest"; + public void createTemplate() throws IOException{ + /*ItemTemplateCreator.createItemTemplate(473, 3, "drake hide jacket", "drake hide jackets", "excellent", "good", "ok", "poor", + * "A jacket made from finest drake hide with brass husks.", + * new short[]{108, 44, 23, 4, 99}, + * 1060, 1, 0, 29030400, 2, 40, 40, -10, new byte[]{2}, + * "model.armour.torso.dragon.", 70.0f, 600, 16, 100000, true, 9); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.glimmerscale.vest"); + itemBuilder.name(name, "glimmerscale vests", "A glimmerscale vest."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1020); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{2}); + itemBuilder.modelName("model.armour.torso.dragon.scale.leather."); + itemBuilder.difficulty(80.0f); + itemBuilder.weightGrams(4500); + itemBuilder.material(Materials.MATERIAL_GLIMMERSTEEL); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_ARMOUR_PLATE, ItemList.anvilLarge, Glimmerscale.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/SpectralBoot.java b/src/main/java/mod/sin/armour/SpectralBoot.java new file mode 100644 index 0000000..3998b8d --- /dev/null +++ b/src/main/java/mod/sin/armour/SpectralBoot.java @@ -0,0 +1,63 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class SpectralBoot implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(SpectralBoot.class.getName()); + public static int templateId; + private String name = "spectral boot"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.spectral.boot"); + itemBuilder.name(name, "spectral boots", "A spectral boot."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_LEATHER, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1065); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{15, 16}); + itemBuilder.modelName("model.armour.foot.dragon."); + itemBuilder.difficulty(70.0f); + itemBuilder.weightGrams(300); + itemBuilder.material(Materials.MATERIAL_LEATHER); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_LEATHER_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleIron, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleCopper, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/SpectralCap.java b/src/main/java/mod/sin/armour/SpectralCap.java new file mode 100644 index 0000000..96d0fea --- /dev/null +++ b/src/main/java/mod/sin/armour/SpectralCap.java @@ -0,0 +1,64 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class SpectralCap implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(SpectralCap.class.getName()); + public static int templateId; + private String name = "spectral cap"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.spectral.cap"); + itemBuilder.name(name, "spectral caps", "A spectral cap."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_LEATHER, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1063); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{1, 28}); + itemBuilder.modelName("model.armour.head.dragon."); + itemBuilder.difficulty(74.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_LEATHER); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_LEATHER_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info("Spectral improve = "+template.getImproveItem()); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleIron, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleCopper, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/SpectralGlove.java b/src/main/java/mod/sin/armour/SpectralGlove.java new file mode 100644 index 0000000..cf4f472 --- /dev/null +++ b/src/main/java/mod/sin/armour/SpectralGlove.java @@ -0,0 +1,63 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class SpectralGlove implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(SpectralGlove.class.getName()); + public static int templateId; + private String name = "spectral glove"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.spectral.glove"); + itemBuilder.name(name, "spectral gloves", "A spectral glove."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_LEATHER, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1064); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{13, 14}); + itemBuilder.modelName("model.armour.hand.dragon."); + itemBuilder.difficulty(68.0f); + itemBuilder.weightGrams(250); + itemBuilder.material(Materials.MATERIAL_LEATHER); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_LEATHER_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleIron, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleCopper, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/SpectralHide.java b/src/main/java/mod/sin/armour/SpectralHide.java new file mode 100644 index 0000000..212d8d0 --- /dev/null +++ b/src/main/java/mod/sin/armour/SpectralHide.java @@ -0,0 +1,43 @@ + package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class SpectralHide implements ItemTypes, MiscConstants { + private static Logger logger = Logger.getLogger(SpectralHide.class.getName()); + public static int templateId; + public void createTemplate() throws IOException{ + String name = "spectral hide"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("wyvern.spectral.hide"); + itemBuilder.name(name, "spectral hides", "Lightweight and transparent, this ethereal leather comes from another plane of existance. It is stronger than natural drake hide."); + itemBuilder.descriptions("excellent", "good", "ok", "poor"); + itemBuilder.itemTypes(new short[]{ + ITEM_TYPE_LEATHER, + ITEM_TYPE_HASDATA, + ITEM_TYPE_COMBINE + }); + itemBuilder.imageNumber((short) 602); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(10, 30, 30); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.resource.leather.dragon."); + itemBuilder.difficulty(20.0f); + itemBuilder.weightGrams(200); + itemBuilder.material(Materials.MATERIAL_LEATHER); + itemBuilder.value(200000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/armour/SpectralHose.java b/src/main/java/mod/sin/armour/SpectralHose.java new file mode 100644 index 0000000..cd441bd --- /dev/null +++ b/src/main/java/mod/sin/armour/SpectralHose.java @@ -0,0 +1,74 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class SpectralHose implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(SpectralHose.class.getName()); + public static int templateId; + private String name = "spectral leggings"; + public void createTemplate() throws IOException{ + /*ItemTemplateCreator.createItemTemplate(473, 3, "drake hide jacket", "drake hide jackets", "excellent", "good", "ok", "poor", + * "A jacket made from finest drake hide with brass husks.", + * new short[]{108, 44, 23, 4, 99}, + * 1060, 1, 0, 29030400, 2, 40, 40, -10, new byte[]{2}, + * "model.armour.torso.dragon.", 70.0f, 600, 16, 100000, true, 9); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.spectral.hose"); + itemBuilder.name(name, "spectral leggings", "Spectral leggings."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_LEATHER, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1061); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{34}); + itemBuilder.modelName("model.armour.leg.dragon."); + itemBuilder.difficulty(77.0f); + itemBuilder.weightGrams(700); + itemBuilder.material(Materials.MATERIAL_LEATHER); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_LEATHER_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info("Spectral improve = "+template.getImproveItem()); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleIron, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleCopper, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/SpectralJacket.java b/src/main/java/mod/sin/armour/SpectralJacket.java new file mode 100644 index 0000000..0271867 --- /dev/null +++ b/src/main/java/mod/sin/armour/SpectralJacket.java @@ -0,0 +1,73 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class SpectralJacket implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(SpectralJacket.class.getName()); + public static int templateId; + private String name = "spectral jacket"; + public void createTemplate() throws IOException{ + /*ItemTemplateCreator.createItemTemplate(473, 3, "drake hide jacket", "drake hide jackets", "excellent", "good", "ok", "poor", + * "A jacket made from finest drake hide with brass husks.", + * new short[]{108, 44, 23, 4, 99}, + * 1060, 1, 0, 29030400, 2, 40, 40, -10, new byte[]{2}, + * "model.armour.torso.dragon.", 70.0f, 600, 16, 100000, true, 9); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.spectral.jacket"); + itemBuilder.name(name, "spectral jackets", "A spectral jacket."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_LEATHER, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1060); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{2}); + itemBuilder.modelName("model.armour.torso.dragon."); + itemBuilder.difficulty(80.0f); + itemBuilder.weightGrams(800); + itemBuilder.material(Materials.MATERIAL_LEATHER); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_LEATHER_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleIron, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleCopper, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/armour/SpectralSleeve.java b/src/main/java/mod/sin/armour/SpectralSleeve.java new file mode 100644 index 0000000..b2656cf --- /dev/null +++ b/src/main/java/mod/sin/armour/SpectralSleeve.java @@ -0,0 +1,63 @@ +package mod.sin.armour; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class SpectralSleeve implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(SpectralSleeve.class.getName()); + public static int templateId; + private String name = "spectral sleeve"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.spectral.sleeve"); + itemBuilder.name(name, "spectral sleeves", "A spectral sleeve."); + itemBuilder.itemTypes(new short[]{ // {108, 44, 23, 4, 99} - Drake hide jacket + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_LEATHER, + ItemTypes.ITEM_TYPE_ARMOUR, + ItemTypes.ITEM_TYPE_DRAGONARMOUR + }); + itemBuilder.imageNumber((short) 1062); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(2, 40, 40); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(new byte[]{3, 4}); + itemBuilder.modelName("model.armour.sleeve.dragon."); + itemBuilder.difficulty(72.0f); + itemBuilder.weightGrams(400); + itemBuilder.material(Materials.MATERIAL_LEATHER); + itemBuilder.value(1000000); + itemBuilder.armourType(ArmourTypes.ARMOUR_LEATHER_DRAGON); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleIron, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + CreationEntryCreator.createSimpleEntry(SkillList.LEATHERWORKING, ItemList.needleCopper, SpectralHide.templateId, + templateId, false, true, 0.0f, false, false, CreationCategories.ARMOUR); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/creatures/Avenger.java b/src/main/java/mod/sin/creatures/Avenger.java new file mode 100644 index 0000000..e7bf6af --- /dev/null +++ b/src/main/java/mod/sin/creatures/Avenger.java @@ -0,0 +1,75 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class Avenger implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_DOMINATABLE, + CreatureTypes.C_TYPE_DETECTINVIS, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.avenger", "Avenger", "Sent from the heavens to purge the unworthy.", + "model.creature.humanoid.avenger.light", types, BodyTemplate.TYPE_HUMAN, (short) 5, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.giant", "sound.death.giant", "sound.combat.hit.giant", "sound.combat.hit.giant", + 0.3f, 25f, 0f, 0f, 0.0f, 0.0f, 1.2f, 500, + new int[]{}, 15, 70, Materials.MATERIAL_MEAT_HUMANOID); + + builder.skill(SkillList.BODY_STRENGTH, 45.0f); + builder.skill(SkillList.BODY_STAMINA, 55.0f); + builder.skill(SkillList.BODY_CONTROL, 60.0f); + builder.skill(SkillList.MIND_LOGICAL, 50.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 50.0f); + builder.skill(SkillList.SOUL_DEPTH, 50.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 70.0f); + builder.skill(SkillList.GROUP_FIGHTING, 50.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("slam"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_LEATHER); + builder.baseCombatRating(45.0f); + builder.combatDamageType(Wound.TYPE_COLD); + builder.maxPercentOfCreatures(0.005f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_TUNDRA.id) + .addCreatures(templateId, 1) + .build(1); + } +} diff --git a/src/main/java/mod/sin/creatures/Bison.java b/src/main/java/mod/sin/creatures/Bison.java new file mode 100644 index 0000000..68e1886 --- /dev/null +++ b/src/main/java/mod/sin/creatures/Bison.java @@ -0,0 +1,67 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviour; +import org.gotti.wurmunlimited.modsupport.vehicles.VehicleFacade; + +import com.wurmonline.server.behaviours.Vehicle; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTemplate; +import com.wurmonline.server.creatures.CreatureTemplateFactory; +import com.wurmonline.server.creatures.CreatureTemplateIds; +import com.wurmonline.server.creatures.NoSuchCreatureTemplateException; +import com.wurmonline.server.items.Item; + +public class Bison implements ModCreature { + + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + templateId = CreatureTemplateIds.BISON_CID; + return new CreatureTemplateBuilder(templateId) { + @Override + public CreatureTemplate build() { + try { + return CreatureTemplateFactory.getInstance().getTemplate(templateId); + } catch (NoSuchCreatureTemplateException e) { + throw new RuntimeException(e); + } + } + }; + } + + public ModVehicleBehaviour getVehicleBehaviour() { + + return new ModVehicleBehaviour() { + + @Override + public void setSettingsForVehicle(Item item, Vehicle vehicle) { + } + + @Override + public void setSettingsForVehicle(Creature creature, Vehicle v) { + VehicleFacade vehicle = wrap(v); + + vehicle.createPassengerSeats(0); + vehicle.setSeatFightMod(0, 0.7f, 0.9f); + vehicle.setSeatOffset(0, 0.0f, 0.0f, 0f); + vehicle.setCreature(true); + vehicle.setSkillNeeded(27.0f); + vehicle.setName(creature.getName()); + vehicle.setMaxDepth(-0.7f); + vehicle.setMaxHeightDiff(0.04f); + vehicle.setMaxSpeed(25.0f); + vehicle.setCommandType((byte) 3); + vehicle.setCanHaveEquipment(true); + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + } +} diff --git a/src/main/java/mod/sin/creatures/Charger.java b/src/main/java/mod/sin/creatures/Charger.java new file mode 100644 index 0000000..874f859 --- /dev/null +++ b/src/main/java/mod/sin/creatures/Charger.java @@ -0,0 +1,116 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviour; +import org.gotti.wurmunlimited.modsupport.vehicles.VehicleFacade; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.behaviours.Vehicle; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class Charger implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_MOVE_GLOBAL, + CreatureTypes.C_TYPE_VEHICLE, + CreatureTypes.C_TYPE_LEADABLE, + CreatureTypes.C_TYPE_SWIMMING, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_DOMINATABLE, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_NON_NEWBIE, + CreatureTypes.C_TYPE_HORSE, + CreatureTypes.C_TYPE_ANIMAL + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.charger", "Charger", "A blazing-fast stallion.", + "model.creature.quadraped.horse.hell", types, BodyTemplate.TYPE_HORSE, (short) 5, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.horse", "sound.death.horse", "sound.combat.hit.horse", "sound.combat.hit.horse", + 1.1f, 12f, 10f, 10.0f, 0.0f, 0.0f, 1.6f, 1000, + new int[]{}, 10, 74, Materials.MATERIAL_MEAT_HORSE); + + builder.skill(SkillList.BODY_STRENGTH, 37.0f); + builder.skill(SkillList.BODY_STAMINA, 30.0f); + builder.skill(SkillList.BODY_CONTROL, 25.0f); + builder.skill(SkillList.MIND_LOGICAL, 30.0f); + builder.skill(SkillList.MIND_SPEED, 20.0f); + builder.skill(SkillList.SOUL_STRENGTH, 30.0f); + builder.skill(SkillList.SOUL_DEPTH, 30.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 25.0f); + builder.skill(SkillList.GROUP_FIGHTING, 20.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("burn"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_LEATHER); + builder.baseCombatRating(13.0f); + builder.combatDamageType(Wound.TYPE_BURN); + builder.denMaterial(Materials.MATERIAL_WOOD_BIRCH); + builder.denName("charger lair"); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + public ModVehicleBehaviour getVehicleBehaviour() { + + return new ModVehicleBehaviour() { + + @Override + public void setSettingsForVehicle(Item item, Vehicle vehicle) { + } + + @Override + public void setSettingsForVehicle(Creature creature, Vehicle v) { + VehicleFacade vehicle = wrap(v); + + vehicle.createPassengerSeats(0); + vehicle.setSeatFightMod(0, 0.8f, 1.1f); + vehicle.setSeatOffset(0, 0.0f, 0.0f, 0.3f); + vehicle.setCreature(true); + vehicle.setSkillNeeded(37.0f); + vehicle.setName(creature.getName()); + vehicle.setMaxHeightDiff(0.09f); + vehicle.setMaxDepth(-1.7f); + vehicle.setMaxSpeed(46.0f); + vehicle.setCommandType((byte) 3); + vehicle.setCanHaveEquipment(true); + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_STEPPE.id) + .addCreatures(templateId, 1) + .build(3); + + new EncounterBuilder(Tiles.Tile.TILE_STEPPE.id) + .addCreatures(templateId, 1) + .build(1); + } +} diff --git a/src/main/java/mod/sin/creatures/Facebreyker.java b/src/main/java/mod/sin/creatures/Facebreyker.java new file mode 100644 index 0000000..0753b17 --- /dev/null +++ b/src/main/java/mod/sin/creatures/Facebreyker.java @@ -0,0 +1,72 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; + +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.skills.SkillList; + +public class Facebreyker implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_UNIQUE, + CreatureTypes.C_TYPE_REGENERATING, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_FENCEBREAKER, + CreatureTypes.C_TYPE_HERBIVORE, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.unique.facebreyker", "Facebreyker", "A bold warrior corrupted by darkness. You feel the presence of Libila.", + "model.creature.humanoid.ogre.rift", types, (byte) 0, (short) 20, (byte) 0, (short) 350, (short) 100, (short) 60, + "sound.death.troll", "sound.death.troll", "sound.combat.hit.troll", "sound.combat.hit.troll", + 0.05f, 50.0f, 50.0f, 0.0f, 0.0f, 0.0f, 1.6f, 1100, + new int[]{867}, 40, 100, (byte) 0); + + builder.skill(SkillList.BODY_STRENGTH, 90.0f); + builder.skill(SkillList.BODY_STAMINA, 90.0f); + builder.skill(SkillList.BODY_CONTROL, 90.0f); + builder.skill(SkillList.MIND_LOGICAL, 30.0f); + builder.skill(SkillList.MIND_SPEED, 30.0f); + builder.skill(SkillList.SOUL_STRENGTH, 70.0f); + builder.skill(SkillList.SOUL_DEPTH, 60.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 80.0f); + builder.skill(SkillList.GROUP_FIGHTING, 80.0f); + builder.skill(SkillList.GROUP_CLUBS, 99.0f); + builder.skill(SkillList.CLUB_HUGE, 99.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("slashe"); + builder.kickDamString("eviscerate"); + builder.maxAge(200); + builder.armourType(10); + builder.baseCombatRating(80.0f); + builder.combatDamageType(Wound.TYPE_CRUSH); + builder.maxGroupAttackSize(100); + + //builder.usesNewAttacks(true); + // float baseDamage, float criticalChance, float baseSpeed, int attackReach, int weightGroup, byte damageType, boolean usesWeapon, int rounds, float waitUntilNextAttack + //builder.addPrimaryAttack(new AttackAction("slashe", AttackIdentifier.STRIKE, new AttackValues(70f, 0.05f, 5f, 3, 1, Wound.TYPE_SLASH, false, 1, 1.0f))); + //builder.addPrimaryAttack(new AttackAction("eviscerate", AttackIdentifier.STRIKE, new AttackValues(100f, 0.5f, 30f, 3, 1, Wound.TYPE_INFECTION, false, 4, 5.0f))); + //builder.addSecondaryAttack(new AttackAction("annihilate", AttackIdentifier.KICK, new AttackValues(200f, 0.3f, 60f, 2, 1, Wound.TYPE_ACID, false, 7, 8.0f))); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + return; + } +} diff --git a/src/main/java/mod/sin/creatures/ForestSpider.java b/src/main/java/mod/sin/creatures/ForestSpider.java new file mode 100644 index 0000000..ef73689 --- /dev/null +++ b/src/main/java/mod/sin/creatures/ForestSpider.java @@ -0,0 +1,80 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class ForestSpider implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_ANIMAL, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.forest.spider", "Forest spider", "Found amongst trees, these spiders are dangerous and poisonous.", + "model.creature.multiped.spider.huge", types, BodyTemplate.TYPE_SPIDER, (short) 5, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.spider", "sound.death.spider", "sound.combat.hit.spider", "sound.combat.hit.spider", + 0.6f, 10f, 0f, 13.0f, 0.0f, 0.0f, 1.2f, 500, + new int[]{ItemList.heart}, 10, 74, Materials.MATERIAL_MEAT_INSECT); + + builder.skill(SkillList.BODY_STRENGTH, 20.0f); + builder.skill(SkillList.BODY_STAMINA, 30.0f); + builder.skill(SkillList.BODY_CONTROL, 35.0f); + builder.skill(SkillList.MIND_LOGICAL, 30.0f); + builder.skill(SkillList.MIND_SPEED, 30.0f); + builder.skill(SkillList.SOUL_STRENGTH, 30.0f); + builder.skill(SkillList.SOUL_DEPTH, 30.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 50.0f); + builder.skill(SkillList.GROUP_FIGHTING, 30.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("pierce"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_CLOTH); + builder.baseCombatRating(13.0f); + builder.combatDamageType(Wound.TYPE_POISON); + builder.denMaterial(Materials.MATERIAL_STONE); + builder.denName("forest spider lair"); + builder.maxPercentOfCreatures(0.05f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_TREE.id) + .addCreatures(templateId, 1) + .build(2); + + new EncounterBuilder(Tiles.Tile.TILE_GRASS.id) + .addCreatures(templateId, 1) + .build(2); + } +} diff --git a/src/main/java/mod/sin/creatures/Giant.java b/src/main/java/mod/sin/creatures/Giant.java new file mode 100644 index 0000000..1af22a8 --- /dev/null +++ b/src/main/java/mod/sin/creatures/Giant.java @@ -0,0 +1,84 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class Giant implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_REGENERATING, + CreatureTypes.C_TYPE_DOMINATABLE, + CreatureTypes.C_TYPE_DETECTINVIS, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.giant", "Giant", "A lumbering hulk.", + "model.creature.humanoid.giant.forest", types, BodyTemplate.TYPE_ETTIN, (short) 5, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.giant", "sound.death.giant", "sound.combat.hit.giant", "sound.combat.hit.giant", + 0.3f, 19f, 15f, 0f, 0.0f, 0.0f, 0.7f, 300, + new int[]{ItemList.heart, ItemList.eye, ItemList.gland, ItemList.tooth}, 15, 70, Materials.MATERIAL_MEAT_TOUGH); + + builder.skill(SkillList.BODY_STRENGTH, 55.0f); + builder.skill(SkillList.BODY_STAMINA, 65.0f); + builder.skill(SkillList.BODY_CONTROL, 30.0f); + builder.skill(SkillList.MIND_LOGICAL, 10.0f); + builder.skill(SkillList.MIND_SPEED, 10.0f); + builder.skill(SkillList.SOUL_STRENGTH, 10.0f); + builder.skill(SkillList.SOUL_DEPTH, 10.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 60.0f); + builder.skill(SkillList.GROUP_FIGHTING, 40.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("maul"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_LEATHER); + builder.baseCombatRating(32.0f); + builder.combatDamageType(Wound.TYPE_ACID); + builder.denMaterial(Materials.MATERIAL_WOOD_BIRCH); + builder.denName("giant lair"); + builder.maxPercentOfCreatures(0.001f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_GRASS.id) + .addCreatures(templateId, 1) + .build(1); + + new EncounterBuilder(Tiles.Tile.TILE_TREE.id) + .addCreatures(templateId, 1) + .build(1); + + } +} diff --git a/src/main/java/mod/sin/creatures/HornedPony.java b/src/main/java/mod/sin/creatures/HornedPony.java new file mode 100644 index 0000000..c7fc26e --- /dev/null +++ b/src/main/java/mod/sin/creatures/HornedPony.java @@ -0,0 +1,114 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviour; +import org.gotti.wurmunlimited.modsupport.vehicles.VehicleFacade; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Vehicle; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class HornedPony implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_MOVE_GLOBAL, + CreatureTypes.C_TYPE_VEHICLE, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_LEADABLE, + CreatureTypes.C_TYPE_SWIMMING, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_DOMINATABLE, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_NON_NEWBIE, + CreatureTypes.C_TYPE_HORSE, + CreatureTypes.C_TYPE_ANIMAL + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.horned.pony", "Horned pony", "Not a unicorn. Unicorns are fictional.", + "model.creature.quadraped.unicorn", types, BodyTemplate.TYPE_HORSE, (short) 5, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.horse", "sound.death.horse", "sound.combat.hit.horse", "sound.combat.hit.horse", + Servers.localServer.PVPSERVER ? 0.75f : 0.4f, 17f, 13f, 15.0f, 0.0f, 0.0f, 1.4f, 800, + new int[]{ItemList.heart}, 10, 74, Materials.MATERIAL_MEAT_HORSE); + + builder.skill(SkillList.BODY_STRENGTH, Servers.localServer.PVPSERVER ? 40.0f : 60.0f); + builder.skill(SkillList.BODY_STAMINA, 60.0f); + builder.skill(SkillList.BODY_CONTROL, 55.0f); + builder.skill(SkillList.MIND_LOGICAL, 40.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 30.0f); + builder.skill(SkillList.SOUL_DEPTH, 30.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 50.0f); + builder.skill(SkillList.GROUP_FIGHTING, 40.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("horn"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + builder.baseCombatRating(Servers.localServer.PVPSERVER ? 15.0f : 20.0f); + builder.combatDamageType(Wound.TYPE_INTERNAL); + builder.maxPercentOfCreatures(0.001f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + public ModVehicleBehaviour getVehicleBehaviour() { + + return new ModVehicleBehaviour() { + + @Override + public void setSettingsForVehicle(Item item, Vehicle vehicle) { + } + + @Override + public void setSettingsForVehicle(Creature creature, Vehicle v) { + VehicleFacade vehicle = wrap(v); + + vehicle.createPassengerSeats(0); + vehicle.setSeatFightMod(0, 0.8f, 1.1f); + vehicle.setSeatOffset(0, 0.0f, 0.0f, 0.0f); + vehicle.setCreature(true); + vehicle.setSkillNeeded(35.0f); + vehicle.setName(creature.getName()); + vehicle.setMaxHeightDiff(0.08f); + vehicle.setMaxDepth(-1.7f); + vehicle.setMaxSpeed(40.0f); + vehicle.setCommandType((byte) 3); + vehicle.setCanHaveEquipment(Servers.localServer.PVPSERVER ? false : true); + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_ENCHANTED_GRASS.id) + .addCreatures(templateId, 1) + .build(2); + } +} diff --git a/src/main/java/mod/sin/creatures/LargeBoar.java b/src/main/java/mod/sin/creatures/LargeBoar.java new file mode 100644 index 0000000..a0d8ebb --- /dev/null +++ b/src/main/java/mod/sin/creatures/LargeBoar.java @@ -0,0 +1,80 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class LargeBoar implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_ANIMAL, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.boar", "Large boar", "A large and strong boar.", + "model.creature.quadraped.boar.wild", types, (byte) BodyTemplate.TYPE_DOG, (short) 5, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.pig", "sound.death.pig", "sound.combat.hit.pig", "sound.combat.hit.pig", + 0.5f, 8f, 0f, 10.0f, 14.0f, 0.0f, 1.2f, 500, + new int[]{ItemList.fur, ItemList.heart}, 10, 74, Materials.MATERIAL_MEAT_PORK); + + builder.skill(SkillList.BODY_STRENGTH, 30.0f); + builder.skill(SkillList.BODY_STAMINA, 35.0f); + builder.skill(SkillList.BODY_CONTROL, 45.0f); + builder.skill(SkillList.MIND_LOGICAL, 5.0f); + builder.skill(SkillList.MIND_SPEED, 10.0f); + builder.skill(SkillList.SOUL_STRENGTH, 34.0f); + builder.skill(SkillList.SOUL_DEPTH, 3.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 40.0f); + builder.skill(SkillList.GROUP_FIGHTING, 30.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("kick"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_CLOTH); + builder.baseCombatRating(18.0f); + builder.combatDamageType(Wound.TYPE_CRUSH); + builder.denMaterial(Materials.MATERIAL_WOOD_BIRCH); + builder.denName("boar lair"); + builder.maxPercentOfCreatures(0.01f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_SAND.id) + .addCreatures(templateId, 1) + .build(2); + + new EncounterBuilder(Tiles.Tile.TILE_GRASS.id) + .addCreatures(templateId, 1) + .build(3); + } +} diff --git a/src/main/java/mod/sin/creatures/LavaFiend.java b/src/main/java/mod/sin/creatures/LavaFiend.java new file mode 100644 index 0000000..0f3a9f4 --- /dev/null +++ b/src/main/java/mod/sin/creatures/LavaFiend.java @@ -0,0 +1,43 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.creatures.CreatureTemplate; +import com.wurmonline.server.creatures.CreatureTemplateFactory; +import com.wurmonline.server.creatures.CreatureTemplateIds; +import com.wurmonline.server.creatures.NoSuchCreatureTemplateException; + +public class LavaFiend implements ModCreature { + + private int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + templateId = CreatureTemplateIds.LAVA_CREATURE_CID; + return new CreatureTemplateBuilder(templateId) { + @Override + public CreatureTemplate build() { + try { + + return CreatureTemplateFactory.getInstance().getTemplate(templateId); + } catch (NoSuchCreatureTemplateException e) { + throw new RuntimeException(e); + } + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_SAND.id) + .addCreatures(templateId, 1) + .build(1); + + } +} diff --git a/src/main/java/mod/sin/creatures/MacroSlayer.java b/src/main/java/mod/sin/creatures/MacroSlayer.java new file mode 100644 index 0000000..0551a90 --- /dev/null +++ b/src/main/java/mod/sin/creatures/MacroSlayer.java @@ -0,0 +1,63 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; + +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class MacroSlayer implements ModCreature, CreatureTypes { + public static int templateId; + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + int[] types = { + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_SWIMMING, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_HERBIVORE, + CreatureTypes.C_TYPE_FENCEBREAKER, + CreatureTypes.C_TYPE_NON_NEWBIE, + CreatureTypes.C_TYPE_NO_REBIRTH + }; + + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.macro.slayer", "Blobber the Macro Slayer", + "The incarnation of the Macro King. Here to claim the souls of those who challenge his rightful rule.", "model.blob", + types, BodyTemplate.TYPE_DRAGON, (short) 5, (byte) 0, (short) 350, (short) 100, (short) 60, + "sound.death.dragon", "sound.death.dragon", "sound.combat.hit.dragon", "sound.combat.hit.dragon", + 0.001f, 10.0f, 10.0f, 10.0f, 10.0f, 10.0f, 0.5f, 500, + new int[]{}, 40, 100, Materials.MATERIAL_MEAT_HUMANOID); + + builder.skill(SkillList.BODY_STRENGTH, 90.0f); + builder.skill(SkillList.BODY_STAMINA, 70.0f); + builder.skill(SkillList.BODY_CONTROL, 60.0f); + builder.skill(SkillList.MIND_LOGICAL, 35.0f); + builder.skill(SkillList.MIND_SPEED, 45.0f); + builder.skill(SkillList.SOUL_STRENGTH, 80.0f); + builder.skill(SkillList.SOUL_DEPTH, 80.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 80.0f); + builder.skill(SkillList.GROUP_FIGHTING, 80.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("macro"); + builder.kickDamString("macro"); + builder.maxAge(200); + builder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + builder.baseCombatRating(99.0f); + builder.combatDamageType(Wound.TYPE_WATER); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + return; + } +} diff --git a/src/main/java/mod/sin/creatures/Reaper.java b/src/main/java/mod/sin/creatures/Reaper.java new file mode 100644 index 0000000..e169efe --- /dev/null +++ b/src/main/java/mod/sin/creatures/Reaper.java @@ -0,0 +1,64 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; + +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class Reaper implements ModCreature, CreatureTypes { + public static int templateId; + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + int[] types = { + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_SWIMMING, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_HERBIVORE, + CreatureTypes.C_TYPE_FENCEBREAKER, + CreatureTypes.C_TYPE_NON_NEWBIE, + CreatureTypes.C_TYPE_NO_REBIRTH + }; + + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.reaper", "Reaper", + "The reaper, here to claim the soul of a powerful creature... and anything else.", "model.creature.gmdark", + types, BodyTemplate.TYPE_HUMAN, (short) 20, (byte) 0, (short) 350, (short) 100, (short) 60, "sound.death.dragon", + "sound.death.dragon", "sound.combat.hit.dragon", "sound.combat.hit.dragon", + 0.03f, 35.0f, 45.0f, 22.0f, 40.0f, 0.0f, 2.5f, 500, + new int[]{ItemList.boneCollar}, 40, 100, Materials.MATERIAL_MEAT_HUMANOID); + + builder.skill(SkillList.BODY_STRENGTH, 60.0f); + builder.skill(SkillList.BODY_STAMINA, 70.0f); + builder.skill(SkillList.BODY_CONTROL, 60.0f); + builder.skill(SkillList.MIND_LOGICAL, 35.0f); + builder.skill(SkillList.MIND_SPEED, 45.0f); + builder.skill(SkillList.SOUL_STRENGTH, 80.0f); + builder.skill(SkillList.SOUL_DEPTH, 80.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 80.0f); + builder.skill(SkillList.GROUP_FIGHTING, 80.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("slice"); + builder.kickDamString("reap"); + builder.maxAge(200); + builder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + builder.baseCombatRating(55.0f); + builder.combatDamageType(Wound.TYPE_INFECTION); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + return; + } +} diff --git a/src/main/java/mod/sin/creatures/RobZombie.java b/src/main/java/mod/sin/creatures/RobZombie.java new file mode 100644 index 0000000..0ad4fd4 --- /dev/null +++ b/src/main/java/mod/sin/creatures/RobZombie.java @@ -0,0 +1,51 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; + +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.skills.SkillList; + +public class RobZombie implements ModCreature, CreatureTypes { + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_HERBIVORE, + CreatureTypes.C_TYPE_UNDEAD, + CreatureTypes.C_TYPE_TRADER, + CreatureTypes.C_TYPE_NPC_TRADER}; + + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.zombie.rob", "Rob Zombie", + "This is Rob Zombie. He is known to eat brains when you do not buy things from him.", "model.creature.humanoid.human.player.zombie", + types, (byte) 0, (short) 20, (byte) 0, (short) 350, (short) 100, (short) 60, + "sound.death.zombie", "sound.death.zombie", "sound.combat.hit.zombie", "sound.combat.hit.zombie", + 0.005f, 150.0f, 150.0f, 150.0f, 0.0f, 0.0f, 0.5f, 500, new int[]{868, 867}, 40, 100, (byte) 0); + + builder.skill(SkillList.BODY_STRENGTH, 99.0f); + builder.skill(SkillList.BODY_STAMINA, 99.0f); + builder.skill(SkillList.BODY_CONTROL, 99.0f); + builder.skill(SkillList.MIND_LOGICAL, 99.0f); + builder.skill(SkillList.MIND_SPEED, 99.0f); + builder.skill(SkillList.SOUL_STRENGTH, 99.0f); + builder.skill(SkillList.SOUL_DEPTH, 99.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 99.0f); + builder.skill(SkillList.GROUP_FIGHTING, 99.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("decimate"); + builder.kickDamString("decimate"); + builder.maxAge(200); + builder.armourType(10); + builder.baseCombatRating(99.0f); + builder.combatDamageType((byte)2); + builder.maxGroupAttackSize(100); + + return builder; + } + + @Override + public void addEncounters() { + return; + } +} diff --git a/src/main/java/mod/sin/creatures/SolDemon.java b/src/main/java/mod/sin/creatures/SolDemon.java new file mode 100644 index 0000000..3b7ef72 --- /dev/null +++ b/src/main/java/mod/sin/creatures/SolDemon.java @@ -0,0 +1,46 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.creatures.CreatureTemplate; +import com.wurmonline.server.creatures.CreatureTemplateFactory; +import com.wurmonline.server.creatures.CreatureTemplateIds; +import com.wurmonline.server.creatures.NoSuchCreatureTemplateException; + +public class SolDemon implements ModCreature { + + private int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + templateId = CreatureTemplateIds.DEMON_SOL_CID; + return new CreatureTemplateBuilder(templateId) { + @Override + public CreatureTemplate build() { + try { + + return CreatureTemplateFactory.getInstance().getTemplate(templateId); + } catch (NoSuchCreatureTemplateException e) { + throw new RuntimeException(e); + } + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_SAND.id) + .addCreatures(templateId, 2) + .build(1); + + new EncounterBuilder(Tiles.Tile.TILE_MYCELIUM.id) + .addCreatures(templateId, 2) + .build(3); + } +} diff --git a/src/main/java/mod/sin/creatures/SpectralDrake.java b/src/main/java/mod/sin/creatures/SpectralDrake.java new file mode 100644 index 0000000..c539ab9 --- /dev/null +++ b/src/main/java/mod/sin/creatures/SpectralDrake.java @@ -0,0 +1,64 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; + +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class SpectralDrake implements ModCreature { + public static int templateId; + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + int[] types = { + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_SWIMMING, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_HERBIVORE, + CreatureTypes.C_TYPE_FENCEBREAKER, + CreatureTypes.C_TYPE_NON_NEWBIE, + CreatureTypes.C_TYPE_NO_REBIRTH + }; + + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.spectraldrake", "Spectral drake", + "The spectral incarnation of a defeated dragon.", "model.creature.drake.spirit", types, BodyTemplate.TYPE_DRAGON, + (short) 20, (byte) 0, (short) 350, (short) 100, (short) 60, "sound.death.dragon", "sound.death.dragon", + "sound.combat.hit.dragon", "sound.combat.hit.dragon", + 0.06f, 45.0f, 50.0f, 22.0f, 45.0f, 0.0f, 2.0f, 500, + new int[]{ItemList.boneCollar}, 40, 100, Materials.MATERIAL_MEAT_DRAGON); + + builder.skill(SkillList.BODY_STRENGTH, 60.0f); + builder.skill(SkillList.BODY_STAMINA, 70.0f); + builder.skill(SkillList.BODY_CONTROL, 60.0f); + builder.skill(SkillList.MIND_LOGICAL, 35.0f); + builder.skill(SkillList.MIND_SPEED, 45.0f); + builder.skill(SkillList.SOUL_STRENGTH, 70.0f); + builder.skill(SkillList.SOUL_DEPTH, 70.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 85.0f); + builder.skill(SkillList.GROUP_FIGHTING, 75.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("claw"); + builder.kickDamString("wingbuff"); + builder.maxAge(200); + builder.armourType(ArmourTypes.ARMOUR_LEATHER_DRAGON); + builder.baseCombatRating(60.0f); + builder.combatDamageType(Wound.TYPE_COLD); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + return; + } +} diff --git a/src/main/java/mod/sin/creatures/SpiritTroll.java b/src/main/java/mod/sin/creatures/SpiritTroll.java new file mode 100644 index 0000000..8a84344 --- /dev/null +++ b/src/main/java/mod/sin/creatures/SpiritTroll.java @@ -0,0 +1,80 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class SpiritTroll implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // new int[]{7, 6, 40, 13, 16, 18, 29, 30, 32, 36, 39, 45, 60, 61}; - Troll + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_FENCEBREAKER, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_REGENERATING, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_CLIMBER, + CreatureTypes.C_TYPE_UNDEAD, + CreatureTypes.C_TYPE_DETECTINVIS, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.spirit.troll", "Spirit troll", "A spirit troll.", + "model.creature.humanoid.troll.standard", types, BodyTemplate.TYPE_HUMAN, (short) 5, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.troll", "sound.death.troll", "sound.combat.hit.troll", "sound.combat.hit.troll", + 0.15f, 15f, 17f, 19.0f, 0.0f, 0.0f, 1.2f, 500, + new int[]{}, 10, 74, (byte) 82); + + builder.skill(SkillList.BODY_STRENGTH, 45.0f); + builder.skill(SkillList.BODY_STAMINA, 40.0f); + builder.skill(SkillList.BODY_CONTROL, 45.0f); + builder.skill(SkillList.MIND_LOGICAL, 30.0f); + builder.skill(SkillList.MIND_SPEED, 30.0f); + builder.skill(SkillList.SOUL_STRENGTH, 30.0f); + builder.skill(SkillList.SOUL_DEPTH, 30.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 50.0f); + builder.skill(SkillList.GROUP_FIGHTING, 30.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("maul"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_LEATHER); + builder.baseCombatRating(26.0f); + builder.combatDamageType(Wound.TYPE_COLD); + builder.denMaterial(Materials.MATERIAL_WOOD_BIRCH); + builder.denName("spirit troll lair"); + builder.maxPercentOfCreatures(0.001f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_SNOW.id) + .addCreatures(templateId, 1) + .build(1); + } +} diff --git a/src/main/java/mod/sin/creatures/Worg.java b/src/main/java/mod/sin/creatures/Worg.java new file mode 100644 index 0000000..b3ab892 --- /dev/null +++ b/src/main/java/mod/sin/creatures/Worg.java @@ -0,0 +1,77 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviour; +import org.gotti.wurmunlimited.modsupport.vehicles.VehicleFacade; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.behaviours.Vehicle; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTemplate; +import com.wurmonline.server.creatures.CreatureTemplateFactory; +import com.wurmonline.server.creatures.CreatureTemplateIds; +import com.wurmonline.server.creatures.NoSuchCreatureTemplateException; +import com.wurmonline.server.items.Item; + +public class Worg implements ModCreature { + + private int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + templateId = CreatureTemplateIds.WORG_CID; + return new CreatureTemplateBuilder(templateId) { + @Override + public CreatureTemplate build() { + try { + return CreatureTemplateFactory.getInstance().getTemplate(templateId); + } catch (NoSuchCreatureTemplateException e) { + throw new RuntimeException(e); + } + } + }; + } + + public ModVehicleBehaviour getVehicleBehaviour() { + + return new ModVehicleBehaviour() { + + @Override + public void setSettingsForVehicle(Item item, Vehicle vehicle) { + } + + @Override + public void setSettingsForVehicle(Creature creature, Vehicle v) { + VehicleFacade vehicle = wrap(v); + + vehicle.createPassengerSeats(0); + vehicle.setSeatFightMod(0, 0.8f, 1.1f); + vehicle.setSeatOffset(0, -0.2f, 0.0f, -0.1f); + vehicle.setCreature(true); + vehicle.setSkillNeeded(30.0f); + vehicle.setName(creature.getName()); + vehicle.setMaxHeightDiff(0.07f); + vehicle.setMaxDepth(-1.7f); + vehicle.setMaxSpeed(50.0f); + vehicle.setCommandType((byte) 3); + vehicle.setCanHaveEquipment(false); + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_GRASS.id) + .addCreatures(templateId, 2) + .build(1); + + new EncounterBuilder(Tiles.Tile.TILE_STEPPE.id) + .addCreatures(templateId, 2) + .build(3); + } +} diff --git a/src/main/java/mod/sin/creatures/WyvernBlack.java b/src/main/java/mod/sin/creatures/WyvernBlack.java new file mode 100644 index 0000000..1fc1d77 --- /dev/null +++ b/src/main/java/mod/sin/creatures/WyvernBlack.java @@ -0,0 +1,121 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviour; +import org.gotti.wurmunlimited.modsupport.vehicles.VehicleFacade; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Vehicle; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class WyvernBlack implements ModCreature, CreatureTypes { + public static int templateId; + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + int[] types = { + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_MOVE_GLOBAL, + CreatureTypes.C_TYPE_VEHICLE, + CreatureTypes.C_TYPE_REGENERATING, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_SWIMMING, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_DOMINATABLE, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_NON_NEWBIE, + CreatureTypes.C_TYPE_ANIMAL + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.wyvern.black", "Black wyvern", "A battle-hardened wyvern with scales as black as night.", + "model.creature.drake.black", types, BodyTemplate.TYPE_DRAGON, (short) 10, (byte) 0, (short) 350, (short) 100, (short) 60, + "sound.death.dragon", "sound.death.dragon", "sound.combat.hit.dragon", "sound.combat.hit.dragon", + Servers.localServer.PVPSERVER ? 0.65f : 0.35f, 20.0f, 23.0f, 0.0f, 0.0f, 0.0f, 1.3f, 800, + new int[]{ItemList.animalHide, ItemList.tail, ItemList.eye, ItemList.gland, ItemList.tooth}, 40, 70, Materials.MATERIAL_MEAT_DRAGON); + + builder.skill(SkillList.BODY_STRENGTH, Servers.localServer.PVPSERVER ? 39f : 54f); + builder.skill(SkillList.BODY_STAMINA, 50.0f); + builder.skill(SkillList.BODY_CONTROL, 50.0f); + builder.skill(SkillList.MIND_LOGICAL, 50.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 50.0f); + builder.skill(SkillList.SOUL_DEPTH, 50.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 70.0f); + builder.skill(SkillList.GROUP_FIGHTING, 70.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("bite"); + builder.kickDamString("wingbuff"); + builder.maxAge(200); + builder.armourType(Servers.localServer.PVPSERVER ? ArmourTypes.ARMOUR_CLOTH : ArmourTypes.ARMOUR_SCALE_DRAGON); + builder.baseCombatRating(28.0f); + builder.combatDamageType(Wound.TYPE_PIERCE); + builder.maxGroupAttackSize(10); + + templateId = builder.getTemplateId(); + return builder; + } + + public ModVehicleBehaviour getVehicleBehaviour() { + + return new ModVehicleBehaviour() { + + @Override + public void setSettingsForVehicle(Item item, Vehicle vehicle) { + } + + @Override + public void setSettingsForVehicle(Creature creature, Vehicle v) { + VehicleFacade vehicle = wrap(v); + + vehicle.createPassengerSeats(0); + vehicle.setSeatFightMod(0, 0.8f, 1.1f); + vehicle.setSeatOffset(0, 0.2f, 0.0f, 0.0f); + vehicle.setCanHaveEquipment(true); + vehicle.setCreature(true); + vehicle.setSkillNeeded(30.0f); + vehicle.setName(creature.getName()); + vehicle.setMaxHeightDiff(0.15f); + vehicle.setMaxDepth(-50f); + vehicle.setMaxSpeed(51.0f); + vehicle.setCommandType((byte) 3); + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_SAND.id) + .addCreatures(templateId, 1) + .build(1); + + if(Servers.localServer.PVPSERVER){ + new EncounterBuilder(Tiles.Tile.TILE_GRASS.id) + .addCreatures(templateId, 1) + .build(1); + + new EncounterBuilder(Tiles.Tile.TILE_TREE.id) + .addCreatures(templateId, 1) + .build(1); + } + } +} diff --git a/src/main/java/mod/sin/creatures/WyvernGreen.java b/src/main/java/mod/sin/creatures/WyvernGreen.java new file mode 100644 index 0000000..88e5635 --- /dev/null +++ b/src/main/java/mod/sin/creatures/WyvernGreen.java @@ -0,0 +1,114 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviour; +import org.gotti.wurmunlimited.modsupport.vehicles.VehicleFacade; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Vehicle; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class WyvernGreen implements ModCreature, CreatureTypes { + public static int templateId; + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + int[] types = { + CreatureTypes.C_TYPE_HERBIVORE, + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_VEHICLE, + CreatureTypes.C_TYPE_REGENERATING, + CreatureTypes.C_TYPE_DOMINATABLE, + CreatureTypes.C_TYPE_SWIMMING, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_NON_NEWBIE, + CreatureTypes.C_TYPE_ANIMAL, + CreatureTypes.C_TYPE_GRAZER + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.wyvern.green", "Green wyvern", "A battle-hardened wyvern with scales as green as the leaves.", + "model.creature.drake.green", types, BodyTemplate.TYPE_DRAGON, (short) 10, (byte) 0, (short) 350, (short) 100, (short) 60, + "sound.death.dragon", "sound.death.dragon", "sound.combat.hit.dragon", "sound.combat.hit.dragon", + Servers.localServer.PVPSERVER ? 0.7f : 0.4f, 20.0f, 23.0f, 0.0f, 0.0f, 0.0f, 1.7f, 1500, + new int[]{ItemList.animalHide, ItemList.tail, ItemList.eye, ItemList.gland, ItemList.tooth}, 40, 70, Materials.MATERIAL_MEAT_DRAGON); + + builder.skill(SkillList.BODY_STRENGTH, Servers.localServer.PVPSERVER ? 40f : 55f); + builder.skill(SkillList.BODY_STAMINA, 50.0f); + builder.skill(SkillList.BODY_CONTROL, 50.0f); + builder.skill(SkillList.MIND_LOGICAL, 50.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 50.0f); + builder.skill(SkillList.SOUL_DEPTH, 50.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 70.0f); + builder.skill(SkillList.GROUP_FIGHTING, 70.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("bite"); + builder.kickDamString("wingbuff"); + builder.maxAge(200); + builder.armourType(Servers.localServer.PVPSERVER ? ArmourTypes.ARMOUR_CLOTH : ArmourTypes.ARMOUR_SCALE_DRAGON); + builder.baseCombatRating(27.0f); + builder.combatDamageType(Wound.TYPE_ACID); + builder.maxGroupAttackSize(10); + + templateId = builder.getTemplateId(); + return builder; + } + + public ModVehicleBehaviour getVehicleBehaviour() { + + return new ModVehicleBehaviour() { + + @Override + public void setSettingsForVehicle(Item item, Vehicle vehicle) { + } + + @Override + public void setSettingsForVehicle(Creature creature, Vehicle v) { + VehicleFacade vehicle = wrap(v); + + vehicle.createPassengerSeats(0); + vehicle.setSeatFightMod(0, 0.9f, 1.2f); + vehicle.setSeatOffset(0, 0.2f, 0.0f, 0.0f); + vehicle.setCanHaveEquipment(true); + vehicle.setCreature(true); + vehicle.setSkillNeeded(Servers.localServer.PVPSERVER ? 31f : 33f); + vehicle.setName(creature.getName()); + vehicle.setMaxHeightDiff(0.18f); + vehicle.setMaxDepth(-10f); + vehicle.setMaxSpeed(52.0f); + vehicle.setCommandType((byte) 3); + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_GRASS.id) + .addCreatures(templateId, 1) + .build(1); + + new EncounterBuilder(Tiles.Tile.TILE_TREE.id) + .addCreatures(templateId, 1) + .build(1); + } +} diff --git a/src/main/java/mod/sin/creatures/WyvernRed.java b/src/main/java/mod/sin/creatures/WyvernRed.java new file mode 100644 index 0000000..ce4c1f2 --- /dev/null +++ b/src/main/java/mod/sin/creatures/WyvernRed.java @@ -0,0 +1,110 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviour; +import org.gotti.wurmunlimited.modsupport.vehicles.VehicleFacade; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Vehicle; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class WyvernRed implements ModCreature, CreatureTypes { + public static int templateId; + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + int[] types = { + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_MOVE_GLOBAL, + CreatureTypes.C_TYPE_VEHICLE, + CreatureTypes.C_TYPE_REGENERATING, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_SWIMMING, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_DOMINATABLE, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.wyvern.red", "Red wyvern", "A battle-hardened wyvern with scales as red as fire.", + "model.creature.drake.red", types, BodyTemplate.TYPE_DRAGON, (short) 10, (byte) 0, (short) 350, (short) 100, (short) 60, + "sound.death.dragon", "sound.death.dragon", "sound.combat.hit.dragon", "sound.combat.hit.dragon", + Servers.localServer.PVPSERVER ? 0.6f : 0.17f, 22.0f, 25.0f, 0.0f, 0.0f, 0.0f, 1.4f, 900, + new int[]{ItemList.animalHide, ItemList.tail, ItemList.eye, ItemList.gland, ItemList.tooth}, 40, 70, Materials.MATERIAL_MEAT_DRAGON); + + builder.skill(SkillList.BODY_STRENGTH, Servers.localServer.PVPSERVER ? 37f : 52f); + builder.skill(SkillList.BODY_STAMINA, 50.0f); + builder.skill(SkillList.BODY_CONTROL, 50.0f); + builder.skill(SkillList.MIND_LOGICAL, 50.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 50.0f); + builder.skill(SkillList.SOUL_DEPTH, 50.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 75.0f); + builder.skill(SkillList.GROUP_FIGHTING, 75.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("bite"); + builder.kickDamString("wingbuff"); + builder.maxAge(200); + builder.armourType(Servers.localServer.PVPSERVER ? ArmourTypes.ARMOUR_LEATHER : ArmourTypes.ARMOUR_SCALE_DRAGON); + builder.baseCombatRating(30.0f); + builder.combatDamageType(Wound.TYPE_BURN); + builder.maxGroupAttackSize(10); + + templateId = builder.getTemplateId(); + return builder; + } + + public ModVehicleBehaviour getVehicleBehaviour() { + + return new ModVehicleBehaviour() { + + @Override + public void setSettingsForVehicle(Item item, Vehicle vehicle) { + } + + @Override + public void setSettingsForVehicle(Creature creature, Vehicle v) { + VehicleFacade vehicle = wrap(v); + + vehicle.createPassengerSeats(0); + vehicle.setSeatFightMod(0, 0.8f, 1.1f); + vehicle.setSeatOffset(0, 0.2f, 0.0f, 0.0f); + vehicle.setCreature(true); + vehicle.setSkillNeeded(Servers.localServer.PVPSERVER ? 35 : 43f); + vehicle.setName(creature.getName()); + vehicle.setMaxHeightDiff(Servers.localServer.PVPSERVER ? 0.15f : 0.10f); + vehicle.setMaxDepth(-50f); + vehicle.setMaxSpeed(50.0f); + vehicle.setCommandType((byte) 3); + vehicle.setCanHaveEquipment(true); + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_ROCK.id) + .addCreatures(templateId, 1) + .build(1); + } +} diff --git a/src/main/java/mod/sin/creatures/WyvernWhite.java b/src/main/java/mod/sin/creatures/WyvernWhite.java new file mode 100644 index 0000000..8982c41 --- /dev/null +++ b/src/main/java/mod/sin/creatures/WyvernWhite.java @@ -0,0 +1,117 @@ +package mod.sin.creatures; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.EncounterBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviour; +import org.gotti.wurmunlimited.modsupport.vehicles.VehicleFacade; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Servers; +import com.wurmonline.server.behaviours.Vehicle; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class WyvernWhite implements ModCreature, CreatureTypes { + public static int templateId; + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + int[] types = { + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_MOVE_GLOBAL, + CreatureTypes.C_TYPE_VEHICLE, + CreatureTypes.C_TYPE_REGENERATING, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_SWIMMING, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_DOMINATABLE, + CreatureTypes.C_TYPE_MONSTER, + CreatureTypes.C_TYPE_NON_NEWBIE, + CreatureTypes.C_TYPE_ANIMAL + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.wyvern.white", "White wyvern", "A battle-hardened wyvern with scales as white as the moon.", + "model.creature.drake.white", types, BodyTemplate.TYPE_DRAGON, (short) 10, (byte) 0, (short) 350, (short) 100, (short) 60, + "sound.death.dragon", "sound.death.dragon", "sound.combat.hit.dragon", "sound.combat.hit.dragon", + Servers.localServer.PVPSERVER ? 0.7f : 0.3f, 17.0f, 20.0f, 0.0f, 0.0f, 0.0f, 1.4f, 900, + new int[]{ItemList.animalHide, ItemList.tail, ItemList.eye, ItemList.gland, ItemList.tooth}, 40, 70, Materials.MATERIAL_MEAT_DRAGON); + + builder.skill(SkillList.BODY_STRENGTH, Servers.localServer.PVPSERVER ? 43f : 58f); + builder.skill(SkillList.BODY_STAMINA, 50.0f); + builder.skill(SkillList.BODY_CONTROL, 50.0f); + builder.skill(SkillList.MIND_LOGICAL, 50.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 50.0f); + builder.skill(SkillList.SOUL_DEPTH, 50.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 70.0f); + builder.skill(SkillList.GROUP_FIGHTING, 70.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("bite"); + builder.kickDamString("wingbuff"); + builder.maxAge(200); + builder.armourType(Servers.localServer.PVPSERVER ? ArmourTypes.ARMOUR_CLOTH : ArmourTypes.ARMOUR_SCALE_DRAGON); + builder.baseCombatRating(25.0f); + builder.combatDamageType(Wound.TYPE_COLD); + builder.maxGroupAttackSize(10); + + templateId = builder.getTemplateId(); + return builder; + } + + public ModVehicleBehaviour getVehicleBehaviour() { + + return new ModVehicleBehaviour() { + + @Override + public void setSettingsForVehicle(Item item, Vehicle vehicle) { + } + + @Override + public void setSettingsForVehicle(Creature creature, Vehicle v) { + VehicleFacade vehicle = wrap(v); + + vehicle.createPassengerSeats(0); + vehicle.setSeatFightMod(0, 0.8f, 1.1f); + vehicle.setSeatOffset(0, 0.2f, 0.0f, 0.0f); + vehicle.setCreature(true); + vehicle.setSkillNeeded(Servers.localServer.PVPSERVER ? 33f : 40f); + vehicle.setName(creature.getName()); + vehicle.setMaxHeightDiff(Servers.localServer.PVPSERVER ? 0.15f : 0.10f); + vehicle.setMaxDepth(-50f); + vehicle.setMaxSpeed(53.0f); + vehicle.setCommandType((byte) 3); + vehicle.setCanHaveEquipment(true); + } + }; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + + new EncounterBuilder(Tiles.Tile.TILE_SNOW.id) + .addCreatures(templateId, 1) + .build(1); + + if(Servers.localServer.PVPSERVER){ + new EncounterBuilder(Tiles.Tile.TILE_TUNDRA.id) + .addCreatures(templateId, 1) + .build(1); + } + } +} diff --git a/src/main/java/mod/sin/creatures/titans/Ifrit.java b/src/main/java/mod/sin/creatures/titans/Ifrit.java new file mode 100644 index 0000000..2fa2929 --- /dev/null +++ b/src/main/java/mod/sin/creatures/titans/Ifrit.java @@ -0,0 +1,70 @@ +package mod.sin.creatures.titans; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; + +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class Ifrit implements ModCreature, CreatureTypes { + public static int templateId; + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.raid.ifrit", "Ifrit", "A valiant warrior of the flame. You feel the presence of Magranon.", + "model.creature.humanoid.giant.juggernaut", types, BodyTemplate.TYPE_HUMAN, (short) 5, (byte) 0, (short) 350, (short) 100, (short) 60, + "sound.death.magranon.juggernaut", "sound.death.magranon.juggernaut", "sound.combat.hit.magranon.juggernaut", "sound.combat.hit.magranon.juggernaut", + 0.014f, 10.0f, 13.0f, 0.0f, 0.0f, 0.0f, 0.5f, 400, + new int[]{}, 40, 100, Materials.MATERIAL_MEAT_HUMANOID); + + builder.skill(SkillList.BODY_STRENGTH, 99.0f); + builder.skill(SkillList.BODY_STAMINA, 99.0f); + builder.skill(SkillList.BODY_CONTROL, 99.0f); + builder.skill(SkillList.MIND_LOGICAL, 99.0f); + builder.skill(SkillList.MIND_SPEED, 99.0f); + builder.skill(SkillList.SOUL_STRENGTH, 99.0f); + builder.skill(SkillList.SOUL_DEPTH, 99.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 99.0f); + builder.skill(SkillList.GROUP_FIGHTING, 99.0f); + builder.skill(SkillList.SCYTHE, 99.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("burn"); + builder.kickDamString("ignite"); + builder.maxAge(200); + builder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + builder.baseCombatRating(99.0f); + builder.combatDamageType(Wound.TYPE_BURN); + builder.maxGroupAttackSize(150); + + //builder.usesNewAttacks(true); + // float baseDamage, float criticalChance, float baseSpeed, int attackReach, int weightGroup, byte damageType, boolean usesWeapon, int rounds, float waitUntilNextAttack + //builder.addPrimaryAttack(new AttackAction("slashe", AttackIdentifier.STRIKE, new AttackValues(70f, 0.05f, 5f, 3, 1, Wound.TYPE_SLASH, false, 1, 1.0f))); + //builder.addPrimaryAttack(new AttackAction("eviscerate", AttackIdentifier.STRIKE, new AttackValues(100f, 0.5f, 30f, 3, 1, Wound.TYPE_INFECTION, false, 4, 5.0f))); + //builder.addSecondaryAttack(new AttackAction("annihilate", AttackIdentifier.KICK, new AttackValues(200f, 0.3f, 60f, 2, 1, Wound.TYPE_ACID, false, 7, 8.0f))); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + return; + } +} diff --git a/src/main/java/mod/sin/creatures/titans/IfritFiend.java b/src/main/java/mod/sin/creatures/titans/IfritFiend.java new file mode 100644 index 0000000..6a891b8 --- /dev/null +++ b/src/main/java/mod/sin/creatures/titans/IfritFiend.java @@ -0,0 +1,67 @@ +package mod.sin.creatures.titans; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class IfritFiend implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_DETECTINVIS, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.ifrit.fiend", "Fiend of Ifrit", "A champion of Ifrit.", + "model.creature.humanoid.lavacreature", types, BodyTemplate.TYPE_HUMAN, (short) 30, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.lizard", "sound.death.lizard", "sound.combat.hit.lizard", "sound.combat.hit.lizard", + 0.3f, 23f, 0f, 19f, 0.0f, 0.0f, 2.0f, 2000, + new int[]{}, 15, 70, Materials.MATERIAL_MEAT_HUMANOID); + + builder.skill(SkillList.BODY_STRENGTH, 55.0f); + builder.skill(SkillList.BODY_STAMINA, 65.0f); + builder.skill(SkillList.BODY_CONTROL, 60.0f); + builder.skill(SkillList.MIND_LOGICAL, 50.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 50.0f); + builder.skill(SkillList.SOUL_DEPTH, 50.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 50.0f); + builder.skill(SkillList.GROUP_FIGHTING, 40.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("burn"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_LEATHER_DRAGON); + builder.baseCombatRating(25.0f); + builder.combatDamageType(Wound.TYPE_BURN); + builder.maxPercentOfCreatures(0.005f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + } +} diff --git a/src/main/java/mod/sin/creatures/titans/IfritSpider.java b/src/main/java/mod/sin/creatures/titans/IfritSpider.java new file mode 100644 index 0000000..8a4cee4 --- /dev/null +++ b/src/main/java/mod/sin/creatures/titans/IfritSpider.java @@ -0,0 +1,67 @@ +package mod.sin.creatures.titans; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class IfritSpider implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_DETECTINVIS, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.ifrit.spider", "Servant of Ifrit", "A mindless minion of Ifrit.", + "model.creature.multiped.spider.lava", types, BodyTemplate.TYPE_SPIDER, (short) 30, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.spider", "sound.death.spider", "sound.combat.hit.spider", "sound.combat.hit.spider", + 0.5f, 15f, 0f, 13f, 0.0f, 0.0f, 1.7f, 1500, + new int[]{}, 15, 70, Materials.MATERIAL_MEAT_INSECT); + + builder.skill(SkillList.BODY_STRENGTH, 65.0f); + builder.skill(SkillList.BODY_STAMINA, 65.0f); + builder.skill(SkillList.BODY_CONTROL, 60.0f); + builder.skill(SkillList.MIND_LOGICAL, 50.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 50.0f); + builder.skill(SkillList.SOUL_DEPTH, 50.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 50.0f); + builder.skill(SkillList.GROUP_FIGHTING, 40.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("burn"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_CLOTH); + builder.baseCombatRating(15.0f); + builder.combatDamageType(Wound.TYPE_BURN); + builder.maxPercentOfCreatures(0.005f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + } +} diff --git a/src/main/java/mod/sin/creatures/titans/Lilith.java b/src/main/java/mod/sin/creatures/titans/Lilith.java new file mode 100644 index 0000000..80e49d3 --- /dev/null +++ b/src/main/java/mod/sin/creatures/titans/Lilith.java @@ -0,0 +1,70 @@ +package mod.sin.creatures.titans; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; + +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class Lilith implements ModCreature, CreatureTypes { + public static int templateId; + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.raid.lilith", "Lilith", "A bold warrior corrupted by darkness. You feel the presence of Libila.", + "model.creature.humanoid.giant.incarnation", types, BodyTemplate.TYPE_HUMAN, (short) 5, (byte) 1, (short) 350, (short) 100, (short) 60, + "sound.death.libila.incarnation", "sound.death.libila.incarnation", "sound.combat.hit.libila.incarnation", "sound.combat.hit.libila.incarnation", + 0.015f, 8.0f, 11.0f, 0.0f, 0.0f, 0.0f, 0.5f, 400, + new int[]{}, 40, 100, Materials.MATERIAL_MEAT_HUMANOID); + + builder.skill(SkillList.BODY_STRENGTH, 99.0f); + builder.skill(SkillList.BODY_STAMINA, 99.0f); + builder.skill(SkillList.BODY_CONTROL, 99.0f); + builder.skill(SkillList.MIND_LOGICAL, 99.0f); + builder.skill(SkillList.MIND_SPEED, 99.0f); + builder.skill(SkillList.SOUL_STRENGTH, 99.0f); + builder.skill(SkillList.SOUL_DEPTH, 99.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 99.0f); + builder.skill(SkillList.GROUP_FIGHTING, 99.0f); + builder.skill(SkillList.SCYTHE, 99.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("slashe"); + builder.kickDamString("eviscerate"); + builder.maxAge(200); + builder.armourType(ArmourTypes.ARMOUR_SCALE_DRAGON); + builder.baseCombatRating(99.0f); + builder.combatDamageType(Wound.TYPE_INFECTION); + builder.maxGroupAttackSize(150); + + //builder.usesNewAttacks(true); + // float baseDamage, float criticalChance, float baseSpeed, int attackReach, int weightGroup, byte damageType, boolean usesWeapon, int rounds, float waitUntilNextAttack + //builder.addPrimaryAttack(new AttackAction("slashe", AttackIdentifier.STRIKE, new AttackValues(70f, 0.05f, 5f, 3, 1, Wound.TYPE_SLASH, false, 1, 1.0f))); + //builder.addPrimaryAttack(new AttackAction("eviscerate", AttackIdentifier.STRIKE, new AttackValues(100f, 0.5f, 30f, 3, 1, Wound.TYPE_INFECTION, false, 4, 5.0f))); + //builder.addSecondaryAttack(new AttackAction("annihilate", AttackIdentifier.KICK, new AttackValues(200f, 0.3f, 60f, 2, 1, Wound.TYPE_ACID, false, 7, 8.0f))); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + return; + } +} diff --git a/src/main/java/mod/sin/creatures/titans/LilithWraith.java b/src/main/java/mod/sin/creatures/titans/LilithWraith.java new file mode 100644 index 0000000..f3dcab3 --- /dev/null +++ b/src/main/java/mod/sin/creatures/titans/LilithWraith.java @@ -0,0 +1,67 @@ +package mod.sin.creatures.titans; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class LilithWraith implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_DETECTINVIS, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.lilith.wraith", "Wraith of Lilith", "A champion of Lilith.", + "model.creature.humanoid.human.spirit.wraith", types, BodyTemplate.TYPE_HUMAN, (short) 30, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.spirit.male", "sound.death.spirit.female", "sound.combat.hit.spirit.male", "sound.combat.hit.spirit.female", + 0.3f, 23f, 0f, 19f, 0.0f, 0.0f, 2.0f, 2000, + new int[]{}, 15, 70, Materials.MATERIAL_MEAT_HUMANOID); + + builder.skill(SkillList.BODY_STRENGTH, 55.0f); + builder.skill(SkillList.BODY_STAMINA, 65.0f); + builder.skill(SkillList.BODY_CONTROL, 60.0f); + builder.skill(SkillList.MIND_LOGICAL, 50.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 50.0f); + builder.skill(SkillList.SOUL_DEPTH, 50.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 50.0f); + builder.skill(SkillList.GROUP_FIGHTING, 40.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("claw"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_LEATHER_DRAGON); + builder.baseCombatRating(25.0f); + builder.combatDamageType(Wound.TYPE_INFECTION); + builder.maxPercentOfCreatures(0.005f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + } +} diff --git a/src/main/java/mod/sin/creatures/titans/LilithZombie.java b/src/main/java/mod/sin/creatures/titans/LilithZombie.java new file mode 100644 index 0000000..e2cc95d --- /dev/null +++ b/src/main/java/mod/sin/creatures/titans/LilithZombie.java @@ -0,0 +1,67 @@ +package mod.sin.creatures.titans; + +import org.gotti.wurmunlimited.modsupport.CreatureTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.creatures.ModCreature; +import com.wurmonline.server.bodys.BodyTemplate; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.combat.ArmourTypes; +import com.wurmonline.server.creatures.CreatureTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class LilithZombie implements ModCreature, CreatureTypes { + public static int templateId; + + @Override + public CreatureTemplateBuilder createCreateTemplateBuilder() { + // {C_TYPE_MOVE_LOCAL, C_TYPE_VEHICLE, C_TYPE_ANIMAL, C_TYPE_LEADABLE, C_TYPE_GRAZER, C_TYPE_OMNIVORE, C_TYPE_DOMINATABLE, C_TYPE_AGG_HUMAN, C_TYPE_NON_NEWBIE, C_TYPE_BURNING}; - Hell Horse + // int[] types = new int[]{7, 6, 13, 3, 29, 39, 60, 61}; - Spider + int[] types = { + CreatureTypes.C_TYPE_MOVE_LOCAL, + CreatureTypes.C_TYPE_AGG_HUMAN, + CreatureTypes.C_TYPE_HUNTING, + CreatureTypes.C_TYPE_CARNIVORE, + CreatureTypes.C_TYPE_DETECTINVIS, + CreatureTypes.C_TYPE_NON_NEWBIE + }; + + //public CreatureTemplateBuilder(final String identifier, final String name, final String description, + // final String modelName, final int[] types, final byte bodyType, final short vision, final byte sex, final short centimetersHigh, final short centimetersLong, final short centimetersWide, + // final String deathSndMale, final String deathSndFemale, final String hitSndMale, final String hitSndFemale, + // final float naturalArmour, final float handDam, final float kickDam, final float biteDam, final float headDam, final float breathDam, final float speed, final int moveRate, + // final int[] itemsButchered, final int maxHuntDist, final int aggress) { + CreatureTemplateBuilder builder = new CreatureTemplateBuilder("mod.creature.lilith.zombie", "Servant of Lilith", "A mindless minion of Lilith.", + "model.creature.humanoid.human.player.zombie", types, BodyTemplate.TYPE_HUMAN, (short) 30, (byte) 0, (short) 85, (short) 50, (short) 85, + "sound.death.zombie", "sound.death.zombie", "sound.combat.hit.zombie", "sound.combat.hit.zombie", + 0.5f, 15f, 0f, 13f, 0.0f, 0.0f, 1.7f, 1500, + new int[]{}, 15, 70, Materials.MATERIAL_MEAT_HUMANOID); + + builder.skill(SkillList.BODY_STRENGTH, 65.0f); + builder.skill(SkillList.BODY_STAMINA, 65.0f); + builder.skill(SkillList.BODY_CONTROL, 60.0f); + builder.skill(SkillList.MIND_LOGICAL, 50.0f); + builder.skill(SkillList.MIND_SPEED, 50.0f); + builder.skill(SkillList.SOUL_STRENGTH, 50.0f); + builder.skill(SkillList.SOUL_DEPTH, 50.0f); + builder.skill(SkillList.WEAPONLESS_FIGHTING, 50.0f); + builder.skill(SkillList.GROUP_FIGHTING, 40.0f); + + builder.boundsValues(-0.5f, -1.0f, 0.5f, 1.42f); + builder.handDamString("claw"); + builder.maxAge(100); + builder.armourType(ArmourTypes.ARMOUR_CLOTH); + builder.baseCombatRating(15.0f); + builder.combatDamageType(Wound.TYPE_INFECTION); + builder.maxPercentOfCreatures(0.005f); + builder.maxGroupAttackSize(100); + + templateId = builder.getTemplateId(); + return builder; + } + + @Override + public void addEncounters() { + if (templateId == 0) + return; + } +} diff --git a/src/main/java/mod/sin/items/AffinityOrb.java b/src/main/java/mod/sin/items/AffinityOrb.java new file mode 100644 index 0000000..cae325e --- /dev/null +++ b/src/main/java/mod/sin/items/AffinityOrb.java @@ -0,0 +1,46 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class AffinityOrb implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(AffinityOrb.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "affinity orb"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("wyvern.affinityorb"); + itemBuilder.name(name, "affinity orbs", "A valuable orb that infuses the user with hidden knowledge."); + itemBuilder.descriptions("brilliantly glowing", "strongly glowing", "faintly glowing", "barely glowing"); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 919); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.artifact.orbdoom"); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_CRYSTAL); + itemBuilder.value(3000000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/ArenaCache.java b/src/main/java/mod/sin/items/ArenaCache.java new file mode 100644 index 0000000..47b7029 --- /dev/null +++ b/src/main/java/mod/sin/items/ArenaCache.java @@ -0,0 +1,45 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class ArenaCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(ArenaCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "arena cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.arenacache"); + itemBuilder.name(name, "arena caches", "A cache of goods from a supply depot, waiting to be opened. What could be inside?"); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(10000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/ArenaSupplyDepot.java b/src/main/java/mod/sin/items/ArenaSupplyDepot.java new file mode 100644 index 0000000..1ccf9af --- /dev/null +++ b/src/main/java/mod/sin/items/ArenaSupplyDepot.java @@ -0,0 +1,51 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class ArenaSupplyDepot implements MiscConstants { + public static Logger logger = Logger.getLogger(ArenaSupplyDepot.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "arena depot"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.arena.depot"); + itemBuilder.name(name, "arena depots", "Contains a valuable cache of treasures."); + // {108, 135, 1, 31, 25, 51, 86, 52, 59, 44, 147, 176, 180, 209, 199} + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_WOOD, + ItemTypes.ITEM_TYPE_NOTAKE, + ItemTypes.ITEM_TYPE_LOCKABLE, + ItemTypes.ITEM_TYPE_DECORATION, + ItemTypes.ITEM_TYPE_ONE_PER_TILE, + ItemTypes.ITEM_TYPE_OWNER_TURNABLE, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_MISSION, + ItemTypes.ITEM_TYPE_PLANTABLE + }); + itemBuilder.imageNumber((short) 462); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(300, 300, 300); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.structure.war.supplydepot.2.0."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(50000); + itemBuilder.material(Materials.MATERIAL_WOOD_BIRCH); + itemBuilder.value(5000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/ArrowPackHunting.java b/src/main/java/mod/sin/items/ArrowPackHunting.java new file mode 100644 index 0000000..9b200b3 --- /dev/null +++ b/src/main/java/mod/sin/items/ArrowPackHunting.java @@ -0,0 +1,62 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.AdvancedCreationEntry; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.CreationRequirement; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class ArrowPackHunting { + public static Logger logger = Logger.getLogger(ArrowPackHunting.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "hunting arrow pack"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.arrowpack.hunting"); + itemBuilder.name(name, "hunting arrow packs", "A pack of arrows, able to be unpacked into a full quiver."); + itemBuilder.descriptions("excellent", "good", "ok", "poor"); + itemBuilder.itemTypes(new short[]{ // {108, 146, 44, 21, 147, 113} - War Arrow + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_WOOD + }); + itemBuilder.imageNumber((short) 760); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(15, 15, 50); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.quiver."); + itemBuilder.difficulty(55.0f); + itemBuilder.weightGrams(2500); + itemBuilder.material(Materials.MATERIAL_WOOD_BIRCH); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + AdvancedCreationEntry huntingPack = CreationEntryCreator.createAdvancedEntry(SkillList.GROUP_FLETCHING, + ItemList.quiver, ItemList.arrowHunting, templateId, + false, false, 0.0F, true, false, 0, 50.0D, CreationCategories.FLETCHING); + + huntingPack.addRequirement(new CreationRequirement(1, ItemList.arrowHunting, 39, true)); + } + } +} diff --git a/src/main/java/mod/sin/items/ArrowPackWar.java b/src/main/java/mod/sin/items/ArrowPackWar.java new file mode 100644 index 0000000..caf5f16 --- /dev/null +++ b/src/main/java/mod/sin/items/ArrowPackWar.java @@ -0,0 +1,62 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.AdvancedCreationEntry; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.CreationRequirement; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class ArrowPackWar { + public static Logger logger = Logger.getLogger(ArrowPackWar.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "war arrow pack"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.arrowpack.war"); + itemBuilder.name(name, "war arrow packs", "A pack of arrows, able to be unpacked into a full quiver."); + itemBuilder.descriptions("excellent", "good", "ok", "poor"); + itemBuilder.itemTypes(new short[]{ // {108, 146, 44, 21, 147, 113} - War Arrow + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_WOOD + }); + itemBuilder.imageNumber((short) 760); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(15, 15, 50); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.quiver."); + itemBuilder.difficulty(55.0f); + itemBuilder.weightGrams(2500); + itemBuilder.material(Materials.MATERIAL_WOOD_BIRCH); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + AdvancedCreationEntry huntingPack = CreationEntryCreator.createAdvancedEntry(SkillList.GROUP_FLETCHING, + ItemList.quiver, ItemList.arrowWar, templateId, + false, false, 0.0F, true, false, 0, 50.0D, CreationCategories.FLETCHING); + + huntingPack.addRequirement(new CreationRequirement(1, ItemList.arrowWar, 39, true)); + } + } +} diff --git a/src/main/java/mod/sin/items/ChaosCrystal.java b/src/main/java/mod/sin/items/ChaosCrystal.java new file mode 100644 index 0000000..920103c --- /dev/null +++ b/src/main/java/mod/sin/items/ChaosCrystal.java @@ -0,0 +1,52 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class ChaosCrystal implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(ChaosCrystal.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + /* ItemTemplateCreatorContinued.createItemTemplate(737, "Valrei mission item", "items", "excellent", "good", "ok", "poor", + * "A weird item belonging on Valrei.", + * new short[]{32, 59, 147, 60}, + * 462, 1, 0, 86400, 3, 5, 50, -10, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.valrei.", 300.0f, 100, 21, 1, false); + */ + String name = "chaos crystal"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.chaoscrystal"); + itemBuilder.name(name, "chaos crystals", "This volatile crystal will either enhance an item, or destroy it outright."); + itemBuilder.descriptions("brilliantly glowing", "strongly glowing", "faintly glowing", "barely glowing"); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 462); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.valrei."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(250); + itemBuilder.material(Materials.MATERIAL_CRYSTAL); + itemBuilder.value(5000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/CoinDecoration.java b/src/main/java/mod/sin/items/CoinDecoration.java new file mode 100644 index 0000000..e78cf15 --- /dev/null +++ b/src/main/java/mod/sin/items/CoinDecoration.java @@ -0,0 +1,65 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.AdvancedCreationEntry; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.CreationRequirement; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class CoinDecoration implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(CoinDecoration.class.getName()); + public static int templateId; + private String name = "coin pile"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.coin.pile"); + itemBuilder.name(name, "coin piles", "A pile of decorative coins."); + itemBuilder.itemTypes(new short[]{ // {108, 21, 135, 86, 31, 51, 52, 157, 44, 92, 176} - Table + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_OWNER_DESTROYABLE, + ItemTypes.ITEM_TYPE_DESTROYABLE, + ItemTypes.ITEM_TYPE_TURNABLE, + ItemTypes.ITEM_TYPE_DECORATION, + ItemTypes.ITEM_TYPE_NOT_MISSION, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_COLORABLE + }); + itemBuilder.imageNumber((short) 572); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 5, 5); + itemBuilder.primarySkill(SkillList.MISCELLANEOUS); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.pile.coin."); + itemBuilder.difficulty(70.0f); + itemBuilder.weightGrams(1000); + itemBuilder.material(Materials.MATERIAL_COPPER); + itemBuilder.value(100); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.MISCELLANEOUS, + ItemList.coinCopper, ItemList.coinCopper, templateId, false, false, 0f, true, false, CreationCategories.DECORATION); + entry.addRequirement(new CreationRequirement(1, ItemList.coinCopper, 3, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/items/CorpseDecoration.java b/src/main/java/mod/sin/items/CorpseDecoration.java new file mode 100644 index 0000000..392df36 --- /dev/null +++ b/src/main/java/mod/sin/items/CorpseDecoration.java @@ -0,0 +1,65 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.AdvancedCreationEntry; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.CreationRequirement; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class CorpseDecoration implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(CorpseDecoration.class.getName()); + public static int templateId; + private String name = "human corpse"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.corpse"); + itemBuilder.name(name, "human corpses", "A human corpse."); + itemBuilder.itemTypes(new short[]{ // {108, 21, 135, 86, 31, 51, 52, 157, 44, 92, 176} - Table + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_OWNER_DESTROYABLE, + ItemTypes.ITEM_TYPE_DESTROYABLE, + ItemTypes.ITEM_TYPE_TURNABLE, + ItemTypes.ITEM_TYPE_DECORATION, + ItemTypes.ITEM_TYPE_NOT_MISSION, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_COLORABLE + }); + itemBuilder.imageNumber((short) 40); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(20, 50, 200); + itemBuilder.primarySkill(SkillList.LEATHERWORKING); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.corpse."); + itemBuilder.difficulty(50.0f); + itemBuilder.weightGrams(50000); + itemBuilder.material(Materials.MATERIAL_FLESH); + itemBuilder.value(1000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.LEATHERWORKING, + ItemList.leather, ItemList.leather, templateId, false, false, 0f, true, false, CreationCategories.DECORATION); + entry.addRequirement(new CreationRequirement(1, ItemList.leather, 3, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/items/DepthDrill.java b/src/main/java/mod/sin/items/DepthDrill.java new file mode 100644 index 0000000..1d450e4 --- /dev/null +++ b/src/main/java/mod/sin/items/DepthDrill.java @@ -0,0 +1,62 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.AdvancedCreationEntry; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.CreationRequirement; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class DepthDrill implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(DepthDrill.class.getName()); + public static int templateId; + private String name = "depth drill"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("wyvern.depthdrill"); + itemBuilder.name(name, "depth drills", "A tool for determining dirt depth."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_TOOL, + ItemTypes.ITEM_TYPE_WEAPON_PIERCE + }); + itemBuilder.imageNumber((short) 60); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(6, 6, 96); + itemBuilder.primarySkill(SkillList.CARPENTRY_FINE); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.resource.shaft."); + itemBuilder.difficulty(30.0f); + itemBuilder.weightGrams(1100); + itemBuilder.material(Materials.MATERIAL_IRON); + itemBuilder.value(100); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.CARPENTRY_FINE, + ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info("Depth Drill does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/items/DisintegrationRod.java b/src/main/java/mod/sin/items/DisintegrationRod.java new file mode 100644 index 0000000..ae39eb3 --- /dev/null +++ b/src/main/java/mod/sin/items/DisintegrationRod.java @@ -0,0 +1,43 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class DisintegrationRod implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(DisintegrationRod.class.getName()); + public static int templateId; + public void createTemplate() throws IOException{ + String name = "Rod of Disintegration"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("item.mod.rod.disintegration"); + itemBuilder.name(name, "rods of disintegration", "A rod designed for removal of ore veins and cave walls."); + itemBuilder.itemTypes(new short[]{ // {42, 53, 127, 155} - Rod of Transmutation {43, 42, 5, 76, 53, 127} - Sleep Powder + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 1259); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 60); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.tool.rodtrans."); + itemBuilder.difficulty(300.0f); + itemBuilder.weightGrams(1000); + itemBuilder.material(Materials.MATERIAL_STONE); + itemBuilder.value(50000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/EnchantOrb.java b/src/main/java/mod/sin/items/EnchantOrb.java new file mode 100644 index 0000000..80b2d47 --- /dev/null +++ b/src/main/java/mod/sin/items/EnchantOrb.java @@ -0,0 +1,43 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; + +public class EnchantOrb implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(EnchantOrb.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "enchant orb"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("wyvern.enchantorb"); + itemBuilder.name(name, "enchant orbs", "It shimmers lightly, the magic inside waiting for a proper vessel."); + itemBuilder.descriptions("vibrant", "glowing", "faint", "empty"); + itemBuilder.itemTypes(new short[]{ + ITEM_TYPE_MAGIC, + ITEM_TYPE_INDESTRUCTIBLE + }); + itemBuilder.imageNumber((short) 819); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.artifact.orbdoom"); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material((byte)52); + itemBuilder.value(50000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/EnchantersCrystal.java b/src/main/java/mod/sin/items/EnchantersCrystal.java new file mode 100644 index 0000000..4967cb5 --- /dev/null +++ b/src/main/java/mod/sin/items/EnchantersCrystal.java @@ -0,0 +1,52 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class EnchantersCrystal implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(EnchantersCrystal.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + /* ItemTemplateCreatorContinued.createItemTemplate(737, "Valrei mission item", "items", "excellent", "good", "ok", "poor", + * "A weird item belonging on Valrei.", + * new short[]{32, 59, 147, 60}, + * 462, 1, 0, 86400, 3, 5, 50, -10, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.valrei.", 300.0f, 100, 21, 1, false); + */ + String name = "enchanters crystal"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.crystal.enchanters"); + itemBuilder.name(name, "enchanters crystals", "This crystal can manipulate the magical properties of an item."); + itemBuilder.descriptions("brilliantly glowing", "strongly glowing", "faintly glowing", "barely glowing"); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 462); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.valrei."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(250); + itemBuilder.material(Materials.MATERIAL_CRYSTAL); + itemBuilder.value(5000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/EternalReservoir.java b/src/main/java/mod/sin/items/EternalReservoir.java new file mode 100644 index 0000000..fead21b --- /dev/null +++ b/src/main/java/mod/sin/items/EternalReservoir.java @@ -0,0 +1,72 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.AdvancedCreationEntry; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.CreationRequirement; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class EternalReservoir implements ItemTypes, MiscConstants { + protected static Logger logger = Logger.getLogger(EternalReservoir.class.getName()); + public static int templateId; + public void createTemplate() throws IOException{ + String name = "eternal reservoir"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.eternal.reservoir"); + itemBuilder.name(name, "eternal reservoir", "Fueled by the souls of the fallen, this black magic device stores souls that tend to nearby creatures and fires."); + itemBuilder.itemTypes(new short[]{ // {25, 49, 31, 52, 40} Stone of Soulfall {108, 31, 25, 194, 52, 44, 195, 67, 49, 123, 178, 157} // Colossus + ItemTypes.ITEM_TYPE_STONE, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_NOTAKE, + ItemTypes.ITEM_TYPE_DECORATION, + ItemTypes.ITEM_TYPE_USE_GROUND_ONLY, + ItemTypes.ITEM_TYPE_NEVER_SHOW_CREATION_WINDOW_OPTION, + ItemTypes.ITEM_TYPE_NOT_MISSION + }); + itemBuilder.imageNumber((short) 60); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(500, 500, 1000); + itemBuilder.primarySkill((int)MiscConstants.NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.structure.rift.altar.1."); + itemBuilder.difficulty(50.0f); + itemBuilder.weightGrams(200000); + itemBuilder.material(Materials.MATERIAL_STONE); + itemBuilder.value(10000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + AdvancedCreationEntry massStorage = CreationEntryCreator.createAdvancedEntry(SkillList.POTTERY, + ItemList.diamondStar, ItemList.dirtPile, templateId, + false, false, 0.0F, true, true, 0, 0.0D, CreationCategories.ALTAR); + + massStorage.addRequirement(new CreationRequirement(1, ItemList.dirtPile, 99, true)); + massStorage.addRequirement(new CreationRequirement(2, ItemList.brickPottery, 200, true)); + massStorage.addRequirement(new CreationRequirement(3, ItemList.peat, 50, true)); + massStorage.addRequirement(new CreationRequirement(4, ChaosCrystal.templateId, 50, true)); + massStorage.addRequirement(new CreationRequirement(5, ItemList.heart, 20, true)); + massStorage.addRequirement(new CreationRequirement(6, ItemList.emerald, 5, true)); + massStorage.addRequirement(new CreationRequirement(7, ItemList.diamond, 5, true)); + massStorage.addRequirement(new CreationRequirement(8, ItemList.opal, 5, true)); + massStorage.addRequirement(new CreationRequirement(9, ItemList.sapphire, 5, true)); + massStorage.addRequirement(new CreationRequirement(10, ItemList.ruby, 5, true)); + } + } +} diff --git a/src/main/java/mod/sin/items/FriyanTablet.java b/src/main/java/mod/sin/items/FriyanTablet.java new file mode 100644 index 0000000..1c071e4 --- /dev/null +++ b/src/main/java/mod/sin/items/FriyanTablet.java @@ -0,0 +1,48 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class FriyanTablet implements ItemTypes, MiscConstants { + protected static Logger logger = Logger.getLogger(FriyanTablet.class.getName()); + public static int templateId; + public void createTemplate() throws IOException{ + String name = "Tablet of Friyan"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.tablet.friyan"); + itemBuilder.name(name, "tablets of friyan", "Once a great scholar and sorceress, Friyan's faith had reached the zenith. While in this world, she wrote her knowledge in tablets like these. Perhaps you may learn more of the gods from it..."); + itemBuilder.itemTypes(new short[]{ // {25, 49, 31, 52, 40} Stone of Soulfall {108, 31, 25, 194, 52, 44, 195, 67, 49, 123, 178, 157} // Colossus + ItemTypes.ITEM_TYPE_STONE, + ItemTypes.ITEM_TYPE_OUTSIDE_ONLY, + ItemTypes.ITEM_TYPE_NOTAKE, + ItemTypes.ITEM_TYPE_DECORATION, + ItemTypes.ITEM_TYPE_INDESTRUCTIBLE, + ItemTypes.ITEM_TYPE_USE_GROUND_ONLY, + ItemTypes.ITEM_TYPE_NOMOVE, + ItemTypes.ITEM_TYPE_NEVER_SHOW_CREATION_WINDOW_OPTION, + ItemTypes.ITEM_TYPE_NOT_MISSION + }); + itemBuilder.imageNumber((short) 60); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(500, 500, 1000); + itemBuilder.primarySkill((int)MiscConstants.NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.structure.portal.10."); + itemBuilder.difficulty(99.0f); + itemBuilder.weightGrams(2000000); + itemBuilder.material(Materials.MATERIAL_STONE); + itemBuilder.value(10000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/HugeCrate.java b/src/main/java/mod/sin/items/HugeCrate.java new file mode 100644 index 0000000..a8fa8e4 --- /dev/null +++ b/src/main/java/mod/sin/items/HugeCrate.java @@ -0,0 +1,68 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.AdvancedCreationEntry; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.CreationRequirement; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class HugeCrate implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(HugeCrate.class.getName()); + public static int templateId; + public void createTemplate() throws IOException{ + String name = "huge crate"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.crate.huge"); + itemBuilder.name(name, "huge crates", "A huge crate made from planks, primarily used to transport goods."); + itemBuilder.itemTypes(new short[]{ // {108, 135, 167, 21, 51, 52, 44, 1, 92, 145, 176} - large crate + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_OWNER_DESTROYABLE, + ItemTypes.ITEM_TYPE_WOOD, + ItemTypes.ITEM_TYPE_TURNABLE, + ItemTypes.ITEM_TYPE_DECORATION, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_HOLLOW, + ItemTypes.ITEM_TYPE_COLORABLE, + ItemTypes.ITEM_TYPE_BULKCONTAINER, + ItemTypes.ITEM_TYPE_TRANSPORTABLE + }); + itemBuilder.imageNumber((short) 311); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(9072000); + itemBuilder.dimensions(140, 140, 140); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.crate.large."); + itemBuilder.difficulty(70.0f); + itemBuilder.weightGrams(20000); + itemBuilder.material(Materials.MATERIAL_WOOD_BIRCH); + itemBuilder.value(10000); + itemBuilder.isTraded(false); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+ templateId); + } + + public void initCreationEntry() { + logger.info("initCreationEntry()"); + if (templateId > 0) { + logger.info("Creating Huge Crate creation entry, ID = "+templateId); + final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.CARPENTRY_FINE, + ItemList.plank, ItemList.nailsIronLarge, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + entry.addRequirement(new CreationRequirement(1, ItemList.plank, 20, true)); + } else { + logger.info("Huge Crate does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/items/MassStorageBehaviour.java b/src/main/java/mod/sin/items/MassStorageBehaviour.java new file mode 100644 index 0000000..424c0e1 --- /dev/null +++ b/src/main/java/mod/sin/items/MassStorageBehaviour.java @@ -0,0 +1,54 @@ +package mod.sin.items; + +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviour; +import org.gotti.wurmunlimited.modsupport.vehicles.VehicleFacade; + +import com.wurmonline.server.behaviours.Seat; +import com.wurmonline.server.behaviours.Vehicle; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; + +public class MassStorageBehaviour extends ModVehicleBehaviour { + public static Logger logger = Logger.getLogger(MassStorageBehaviour.class.getName()); + public void setSettingsForVehicle(final Creature creature, final Vehicle vehicle){ + // Empty + } + /*public void setSettingsForVehicle(final Item item, final Vehicle v){ + logger.info("Setting vehicle behaviour for item "+item.getTemplate().getTemplateId()); + + // Vehicle facade to access: + VehicleFacade vehicle = wrap(v); + vehicle.createPassengerSeats(1); + vehicle.setCommandType((byte)1); + vehicle.setCreature(false); + vehicle.setSeatFightMod(0, 0.9f, 0.9f); + vehicle.setSeatOffset(0, 0.0f, 0.0f, 0.246f); + vehicle.setSkillNeeded(19.0f); + }*/ + public void setSettingsForVehicle(final Item item, final Vehicle v) { + logger.info("Setting vehicle behaviour for item "+item.getTemplate().getTemplateId()); + /* + * Vehicle has some protected fields. The facade will deal with those. + */ + VehicleFacade vehicle = wrap(v); + vehicle.createPassengerSeats(0); + vehicle.setSeatFightMod(0, 0.7f, 0.4f); + vehicle.setSeatOffset(0, 0f, 1.5f, -0.2f); + vehicle.setCreature(false); + vehicle.setEmbarkString("enter"); + vehicle.setName(item.getName()); + vehicle.setMaxDepth(9000f); + vehicle.setMaxHeightDiff(0.00f); + vehicle.setCommandType((byte)2); + + /* + * The Seat constructor is protected too. createSeat() will handle that + */ + final Seat[] hitches = { createSeat(Seat.TYPE_HITCHED) }; + hitches[0].offx = 3.0f; + hitches[0].offy = 0.0f; + vehicle.addHitchSeats(hitches); + } +} diff --git a/src/main/java/mod/sin/items/MassStorageUnit.java b/src/main/java/mod/sin/items/MassStorageUnit.java new file mode 100644 index 0000000..64fba79 --- /dev/null +++ b/src/main/java/mod/sin/items/MassStorageUnit.java @@ -0,0 +1,87 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; +import org.gotti.wurmunlimited.modsupport.vehicles.ModVehicleBehaviours; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.AdvancedCreationEntry; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.CreationRequirement; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class MassStorageUnit implements ItemTypes { + private static Logger logger = Logger.getLogger(MassStorageUnit.class.getName()); + public static int templateId; + private String name = "mass storage unit"; + + public void createTemplate() throws IOException{ + ModVehicleBehaviours.init(); + ItemTemplateBuilder builder = new ItemTemplateBuilder("mod.item.mass.storage"); + builder.name(name, "mass storage units", "A massive storage unit able to be loaded with containers."); + builder.descriptions("almost full", "somewhat occupied", "half-full", "emptyish"); + builder.itemTypes(new short[] { + ITEM_TYPE_WOOD, + ITEM_TYPE_NOTAKE, + ITEM_TYPE_REPAIRABLE, + ITEM_TYPE_TURNABLE, + ITEM_TYPE_DECORATION, + ITEM_TYPE_DESTROYABLE, + ITEM_TYPE_ONE_PER_TILE, + ITEM_TYPE_LOCKABLE, + ITEM_TYPE_HOLLOW, + ITEM_TYPE_VEHICLE, + ITEM_TYPE_IMPROVEITEM, + ITEM_TYPE_OWNER_DESTROYABLE, + ItemTypes.ITEM_TYPE_USES_SPECIFIED_CONTAINER_VOLUME, + ITEM_TYPE_OWNER_TURNABLE, + ITEM_TYPE_CART, + ITEM_TYPE_OWNER_MOVEABLE + }); + builder.imageNumber((short) 60); + builder.behaviourType((short) 41); + builder.combatDamage(0); + builder.decayTime(9072000L); + builder.dimensions(400, 300, 1000); + builder.primarySkill(-10); + builder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + builder.modelName("model.furniture.wooden.storageunit."); + //builder.size(3); + + builder.difficulty(80.0F); + builder.weightGrams(300000); + builder.material(Materials.MATERIAL_WOOD_BIRCH); + + ItemTemplate template = builder.build(); + templateId = template.getTemplateId(); + template.setContainerSize(300, 300, 600); + + MassStorageBehaviour massStorageBehaviour = new MassStorageBehaviour(); + ModVehicleBehaviours.addItemVehicle(templateId, massStorageBehaviour); + //KingdomWagonBehaviour kingdomWagonBehaviour = new KingdomWagonBehaviour(); + //ModVehicleBehaviours.addItemVehicle(resultTemplate.getTemplateId(), kingdomWagonBehaviour); + + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + AdvancedCreationEntry massStorage = CreationEntryCreator.createAdvancedEntry(SkillList.CARPENTRY_FINE, + ItemList.woodBeam, ItemList.woodBeam, templateId, + false, false, 0.0F, true, true, 0, 70.0D, CreationCategories.STORAGE); + + massStorage.addRequirement(new CreationRequirement(1, ItemList.plank, 500, true)); + massStorage.addRequirement(new CreationRequirement(2, ItemList.shaft, 200, true)); + massStorage.addRequirement(new CreationRequirement(3, ItemList.ironBand, 50, true)); + massStorage.addRequirement(new CreationRequirement(4, ItemList.nailsIronLarge, 100, true)); + } + } +} diff --git a/src/main/java/mod/sin/items/SealedMap.java b/src/main/java/mod/sin/items/SealedMap.java new file mode 100644 index 0000000..c4f8aef --- /dev/null +++ b/src/main/java/mod/sin/items/SealedMap.java @@ -0,0 +1,45 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class SealedMap implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(SealedMap.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "sealed map"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.sealed.map"); + itemBuilder.name(name, "sealed map", "A sealed treasure map, waiting to be opened."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_FULLPRICE, // Not actually full price, the hook for value works before this is applied. This ensures coins are used. + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 640); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_MAGIC); + itemBuilder.value(5000000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/SkeletonDecoration.java b/src/main/java/mod/sin/items/SkeletonDecoration.java new file mode 100644 index 0000000..2fed3f2 --- /dev/null +++ b/src/main/java/mod/sin/items/SkeletonDecoration.java @@ -0,0 +1,62 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class SkeletonDecoration implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(SkeletonDecoration.class.getName()); + public static int templateId; + private String name = "skeleton"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.skeleton"); + itemBuilder.name(name, "skeletons", "A skeleton."); + itemBuilder.itemTypes(new short[]{ // {108, 21, 135, 86, 31, 51, 52, 157, 44, 92, 176} - Table + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_OWNER_DESTROYABLE, + ItemTypes.ITEM_TYPE_DESTROYABLE, + ItemTypes.ITEM_TYPE_TURNABLE, + ItemTypes.ITEM_TYPE_DECORATION, + ItemTypes.ITEM_TYPE_NOT_MISSION, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_COLORABLE + }); + itemBuilder.imageNumber((short) 40); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(20, 50, 200); + itemBuilder.primarySkill(SkillList.BUTCHERING); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.corpse.human.butchered."); + itemBuilder.difficulty(90.0f); + itemBuilder.weightGrams(50000); + itemBuilder.material(Materials.MATERIAL_FLESH); + itemBuilder.value(1000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.BUTCHERING, ItemList.knifeButchering, 22760, + templateId, false, true, 0f, false, false, CreationCategories.DECORATION); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/items/Soul.java b/src/main/java/mod/sin/items/Soul.java new file mode 100644 index 0000000..478d708 --- /dev/null +++ b/src/main/java/mod/sin/items/Soul.java @@ -0,0 +1,45 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class Soul implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(Soul.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "soul"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.soul"); + itemBuilder.name(name, "souls", "The captured soul of a creature."); + itemBuilder.descriptions("brilliantly glowing", "strongly glowing", "faintly glowing", "barely glowing"); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 859); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.valrei."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(250); + itemBuilder.material(Materials.MATERIAL_CRYSTAL); + itemBuilder.value(5000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/StatuetteBreyk.java b/src/main/java/mod/sin/items/StatuetteBreyk.java new file mode 100644 index 0000000..8f8614b --- /dev/null +++ b/src/main/java/mod/sin/items/StatuetteBreyk.java @@ -0,0 +1,68 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class StatuetteBreyk implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(StatuetteBreyk.class.getName()); + public static int templateId; + private String name = "statuette of Breyk"; + public void createTemplate() throws IOException{ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.statuette.breyk"); + itemBuilder.name(name, "statuettes", "A statuette resembling the artists interpretation of the deity Breyk."); + itemBuilder.itemTypes(new short[]{ // {108, 52, 22, 44, 87, 92, 147} - Statuette + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_DECORATION, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_MATERIAL_PRICEEFFECT, + ItemTypes.ITEM_TYPE_COLORABLE, + ItemTypes.ITEM_TYPE_MISSION + }); + itemBuilder.imageNumber((short) 282); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(3, 5, 20); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.decoration.statuette.fo."); + itemBuilder.difficulty(40.0f); + itemBuilder.weightGrams(1000); + itemBuilder.material(Materials.MATERIAL_SILVER); + itemBuilder.value(20000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_GOLDSMITHING, ItemList.anvilSmall, ItemList.silverBar, + templateId, false, true, 0.0f, false, false, CreationCategories.STATUETTES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_GOLDSMITHING, ItemList.anvilSmall, ItemList.goldBar, + templateId, false, true, 0.0f, false, false, CreationCategories.STATUETTES); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/items/StatuetteCyberhusky.java b/src/main/java/mod/sin/items/StatuetteCyberhusky.java new file mode 100644 index 0000000..1923f25 --- /dev/null +++ b/src/main/java/mod/sin/items/StatuetteCyberhusky.java @@ -0,0 +1,68 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +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"; + 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.itemTypes(new short[]{ // {108, 52, 22, 44, 87, 92, 147} - Statuette + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_DECORATION, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_MATERIAL_PRICEEFFECT, + ItemTypes.ITEM_TYPE_COLORABLE, + ItemTypes.ITEM_TYPE_MISSION + }); + itemBuilder.imageNumber((short) 282); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(3, 5, 20); + itemBuilder.primarySkill(-10); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.decoration.statuette.magranon."); + itemBuilder.difficulty(40.0f); + itemBuilder.weightGrams(1000); + itemBuilder.material(Materials.MATERIAL_SILVER); + itemBuilder.value(20000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_GOLDSMITHING, ItemList.anvilSmall, ItemList.silverBar, + templateId, false, true, 0.0f, false, false, CreationCategories.STATUETTES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_GOLDSMITHING, ItemList.anvilSmall, ItemList.goldBar, + templateId, false, true, 0.0f, false, false, CreationCategories.STATUETTES); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/items/TreasureBox.java b/src/main/java/mod/sin/items/TreasureBox.java new file mode 100644 index 0000000..982c368 --- /dev/null +++ b/src/main/java/mod/sin/items/TreasureBox.java @@ -0,0 +1,46 @@ +package mod.sin.items; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class TreasureBox implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(TreasureBox.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "treasure box"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.treasurebox"); + itemBuilder.name(name, "treasure boxes", "A box of treasure, waiting to be opened. What could be inside?"); + itemBuilder.descriptions("brilliantly glowing", "strongly glowing", "faintly glowing", "barely glowing"); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(10000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/AnimalCache.java b/src/main/java/mod/sin/items/caches/AnimalCache.java new file mode 100644 index 0000000..7d84274 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/AnimalCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class AnimalCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(AnimalCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "animal cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.animal"); + itemBuilder.name(name, "animal caches", "A cache containing a tokened animal. It might even be a unique creature."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/ArmourCache.java b/src/main/java/mod/sin/items/caches/ArmourCache.java new file mode 100644 index 0000000..6d94bc0 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/ArmourCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class ArmourCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(ArmourCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "armour cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.armour"); + itemBuilder.name(name, "armour caches", "A cache of armour. This armour may contain special properties."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/ArtifactCache.java b/src/main/java/mod/sin/items/caches/ArtifactCache.java new file mode 100644 index 0000000..25746e8 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/ArtifactCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class ArtifactCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(ArtifactCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "artifact cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.artifact"); + itemBuilder.name(name, "artifact caches", "A cache containing a special artifact."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/CrystalCache.java b/src/main/java/mod/sin/items/caches/CrystalCache.java new file mode 100644 index 0000000..256ee17 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/CrystalCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class CrystalCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(CrystalCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "crystal cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.crystal"); + itemBuilder.name(name, "crystal caches", "A cache of magical crystals."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/DragonCache.java b/src/main/java/mod/sin/items/caches/DragonCache.java new file mode 100644 index 0000000..505b8a5 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/DragonCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class DragonCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(DragonCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "dragon cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.dragon"); + itemBuilder.name(name, "dragon caches", "A cache of dragon material. May also contain drake hide or dragonscale armour."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/GemCache.java b/src/main/java/mod/sin/items/caches/GemCache.java new file mode 100644 index 0000000..e954de7 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/GemCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class GemCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(GemCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "gem cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.gem"); + itemBuilder.name(name, "gem caches", "A cache of gems. May also contain star gems."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/MoonCache.java b/src/main/java/mod/sin/items/caches/MoonCache.java new file mode 100644 index 0000000..cb31ce5 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/MoonCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class MoonCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(MoonCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "moon cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.moon"); + itemBuilder.name(name, "moon caches", "A cache of moon metals. May also contain items created from moon metals."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/PotionCache.java b/src/main/java/mod/sin/items/caches/PotionCache.java new file mode 100644 index 0000000..1a8d662 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/PotionCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class PotionCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(PotionCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "potion cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.potion"); + itemBuilder.name(name, "potion caches", "A cache of potions."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/RiftCache.java b/src/main/java/mod/sin/items/caches/RiftCache.java new file mode 100644 index 0000000..bc9f5bd --- /dev/null +++ b/src/main/java/mod/sin/items/caches/RiftCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class RiftCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(RiftCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "rift cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.rift"); + itemBuilder.name(name, "rift caches", "A cache of rift material."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/ToolCache.java b/src/main/java/mod/sin/items/caches/ToolCache.java new file mode 100644 index 0000000..81f3943 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/ToolCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class ToolCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(ToolCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "tool cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.tool"); + itemBuilder.name(name, "tool caches", "A cache containing a few tools. These tools could have special properties."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/TreasureMapCache.java b/src/main/java/mod/sin/items/caches/TreasureMapCache.java new file mode 100644 index 0000000..8a2ca67 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/TreasureMapCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class TreasureMapCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(TreasureMapCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "treasure map cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.treasure.map"); + itemBuilder.name(name, "treasure map caches", "A cache containing a new treasure map."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/items/caches/WeaponCache.java b/src/main/java/mod/sin/items/caches/WeaponCache.java new file mode 100644 index 0000000..73531f7 --- /dev/null +++ b/src/main/java/mod/sin/items/caches/WeaponCache.java @@ -0,0 +1,45 @@ +package mod.sin.items.caches; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; + +public class WeaponCache implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(WeaponCache.class.getName()); + public static int templateId; + + public void createTemplate() throws IOException{ + String name = "weapon cache"; + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.cache.weapon"); + itemBuilder.name(name, "weapon caches", "A cache containing a few weapons. These weapons could have special properties."); + itemBuilder.itemTypes(new short[]{ + ItemTypes.ITEM_TYPE_MAGIC, + ItemTypes.ITEM_TYPE_FULLPRICE, + ItemTypes.ITEM_TYPE_NOSELLBACK, + ItemTypes.ITEM_TYPE_ALWAYS_BANKABLE + }); + itemBuilder.imageNumber((short) 243); + itemBuilder.behaviourType((short) 1); + itemBuilder.combatDamage(0); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(1, 1, 1); + itemBuilder.primarySkill((int) NOID); + itemBuilder.bodySpaces(EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.container.giftbox."); + itemBuilder.difficulty(5.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_GOLD); + itemBuilder.value(1000); + itemBuilder.isTraded(true); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/weapons/BattleYoyo.java b/src/main/java/mod/sin/weapons/BattleYoyo.java new file mode 100644 index 0000000..4b9fab9 --- /dev/null +++ b/src/main/java/mod/sin/weapons/BattleYoyo.java @@ -0,0 +1,70 @@ +package mod.sin.weapons; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class BattleYoyo implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(BattleYoyo.class.getName()); + public static int templateId; + private String name = "battle yoyo"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(337, + * "Hammer of Magranon", "hammers of magranon", "excellent", "good", "ok", "poor", + * "A huge brutal warhammer made totally from bronze.", + * new short[]{52, 48, 69, 37, 14, 40, 71}, + * 1339, 35, 80, Long.MAX_VALUE, 5, 10, 80, 10070, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.artifact.hammerhuge.", 99.0f, 7000, 31, 3000000, false); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.battle.yoyo"); + itemBuilder.name(name, "battle yoyos", "A reinforced yoyo meant for combat. Designed to see whether walking the dog is an effective murder technique."); + itemBuilder.itemTypes(new short[]{ // new short[]{108, 44, 147, 22, 37, 14, 189} - Large Maul + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_WOOD, + ItemTypes.ITEM_TYPE_WEAPON, + ItemTypes.ITEM_TYPE_WEAPON_CRUSH + }); + itemBuilder.imageNumber((short) 761); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(35); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.YOYO); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.toy.yoyo."); + itemBuilder.difficulty(40.0f); + itemBuilder.weightGrams(1000); + itemBuilder.material(Materials.MATERIAL_WOOD_BIRCH); + itemBuilder.value(1000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.TOYMAKING, ItemList.clothString, ItemList.shaft, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPONS); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/weapons/Club.java b/src/main/java/mod/sin/weapons/Club.java new file mode 100644 index 0000000..7a66b42 --- /dev/null +++ b/src/main/java/mod/sin/weapons/Club.java @@ -0,0 +1,70 @@ +package mod.sin.weapons; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class Club implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(Club.class.getName()); + public static int templateId; + private String name = "club"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(337, + * "Hammer of Magranon", "hammers of magranon", "excellent", "good", "ok", "poor", + * "A huge brutal warhammer made totally from bronze.", + * new short[]{52, 48, 69, 37, 14, 40, 71}, + * 1339, 35, 80, Long.MAX_VALUE, 5, 10, 80, 10070, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.artifact.hammerhuge.", 99.0f, 7000, 31, 3000000, false); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.club"); + itemBuilder.name(name, "clubs", "A blunt weapon."); + itemBuilder.itemTypes(new short[]{ // new short[]{108, 44, 147, 22, 37, 14, 189} - Large Maul + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_WOOD, + ItemTypes.ITEM_TYPE_WEAPON, + ItemTypes.ITEM_TYPE_WEAPON_CRUSH + }); + itemBuilder.imageNumber((short) 1239); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(35); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.CLUB_HUGE); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.weapon.club.huge."); + itemBuilder.difficulty(40.0f); + itemBuilder.weightGrams(8000); + itemBuilder.material(Materials.MATERIAL_WOOD_BIRCH); + itemBuilder.value(1000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.CARPENTRY_FINE, ItemList.knifeCarving, ItemList.log, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPONS); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/weapons/Eviscerator.java b/src/main/java/mod/sin/weapons/Eviscerator.java new file mode 100644 index 0000000..cd86230 --- /dev/null +++ b/src/main/java/mod/sin/weapons/Eviscerator.java @@ -0,0 +1,71 @@ +package mod.sin.weapons; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +import mod.sin.weapons.titan.WilhelmsWrath; + +public class Eviscerator implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(Eviscerator.class.getName()); + public static int templateId; + private String name = "eviscerator"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(337, + * "Hammer of Magranon", "hammers of magranon", "excellent", "good", "ok", "poor", + * "A huge brutal warhammer made totally from bronze.", + * new short[]{52, 48, 69, 37, 14, 40, 71}, + * 1339, 35, 80, Long.MAX_VALUE, 5, 10, 80, 10070, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.artifact.hammerhuge.", 99.0f, 7000, 31, 3000000, false); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.eviscerator"); + itemBuilder.name(name, "eviscerators", "A one-handed scythe of despair, optimal for the Genocide of entire species."); + itemBuilder.itemTypes(new short[]{ // new short[]{108, 44, 147, 22, 37, 14, 189} - Large Maul + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_WEAPON, + ItemTypes.ITEM_TYPE_WEAPON_SLASH + }); + itemBuilder.imageNumber((short) 753); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.SCYTHE); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.weapon.scythe."); + itemBuilder.difficulty(90.0f); + itemBuilder.weightGrams(500); + itemBuilder.material(Materials.MATERIAL_ADAMANTINE); + itemBuilder.value(1000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.GROUP_SMITHING_WEAPONSMITHING, WilhelmsWrath.templateId, WilhelmsWrath.templateId, + templateId, true, true, 0.0f, false, false, CreationCategories.WEAPONS); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/weapons/Knuckles.java b/src/main/java/mod/sin/weapons/Knuckles.java new file mode 100644 index 0000000..6e11a61 --- /dev/null +++ b/src/main/java/mod/sin/weapons/Knuckles.java @@ -0,0 +1,80 @@ +package mod.sin.weapons; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class Knuckles implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(Knuckles.class.getName()); + public static int templateId; + private String name = "knuckles"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(337, + * "Hammer of Magranon", "hammers of magranon", "excellent", "good", "ok", "poor", + * "A huge brutal warhammer made totally from bronze.", + * new short[]{52, 48, 69, 37, 14, 40, 71}, + * 1339, 35, 80, Long.MAX_VALUE, 5, 10, 80, 10070, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.artifact.hammerhuge.", 99.0f, 7000, 31, 3000000, false); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.knuckles"); + itemBuilder.name(name, "knuckles", "A classic weapon used in hand-to-hand combat."); + itemBuilder.itemTypes(new short[]{ // new short[]{108, 44, 147, 22, 37, 14, 189} - Large Maul + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_WEAPON, + ItemTypes.ITEM_TYPE_WEAPON_CRUSH + }); + itemBuilder.imageNumber((short) 60); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.WEAPONLESS_FIGHTING); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.decoration.ring.rift.2."); + itemBuilder.difficulty(40.0f); + itemBuilder.weightGrams(800); + itemBuilder.material(Materials.MATERIAL_BRASS); + itemBuilder.value(1000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.GROUP_SMITHING_WEAPONSMITHING, ItemList.anvilSmall, ItemList.brassBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPONS); + CreationEntryCreator.createSimpleEntry(SkillList.GROUP_SMITHING_WEAPONSMITHING, ItemList.anvilSmall, ItemList.ironBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPONS); + CreationEntryCreator.createSimpleEntry(SkillList.GROUP_SMITHING_WEAPONSMITHING, ItemList.anvilSmall, ItemList.steelBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPONS); + CreationEntryCreator.createSimpleEntry(SkillList.GROUP_SMITHING_WEAPONSMITHING, ItemList.anvilSmall, ItemList.adamantineBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPONS); + CreationEntryCreator.createSimpleEntry(SkillList.GROUP_SMITHING_WEAPONSMITHING, ItemList.anvilSmall, ItemList.glimmerSteelBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPONS); + CreationEntryCreator.createSimpleEntry(SkillList.GROUP_SMITHING_WEAPONSMITHING, ItemList.anvilSmall, ItemList.seryllBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPONS); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/weapons/Warhammer.java b/src/main/java/mod/sin/weapons/Warhammer.java new file mode 100644 index 0000000..e6af453 --- /dev/null +++ b/src/main/java/mod/sin/weapons/Warhammer.java @@ -0,0 +1,72 @@ +package mod.sin.weapons; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +import mod.sin.weapons.heads.WarhammerHead; + +public class Warhammer implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(Warhammer.class.getName()); + public static int templateId; + private String name = "warhammer"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(337, + * "Hammer of Magranon", "hammers of magranon", "excellent", "good", "ok", "poor", + * "A huge brutal warhammer made totally from bronze.", + * new short[]{52, 48, 69, 37, 14, 40, 71}, + * 1339, 35, 80, Long.MAX_VALUE, 5, 10, 80, 10070, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.artifact.hammerhuge.", 99.0f, 7000, 31, 3000000, false); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.warhammer"); + itemBuilder.name(name, "warhammers", "A warhammer."); + itemBuilder.itemTypes(new short[]{ // new short[]{108, 44, 147, 22, 37, 14, 189} - Large Maul + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_WEAPON, + ItemTypes.ITEM_TYPE_WEAPON_CRUSH + }); + itemBuilder.imageNumber((short) 1339); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.WARHAMMER); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.artifact.hammerhuge."); + itemBuilder.difficulty(35.0f); + itemBuilder.weightGrams(7000); + itemBuilder.material(Materials.MATERIAL_IRON); + itemBuilder.value(1000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.GROUP_SMITHING_WEAPONSMITHING, ItemList.shaft, WarhammerHead.templateId, + templateId, true, true, 0.0f, false, false, CreationCategories.WEAPONS); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/weapons/heads/WarhammerHead.java b/src/main/java/mod/sin/weapons/heads/WarhammerHead.java new file mode 100644 index 0000000..f2b520d --- /dev/null +++ b/src/main/java/mod/sin/weapons/heads/WarhammerHead.java @@ -0,0 +1,74 @@ +package mod.sin.weapons.heads; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.CreationCategories; +import com.wurmonline.server.items.CreationEntryCreator; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class WarhammerHead implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(WarhammerHead.class.getName()); + public static int templateId; + private String name = "warhammer head"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(293, 4, + * "maul head", "large maul heads", "excellent", "good", "ok", "poor", + * "The thick, heavy, spiked metal head for a maul.", + * new short[]{44, 22}, 1232, 1, 0, 3024000, 20, 20, 20, -10, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.weapon.head.large.maul.", 15.0f, 4000, 11, 100, false, -1); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.warhammer.head"); + itemBuilder.name(name, "warhammer heads", "A warhammer head."); + itemBuilder.itemTypes(new short[]{ // new short[]{44, 22} - Large Maul Head + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_METAL + }); + itemBuilder.imageNumber((short) 1232); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.WARHAMMER); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.artifact.hammerhuge."); + itemBuilder.difficulty(25.0f); + itemBuilder.weightGrams(6000); + itemBuilder.material(Materials.MATERIAL_IRON); + itemBuilder.value(1000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } + + public void initCreationEntry(){ + logger.info("initCreationEntry()"); + if(templateId > 0){ + logger.info("Creating "+name+" creation entry, ID = "+templateId); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_HEADS, ItemList.anvilLarge, ItemList.ironBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPON_HEADS); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_HEADS, ItemList.anvilLarge, ItemList.steelBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPON_HEADS); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_HEADS, ItemList.anvilLarge, ItemList.adamantineBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPON_HEADS); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_HEADS, ItemList.anvilLarge, ItemList.glimmerSteelBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPON_HEADS); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_HEADS, ItemList.anvilLarge, ItemList.seryllBar, + templateId, false, true, 0.0f, false, false, CreationCategories.WEAPON_HEADS); + //final AdvancedCreationEntry entry = CreationEntryCreator.createAdvancedEntry(SkillList.SMITHING_WEAPON_HEADS, + // ItemList.ironBand, ItemList.shaft, templateId, false, false, 0f, true, false, CreationCategories.TOOLS); + //entry.addRequirement(new CreationRequirement(1, ItemList.woodenHandleSword, 2, true)); + //entry.addRequirement(new CreationRequirement(2, ItemList.nailsIronSmall, 1, true)); + }else{ + logger.info(name+" does not have a template ID on creation entry."); + } + } +} diff --git a/src/main/java/mod/sin/weapons/titan/MaartensMight.java b/src/main/java/mod/sin/weapons/titan/MaartensMight.java new file mode 100644 index 0000000..0a7e6f7 --- /dev/null +++ b/src/main/java/mod/sin/weapons/titan/MaartensMight.java @@ -0,0 +1,52 @@ +package mod.sin.weapons.titan; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class MaartensMight implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(MaartensMight.class.getName()); + public static int templateId; + private String name = "Maarten's Might"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(337, + * "Hammer of Magranon", "hammers of magranon", "excellent", "good", "ok", "poor", + * "A huge brutal warhammer made totally from bronze.", + * new short[]{52, 48, 69, 37, 14, 40, 71}, + * 1339, 35, 80, Long.MAX_VALUE, 5, 10, 80, 10070, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.artifact.hammerhuge.", 99.0f, 7000, 31, 3000000, false); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.titan.maarten.might"); + itemBuilder.name(name, "Maarten's Mights", "Extracted from a mine just outside Valhalla, this warhammer cannot be blocked."); + itemBuilder.itemTypes(new short[]{ // new short[]{108, 44, 147, 22, 37, 14, 189} - Large Maul + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_WEAPON, + ItemTypes.ITEM_TYPE_WEAPON_CRUSH + }); + itemBuilder.imageNumber((short) 1339); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.WARHAMMER); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.artifact.hammerhuge."); + itemBuilder.difficulty(90.0f); + itemBuilder.weightGrams(100); + itemBuilder.material(Materials.MATERIAL_GLIMMERSTEEL); + itemBuilder.value(1000000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/weapons/titan/RaffehsRage.java b/src/main/java/mod/sin/weapons/titan/RaffehsRage.java new file mode 100644 index 0000000..dd42838 --- /dev/null +++ b/src/main/java/mod/sin/weapons/titan/RaffehsRage.java @@ -0,0 +1,52 @@ +package mod.sin.weapons.titan; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class RaffehsRage implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(RaffehsRage.class.getName()); + public static int templateId; + private String name = "Raffeh's Rage"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(337, + * "Hammer of Magranon", "hammers of magranon", "excellent", "good", "ok", "poor", + * "A huge brutal warhammer made totally from bronze.", + * new short[]{52, 48, 69, 37, 14, 40, 71}, + * 1339, 35, 80, Long.MAX_VALUE, 5, 10, 80, 10070, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.artifact.hammerhuge.", 99.0f, 7000, 31, 3000000, false); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.titan.raffeh.rage"); + itemBuilder.name(name, "Raffeh's Rages", "A melding of ice and fire from the champion of Kaen Ist, this maul is an elemental maelstrom."); + itemBuilder.itemTypes(new short[]{ // new short[]{108, 44, 147, 22, 37, 14, 189} - Large Maul + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_WEAPON, + ItemTypes.ITEM_TYPE_WEAPON_CRUSH + }); + itemBuilder.imageNumber((short) 1213); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.MAUL_MEDIUM); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.weapon.maul.medium."); + itemBuilder.difficulty(90.0f); + itemBuilder.weightGrams(100); + itemBuilder.material(Materials.MATERIAL_GLIMMERSTEEL); + itemBuilder.value(1000000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/weapons/titan/VindictivesVengeance.java b/src/main/java/mod/sin/weapons/titan/VindictivesVengeance.java new file mode 100644 index 0000000..e0b9040 --- /dev/null +++ b/src/main/java/mod/sin/weapons/titan/VindictivesVengeance.java @@ -0,0 +1,52 @@ +package mod.sin.weapons.titan; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class VindictivesVengeance implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(VindictivesVengeance.class.getName()); + public static int templateId; + private String name = "Vindictive's Vengeance"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(337, + * "Hammer of Magranon", "hammers of magranon", "excellent", "good", "ok", "poor", + * "A huge brutal warhammer made totally from bronze.", + * new short[]{52, 48, 69, 37, 14, 40, 71}, + * 1339, 35, 80, Long.MAX_VALUE, 5, 10, 80, 10070, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.artifact.hammerhuge.", 99.0f, 7000, 31, 3000000, false); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.titan.vindictive.vengeance"); + itemBuilder.name(name, "Vindictive Vengeances", "A sickle as light as a feather, capable of swinging as swiftly as the user can wield it."); + itemBuilder.itemTypes(new short[]{ // new short[]{108, 44, 147, 22, 37, 14, 189} - Large Maul + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_WEAPON, + ItemTypes.ITEM_TYPE_WEAPON_SLASH + }); + itemBuilder.imageNumber((short) 752); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.SICKLE); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.weapon.sickle."); + itemBuilder.difficulty(90.0f); + itemBuilder.weightGrams(100); + itemBuilder.material(Materials.MATERIAL_ADAMANTINE); + itemBuilder.value(1000000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/weapons/titan/WilhelmsWrath.java b/src/main/java/mod/sin/weapons/titan/WilhelmsWrath.java new file mode 100644 index 0000000..385d8f7 --- /dev/null +++ b/src/main/java/mod/sin/weapons/titan/WilhelmsWrath.java @@ -0,0 +1,52 @@ +package mod.sin.weapons.titan; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.ItemTemplateBuilder; + +import com.wurmonline.server.MiscConstants; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTypes; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.skills.SkillList; + +public class WilhelmsWrath implements ItemTypes, MiscConstants { + public static Logger logger = Logger.getLogger(WilhelmsWrath.class.getName()); + public static int templateId; + private String name = "Wilhelm's Wrath"; + public void createTemplate() throws IOException{ + /* ItemTemplateCreator.createItemTemplate(337, + * "Hammer of Magranon", "hammers of magranon", "excellent", "good", "ok", "poor", + * "A huge brutal warhammer made totally from bronze.", + * new short[]{52, 48, 69, 37, 14, 40, 71}, + * 1339, 35, 80, Long.MAX_VALUE, 5, 10, 80, 10070, MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY, + * "model.artifact.hammerhuge.", 99.0f, 7000, 31, 3000000, false); + */ + ItemTemplateBuilder itemBuilder = new ItemTemplateBuilder("mod.item.titan.wilhelm.wrath"); + itemBuilder.name(name, "Wilhelm's Wraths", "A magnificent one-handed scythe, hand-crafted by Libila for her favoured champion, Wilhelm. To achieve it's full potential, one must wield it in combat."); + itemBuilder.itemTypes(new short[]{ // new short[]{108, 44, 147, 22, 37, 14, 189} - Large Maul + ItemTypes.ITEM_TYPE_NAMED, + ItemTypes.ITEM_TYPE_METAL, + ItemTypes.ITEM_TYPE_REPAIRABLE, + ItemTypes.ITEM_TYPE_WEAPON, + ItemTypes.ITEM_TYPE_WEAPON_SLASH + }); + itemBuilder.imageNumber((short) 753); + itemBuilder.behaviourType((short) 35); + itemBuilder.combatDamage(40); + itemBuilder.decayTime(Long.MAX_VALUE); + itemBuilder.dimensions(5, 10, 80); + itemBuilder.primarySkill(SkillList.SCYTHE); + itemBuilder.bodySpaces(MiscConstants.EMPTY_BYTE_PRIMITIVE_ARRAY); + itemBuilder.modelName("model.weapon.scythe."); + itemBuilder.difficulty(90.0f); + itemBuilder.weightGrams(1000); + itemBuilder.material(Materials.MATERIAL_ADAMANTINE); + itemBuilder.value(1000000); + + ItemTemplate template = itemBuilder.build(); + templateId = template.getTemplateId(); + logger.info(name+" TemplateID: "+templateId); + } +} diff --git a/src/main/java/mod/sin/wyvern/AntiCheat.java b/src/main/java/mod/sin/wyvern/AntiCheat.java new file mode 100644 index 0000000..33def52 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/AntiCheat.java @@ -0,0 +1,230 @@ +package mod.sin.wyvern; + +import java.nio.ByteBuffer; +import java.util.Set; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modloader.ReflectionUtil; +import org.gotti.wurmunlimited.modloader.classhooks.HookException; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Constants; +import com.wurmonline.server.Features; +import com.wurmonline.server.Server; +import com.wurmonline.server.creatures.Communicator; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.ai.NoPathException; +import com.wurmonline.server.creatures.ai.Path; +import com.wurmonline.server.creatures.ai.PathFinder; +import com.wurmonline.server.creatures.ai.PathTile; +import com.wurmonline.server.zones.Water; +import com.wurmonline.server.zones.Zones; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; + +public class AntiCheat { + private static Logger logger = Logger.getLogger(AntiCheat.class.getName()); + private static final int emptyRock = Tiles.encode((short)-100, (byte)Tiles.Tile.TILE_CAVE_WALL.id, (byte)0); + private static boolean isCaveWall(int xx, int yy){ + if (xx < 0 || xx >= Zones.worldTileSizeX || yy < 0 || yy >= Zones.worldTileSizeY) { + return true; + } else if (Tiles.isSolidCave((byte)Tiles.decodeType((int)Server.caveMesh.data[xx | yy << Constants.meshSize]))) { + return true; + } + return false; + } + private static boolean isSurroundedByCaveWalls(int tilex, int tiley){ + int xx = tilex+1; + int yy = tiley; + if(!isCaveWall(xx, yy)){ + return false; + } + xx = tilex-1; + if(!isCaveWall(xx, yy)){ + return false; + } + xx = tilex; + yy = tiley+1; + if(!isCaveWall(xx, yy)){ + return false; + } + yy = tiley-1; + if(!isCaveWall(xx, yy)){ + return false; + } + return true; + } + private static int getDummyWallAntiCheat(int tilex, int tiley){ + return Tiles.encode((short)Tiles.decodeHeight((int)Server.caveMesh.data[tilex | tiley << Constants.meshSize]), (byte)Tiles.Tile.TILE_CAVE_WALL.id, (byte)Tiles.decodeData((int)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()) { + try { + ByteBuffer bb = comm.getConnection().getBuffer(); + bb.put((byte) 102); + bb.put((byte) (Features.Feature.CAVEWATER.isEnabled() ? 1 : 0)); + bb.put((byte) (comm.player.isSendExtraBytes() ? 1 : 0)); + bb.putShort(xStart); + bb.putShort(yStart); + bb.putShort((short)width); + bb.putShort((short)height); + boolean onSurface = comm.player.isOnSurface(); + for (int x = 0; x < width; ++x) { + for (int y = 0; y < height; ++y) { + int xx = xStart + x; + int yy = yStart + y; + if (xx < 0 || xx >= Zones.worldTileSizeX || yy < 0 || yy >= Zones.worldTileSizeY) { + bb.putInt(emptyRock); + xx = 0; + yy = 0; + } else if (!onSurface) { + if(!(Tiles.decodeType((int)Server.caveMesh.getTile(xx, yy)) == Tiles.Tile.TILE_CAVE_EXIT.id) && isSurroundedByCaveWalls(xx, yy)){ + bb.putInt(getDummyWallAntiCheat(xx, yy)); + }else{ + bb.putInt(Server.caveMesh.data[xx | yy << Constants.meshSize]); + } + } else if (Tiles.isSolidCave((byte)Tiles.decodeType((int)Server.caveMesh.data[xx | yy << Constants.meshSize]))) { + bb.putInt(getDummyWallAntiCheat(xx, yy)); + } else { + bb.putInt(Server.caveMesh.data[xx | yy << Constants.meshSize]); + } + if (Features.Feature.CAVEWATER.isEnabled()) { + bb.putShort((short)Water.getCaveWater(xx, yy)); + } + if (!comm.player.isSendExtraBytes()) continue; + bb.put(Server.getClientCaveFlags(xx, yy)); + } + } + comm.getConnection().flush(); + } + catch (Exception ex) { + comm.player.setLink(false); + } + } + } + public static boolean isVisibleThroughTerrain(Creature performer, Creature defender){ + int trees = 0; + //int treetilex = -1; + //int treetiley = -1; + //int tileArrowDownX = -1; + //int tileArrowDownY = -1; + PathFinder pf = new PathFinder(true); + try { + Path path = pf.rayCast(performer.getCurrentTile().tilex, performer.getCurrentTile().tiley, defender.getCurrentTile().tilex, defender.getCurrentTile().tiley, performer.isOnSurface(), ((int)Creature.getRange(performer, defender.getPosX(), defender.getPosY()) >> 2) + 5); + float initialHeight = Math.max(-1.4f, performer.getPositionZ() + performer.getAltOffZ() + 1.4f); + float targetHeight = Math.max(-1.4f, defender.getPositionZ() + defender.getAltOffZ() + 1.4f); + double distx = Math.pow(performer.getCurrentTile().tilex - defender.getCurrentTile().tilex, 2.0); + double disty = Math.pow(performer.getCurrentTile().tiley - defender.getCurrentTile().tiley, 2.0); + double dist = Math.sqrt(distx + disty); + double dx = (double)(targetHeight - initialHeight) / dist; + while (!path.isEmpty()) { + PathTile p = path.getFirst(); + if(Tiles.getTile((byte)Tiles.decodeType((int)p.getTile())).isTree()){ + trees++; + } + /*if (Tiles.getTile((byte)Tiles.decodeType((int)p.getTile())).isTree() && treetilex == -1 && Server.rand.nextInt(10) < ++trees) { + treetilex = p.getTileX(); + treetiley = p.getTileY(); + }*/ + distx = Math.pow(p.getTileX() - defender.getCurrentTile().tilex, 2.0); + disty = Math.pow(p.getTileY() - defender.getCurrentTile().tiley, 2.0); + double currdist = Math.sqrt(distx + disty); + float currHeight = Math.max(-1.4f, Zones.getLowestCorner(p.getTileX(), p.getTileY(), performer.getLayer())); + double distmod = currdist * dx; + if (dx < 0.0) { + if ((double)currHeight > (double)targetHeight - distmod) { + return false; + } + } else if ((double)currHeight > (double)targetHeight - distmod) { + return false; + } + /*if (tileArrowDownX == -1 && Server.rand.nextInt(15) == 0) { + tileArrowDownX = p.getTileX(); + tileArrowDownY = p.getTileY(); + }*/ + path.removeFirst(); + } + if(trees >= 8){ + return false; + } + } + catch (NoPathException np) { + performer.getCommunicator().sendCombatNormalMessage("You fail to get a clear shot."); + return false; + } + return true; + } + public static boolean isVisibleToAntiCheat(Creature cret, Creature watcher) { + if (!cret.isVisible()) { + return cret.getPower() > 0 && cret.getPower() <= watcher.getPower(); + } + if (cret.isStealth()) { + if (cret.getPower() > 0 && cret.getPower() <= watcher.getPower()) { + return true; + } + if (cret.getPower() < watcher.getPower()) { + return true; + } + if (watcher.isUnique() || watcher.isDetectInvis()) { + return true; + } + Set stealthBreakers = null; + try { + stealthBreakers = ReflectionUtil.getPrivateField(cret, ReflectionUtil.getField(cret.getClass(), "stealthBreakers")); + } catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + logger.info("Failed to get stealthBreakers for creature "+cret.getName()); + e.printStackTrace(); + } + if (stealthBreakers != null && stealthBreakers.contains(watcher.getWurmId())) { + return true; + } + return false; + } + if(WyvernMods.espCounter && watcher.isPlayer()){ + if(cret.isPlayer() || cret.getLeader() != null || cret.isRidden() || cret.isUnique()){ + if(cret.isWithinDistanceTo(watcher, 120)){ + return true; + } + if(isVisibleThroughTerrain(cret, watcher)){ + return true; + } + return false; + } + } + return true; + } + public static void preInit(){ + try{ + ClassPool classPool = HookManager.getInstance().getClassPool(); + + // - 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"); + ctCommunicator.getDeclaredMethod("sendCaveStrip").setBody("{" + + " mod.sin.wyvern.AntiCheat.sendCaveStripAntiCheat(this, $$);" + + "}"); + + // - 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"); + ctCreature.getDeclaredMethod("isVisibleTo").setBody("{" + + " return mod.sin.wyvern.AntiCheat.isVisibleToAntiCheat(this, $$);" + + "}"); + + // - Edit VirtualZone creature movement so that it removes units that the player cannot see - // + CtClass ctVirtualZone = classPool.get("com.wurmonline.server.zones.VirtualZone"); + ctVirtualZone.getDeclaredMethod("coversCreature").insertBefore("" + + "if(!this.covers($1.getTileX(), $1.getTileY())){" + + " return false;" + + "}" + + "if(!mod.sin.wyvern.AntiCheat.isVisibleToAntiCheat($1, this.watcher)){" + + " return false;" + + "}"); + + } catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { + throw new HookException((Throwable)e); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/Bounty.java b/src/main/java/mod/sin/wyvern/Bounty.java new file mode 100644 index 0000000..5985f98 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/Bounty.java @@ -0,0 +1,244 @@ +package mod.sin.wyvern; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modloader.ReflectionUtil; +import org.gotti.wurmunlimited.modloader.classhooks.HookException; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; + +import com.wurmonline.server.Server; +import com.wurmonline.server.creatures.Creature; + +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import javassist.bytecode.Descriptor; +import mod.sin.lib.Util; +import mod.sin.wyvern.bestiary.MethodsBestiary; +import mod.sin.wyvern.bounty.LootBounty; +import mod.sin.wyvern.bounty.PlayerBounty; + +public class Bounty { + public static final Logger logger = Logger.getLogger(Bounty.class.getName()); + //protected static WyvernMods mod; + public static HashMap reward = new HashMap(); + + // Using a hook in CombatEngine.addWound, we call this function to create a list of creatures that actually inflicted damage. + public static HashMap> dealtDamage = new HashMap>(); + public static void addDealtDamage(long defender, long attacker, double damage){ + if(dealtDamage.containsKey(defender)){ + Map dealers = dealtDamage.get(defender); + if(!dealers.containsKey(attacker)){ + dealers.put(attacker, damage); + }else{ + double newDam = dealers.get(attacker); + newDam += damage; + dealers.put(attacker, newDam); + } + }else{ + Map dealers = new HashMap(); + dealers.put(attacker, damage); + dealtDamage.put(defender, dealers); + } + } + + public static long lastAttacked(Map attackers, long playerId){ + return System.currentTimeMillis()-attackers.get(playerId); + } + + public static boolean isCombatant(Map attackers, long playerId){ + long now = System.currentTimeMillis(); + long delta = now-attackers.get(playerId); + if(delta > 120000){ + return false; + } + return true; + } + + public static Map getAttackers(Creature mob){ + try { + return ReflectionUtil.getPrivateField(mob, ReflectionUtil.getField(mob.getClass(), "attackers")); + } catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + return null; + } + + public static double getCreatureStrength(Creature mob){ + float combatRating = mob.getBaseCombatRating() + mob.getBonusCombatRating(); + float maxDmg = Math.max(mob.getTemplate().getBreathDamage(), mob.getHandDamage()); + maxDmg = Math.max(maxDmg, mob.getBiteDamage()); + maxDmg = Math.max(maxDmg, mob.getKickDamage()); + maxDmg = Math.max(maxDmg, mob.getHeadButtDamage()); + double fighting = mob.getFightingSkill().getKnowledge(); + double weaponlessFighting = mob.getWeaponLessFightingSkill().getKnowledge(); + double fs = Math.max(fighting, weaponlessFighting); + double bodyStr = mob.getBodyStrength().getKnowledge(); + double cretStr = 2000D + ((double)combatRating*(double)maxDmg*Math.sqrt(fs)*bodyStr); + //logger.info("pre-armour: "+cretStr); + //cretStr /= Math.max(mob.getArmourMod(), 0.001d); + fs /= mob.getArmourMod(); + cretStr = 500D + ((double)combatRating*Math.cbrt(maxDmg)*Math.sqrt(fs)*Math.cbrt(bodyStr)); + cretStr *= 2d; + //logger.info("post-armour: "+cretStr); + //cretStr *= 1-(Math.min(Math.max(mob.getArmourMod(), 0.001d), 0.8f)); + //cretStr = 2000D + ((double)combatRating*(double)maxDmg*Math.sqrt(fs)*bodyStr); + double k = 100000000d; + cretStr = (cretStr*Math.pow(2, (-(cretStr/k)))+k*(1-Math.pow(2, -cretStr/k)))/(1+Math.pow(2, -cretStr/k)); + if(cretStr < 500D){ + cretStr *= 1+(Server.rand.nextFloat()*0.2f); + cretStr = Math.max(cretStr, 500D); + } + //logger.info("capped: "+cretStr); + return cretStr; + } + + /*public static void preInit(WyvernMods mod){ + Bounty.mod = mod; + //reward.put("black wolf", 750); + }*/ + + public static void init(){ + try { + ClassPool classPool = HookManager.getInstance().getClassPool(); + final Class thisClass = Bounty.class; + + CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); + + /*CtMethod ctCheckBounty = CtMethod.make((String) + "public void checkBounty(com.wurmonline.server.players.Player player, com.wurmonline.server.creatures.Creature mob){" + + " if(!mod.sin.wyvernmods.bounty.MethodsBounty.isCombatant(this.attackers, player.getWurmId()) || mob.isPlayer() || mob.isReborn()){" + + " return;" + + " }" + + (mod.bDebug ? "logger.info(player.getName()+\" killed \"+mob.getName());" : "") + + " mod.sin.wyvernmods.bounty.MethodsBounty.checkPlayerReward(player, mob);" + + "}", ctCreature); + ctCreature.addMethod(ctCheckBounty);*/ + String replace; + replace = "" + //+ "mod.sin.wyvern.bounty.MethodsBounty.checkBounty(player, this);" + + PlayerBounty.class.getName()+".checkPlayerBounty(player, this);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkCoinAward", replace); + /*ctCreature.getDeclaredMethod("modifyFightSkill").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("checkCoinAward")) { + m.replace("mod.sin.wyvern.bounty.MethodsBounty.checkBounty(player, this);" + + "$_ = $proceed($$);"); + logger.info("Instrumented checkCoinAward to call checkBounty as well."); + return; + } + } + });*/ + replace = "$_ = $proceed($$);" + //+ "mod.sin.wyvern.bounty.MethodsBounty.checkLootTable(this, corpse);"; + + LootBounty.class.getName()+".checkLootTable(this, corpse);"; + Util.instrumentDeclared(thisClass, ctCreature, "die", "setRotation", replace); + /*ctCreature.getDeclaredMethod("die").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("setRotation")) { + m.replace("$_ = $proceed($$);" + + "mod.sin.wyvern.bounty.MethodsBounty.checkLootTable(this, corpse);"); + logger.info("Instrumented setRotation to call insertCorpseItems as well."); + return; + } + } + });*/ + + // doNew(int templateid, boolean createPossessions, float aPosX, float aPosY, float aRot, int layer, String name, byte gender, byte kingdom, byte ctype, boolean reborn, byte age) + CtClass[] params = { + CtClass.intType, + CtClass.booleanType, + CtClass.floatType, + CtClass.floatType, + CtClass.floatType, + CtClass.intType, + classPool.get("java.lang.String"), + CtClass.byteType, + CtClass.byteType, + CtClass.byteType, + CtClass.booleanType, + CtClass.byteType, + CtClass.intType + }; + String desc = Descriptor.ofMethod(ctCreature, params); + Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc, "logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"); + // Debugging to show all new creatures created. + //CtMethod ctDoNew = ctCreature.getMethod("doNew", "(IZFFFILjava/lang/String;BBBZB)Lcom/wurmonline/server/creatures/Creature;"); + //ctDoNew.insertBefore("logger.info(\"Creating new creature: \"+templateid+\" - \"+(aPosX/4)+\", \"+(aPosY/4)+\" [\"+com.wurmonline.server.creatures.CreatureTemplateFactory.getInstance().getTemplate(templateid).getName()+\"]\");"); + // Modify new creatures + replace = "$_ = $proceed($$);" + //+ "mod.sin.wyvern.bestiary.MethodsBestiary.modifyNewCreature($1);"; + + MethodsBestiary.class.getName()+".modifyNewCreature($1);"; + Util.instrumentDescribed(thisClass, ctCreature, "doNew", desc, "sendToWorld", replace); + /*ctDoNew.instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("sendToWorld")) { + m.replace("$_ = $proceed($$);" + + "mod.sin.wyvern.bestiary.MethodsBestiary.modifyNewCreature($1);"); + return; + } + } + });*/ + + // -- Enable adjusting size for creatures -- // + CtClass ctCreatureStatus = classPool.get("com.wurmonline.server.creatures.CreatureStatus"); + Util.setBodyDeclared(thisClass, ctCreatureStatus, "getSizeMod", "{return "+MethodsBestiary.class.getName()+".getAdjustedSizeMod(this);}"); + //ctCreatureStatus.getDeclaredMethod("getSizeMod").setBody("{return mod.sin.wyvern.bestiary.MethodsBestiary.getAdjustedSizeMod(this);}"); + + // -- Enable adjusting color for creatures -- // + CtClass ctCreatureTemplate = classPool.get("com.wurmonline.server.creatures.CreatureTemplate"); + replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" + + " return "+MethodsBestiary.class.getName()+".getCreatureColorRed(this);" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorRed", replace); + replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" + + " return "+MethodsBestiary.class.getName()+".getCreatureColorGreen(this);" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorGreen", replace); + replace = "if("+MethodsBestiary.class.getName()+".checkColorTemplate(this)){" + + " return "+MethodsBestiary.class.getName()+".getCreatureColorBlue(this);" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCreatureTemplate, "getColorBlue", replace); + /*ctCreatureTemplate.getDeclaredMethod("getColorRed").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" + + " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorRed(this);" + + "}"); + ctCreatureTemplate.getDeclaredMethod("getColorGreen").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" + + " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorGreen(this);" + + "}"); + ctCreatureTemplate.getDeclaredMethod("getColorBlue").insertBefore("if(mod.sin.wyvern.bestiary.MethodsBestiary.checkColorTemplate(this)){" + + " return mod.sin.wyvern.bestiary.MethodsBestiary.getCreatureColorBlue(this);" + + "}");*/ + + // -- When a creature takes damage, track the damage taken -- // + CtClass[] params2 = { + ctCreature, + ctCreature, + CtClass.byteType, + CtClass.intType, + CtClass.doubleType, + CtClass.floatType, + classPool.get("java.lang.String"), + classPool.get("com.wurmonline.server.combat.Battle"), + CtClass.floatType, + CtClass.floatType, + CtClass.booleanType, + CtClass.booleanType + }; + String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2); + CtClass ctCombatEngine = classPool.get("com.wurmonline.server.combat.CombatEngine"); + replace = "" + + "if($1 != null && $2 != null){" + + " "+Bounty.class.getName()+".addDealtDamage($2.getWurmId(), $1.getWurmId(), $5);" + + "}"; + Util.insertBeforeDescribed(thisClass, ctCombatEngine, "addWound", desc2, replace); + //ctCombatEngine.getMethod("addWound", desc2).insertBefore("if($1 != null && $2 != null){mod.sin.wyvern.bounty.MethodsBounty.addDealtDamage($2.getWurmId(), $1.getWurmId(), $5);}"); + + } + catch (NotFoundException e) { + throw new HookException((Throwable)e); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/Caches.java b/src/main/java/mod/sin/wyvern/Caches.java new file mode 100644 index 0000000..f00c88f --- /dev/null +++ b/src/main/java/mod/sin/wyvern/Caches.java @@ -0,0 +1,423 @@ +package mod.sin.wyvern; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.pveplands.treasurehunting.Treasuremap; +import com.wurmonline.server.FailedException; +import com.wurmonline.server.Server; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemSpellEffects; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.items.NoSuchTemplateException; +import com.wurmonline.server.items.WurmColor; +import com.wurmonline.server.spells.SpellEffect; +import com.wurmonline.shared.constants.Enchants; + +import mod.sin.actions.items.TreasureCacheOpenAction; +import mod.sin.armour.*; +import mod.sin.items.*; +import mod.sin.items.caches.*; +import mod.sin.weapons.*; + +public class Caches { + public static final Logger logger = Logger.getLogger(Caches.class.getName()); + + public static ArrayList CACHE_IDS = new ArrayList(); + + public static AnimalCache ANIMAL_CACHE = new AnimalCache(); + public static ArmourCache ARMOUR_CACHE = new ArmourCache(); + public static ArtifactCache ARTIFACT_CACHE = new ArtifactCache(); + public static CrystalCache CRYSTAL_CACHE = new CrystalCache(); + public static DragonCache DRAGON_CACHE = new DragonCache(); + public static GemCache GEM_CACHE = new GemCache(); + public static MoonCache MOON_CACHE = new MoonCache(); + public static PotionCache POTION_CACHE = new PotionCache(); + public static RiftCache RIFT_CACHE = new RiftCache(); + public static ToolCache TOOL_CACHE = new ToolCache(); + public static TreasureMapCache TREASUREMAP_CACHE = new TreasureMapCache(); + public static WeaponCache WEAPON_CACHE = new WeaponCache(); + + public static boolean isTreasureCache(Item item){ + int templateId = item.getTemplateId(); + if(CACHE_IDS.contains(templateId)){ + return true; + } + return false; + } + + public static float getBaseQuality(float quality){ + return quality*0.5f; + } + public static float getRandomQuality(float quality){ + return quality*0.55f; + } + public static float getWeightMultiplier(int templateId, float quality){ + if(templateId == DragonCache.templateId){ + return (quality*0.005f)+(quality*0.001f*Server.rand.nextFloat()); + }else if(templateId == MoonCache.templateId){ + return 1f+(quality*0.05f)+(quality*0.05f*Server.rand.nextFloat()); + } + return 1f+(quality*0.02f); + } + public static boolean adjustBasicWeight(int templateId){ + if(templateId == DragonCache.templateId){ + return true; + }else if(templateId == MoonCache.templateId){ + return true; + } + return false; + } + public static void applyEnchant(Item item, byte enchant, float power){ + ItemSpellEffects effs = item.getSpellEffects(); + if(effs == null){ + effs = new ItemSpellEffects(item.getWurmId()); + } + SpellEffect eff = new SpellEffect(item.getWurmId(), enchant, power, 20000000); + effs.addSpellEffect(eff); + if(item.getDescription().length() > 0){ + item.setDescription(item.getDescription()+" "); + } + item.setDescription(item.getDescription()+eff.getName().substring(0,1)+Math.round(power)); + } + + public static boolean createsCustomBasic(int templateId){ + if(templateId == TreasureMapCache.templateId){ + return true; + } + return false; + } + + public static void getCustomBasic(Creature performer, Item cache){ + int templateId = cache.getTemplateId(); + if(templateId == TreasureMapCache.templateId){ + Item map = Treasuremap.CreateTreasuremap(performer, cache, null, null, true); + map.setRarity(cache.getRarity()); + performer.getInventory().insertItem(map, true); + } + } + public static int[] getBasicTemplates(int templateId){ + if(templateId == ArmourCache.templateId){ + return new int[]{ + ItemList.clothGlove, ItemList.clothHood, ItemList.clothHose, ItemList.clothJacket, ItemList.clothJacket, ItemList.clothShirt, ItemList.clothShoes, ItemList.clothSleeve, + ItemList.leatherBoot, ItemList.leatherCap, ItemList.leatherGlove, ItemList.leatherHose, ItemList.leatherJacket, ItemList.leatherSleeve, + ItemList.studdedLeatherBoot, ItemList.studdedLeatherCap, ItemList.studdedLeatherGlove, ItemList.studdedLeatherHose, ItemList.studdedLeatherHose, ItemList.studdedLeatherJacket, ItemList.studdedLeatherSleeve, + ItemList.chainBoot, ItemList.chainCoif, ItemList.chainGlove, ItemList.chainHose, ItemList.chainJacket, ItemList.chainSleeve, + ItemList.plateBoot, ItemList.plateGauntlet, ItemList.plateHose, ItemList.plateJacket, ItemList.plateSleeve, ItemList.helmetGreat, ItemList.helmetBasinet, ItemList.helmetOpen + }; + }else if(templateId == ArtifactCache.templateId){ + return new int[]{ + ItemList.swordShort, ItemList.swordLong, ItemList.swordTwoHander, + ItemList.axeSmall, ItemList.axeMedium, ItemList.axeHuge, + ItemList.maulSmall, ItemList.maulMedium, ItemList.maulLarge, + ItemList.spearLong, ItemList.staffSteel, ItemList.halberd, + Club.templateId, Knuckles.templateId, Warhammer.templateId + }; + }else if(templateId == CrystalCache.templateId){ + return new int[]{ + ChaosCrystal.templateId, ChaosCrystal.templateId, + EnchantersCrystal.templateId + }; + }else if(templateId == DragonCache.templateId){ + return new int[]{ + ItemList.drakeHide, + ItemList.drakeHide, + ItemList.dragonScale, + ItemList.dragonScale, + SpectralHide.templateId + }; + }else if(templateId == GemCache.templateId){ + return new int[]{ + ItemList.diamond, + ItemList.emerald, + ItemList.opal, + ItemList.ruby, + ItemList.sapphire + }; + }else if(templateId == MoonCache.templateId){ + return new int[]{ + ItemList.glimmerSteelBar, + ItemList.adamantineBar + }; + }else if(templateId == PotionCache.templateId){ + return new int[]{ + ItemList.potionAcidDamage, + ItemList.potionArmourSmithing, + ItemList.potionBlacksmithing, + ItemList.potionCarpentry, + ItemList.potionFireDamage, + ItemList.potionFletching, + ItemList.potionFrostDamage, + ItemList.potionLeatherworking, + ItemList.potionMasonry, + ItemList.potionMining, + ItemList.potionRopemaking, + ItemList.potionShipbuilding, + ItemList.potionStonecutting, + ItemList.potionTailoring, + ItemList.potionWeaponSmithing, + ItemList.potionWoodcutting + }; + }else if(templateId == RiftCache.templateId){ + return new int[]{ + ItemList.riftCrystal, + ItemList.riftWood, + ItemList.riftStone + }; + } + return null; + } + public static void adjustBasicItem(int templateId, float quality, Item item){ + if(templateId == ArmourCache.templateId){ + if(quality > 50){ + if(quality > 95 && Server.rand.nextBoolean()){ + applyEnchant(item, Enchants.BUFF_SHARED_PAIN, quality*Server.rand.nextFloat()*1.2f); + applyEnchant(item, Enchants.BUFF_WEBARMOUR, quality*Server.rand.nextFloat()*1.2f); + }else if(Server.rand.nextBoolean()){ + byte[] armourEnchants = { + Enchants.BUFF_SHARED_PAIN, + Enchants.BUFF_WEBARMOUR + }; + applyEnchant(item, armourEnchants[Server.rand.nextInt(armourEnchants.length)], quality*Server.rand.nextFloat()*1.5f); + } + } + if(quality > 80 && Server.rand.nextInt(4) == 0){ + byte[] materials = { + Materials.MATERIAL_ADAMANTINE, + Materials.MATERIAL_COTTON, + Materials.MATERIAL_GLIMMERSTEEL, + Materials.MATERIAL_IRON, + Materials.MATERIAL_LEATHER, + Materials.MATERIAL_SERYLL, + Materials.MATERIAL_STEEL + }; + item.setMaterial(materials[Server.rand.nextInt(materials.length)]); + }else{ + if(item.isMetal()){ + item.setMaterial(Materials.MATERIAL_IRON); + }else if(item.isLeather()){ + item.setMaterial(Materials.MATERIAL_LEATHER); + } + } + }else if(templateId == ArtifactCache.templateId){ + byte[] materials = { + Materials.MATERIAL_ADAMANTINE, + Materials.MATERIAL_GLIMMERSTEEL, + Materials.MATERIAL_STEEL + }; + item.setMaterial(materials[Server.rand.nextInt(materials.length)]); + float qualBoost = (100f-item.getQualityLevel())*Server.rand.nextFloat(); + item.setQualityLevel(item.getQualityLevel()+qualBoost); + if(quality > 50 && Server.rand.nextInt(200) < quality){ + if(item.getRarity() == 0){ + if(Server.rand.nextInt(600) < quality){ + item.setRarity((byte) 2); + }else{ + item.setRarity((byte) 1); + } + } + } + if(quality > 70 && Server.rand.nextBoolean()){ + if(Server.rand.nextBoolean()){ + byte[] enchants = { + Enchants.BUFF_WIND_OF_AGES, + Enchants.BUFF_BLESSINGDARK + }; + applyEnchant(item, enchants[Server.rand.nextInt(enchants.length)], quality*Server.rand.nextFloat()*0.9f); + applyEnchant(item, Enchants.BUFF_NIMBLENESS, quality*Server.rand.nextFloat()*1.2f); + }else{ + applyEnchant(item, Enchants.BUFF_LIFETRANSFER, quality+(quality*Server.rand.nextFloat())); + } + } + }else if(templateId == CrystalCache.templateId){ + item.setQualityLevel(Server.rand.nextFloat()*quality); + } + } + public static int getBasicNums(int templateId){ + if(templateId == CrystalCache.templateId){ + return 15; + }else if(templateId == GemCache.templateId){ + return 2; + } + return 1; + } + public static int getExtraBasicNums(int templateId, float quality){ + if(templateId == ArmourCache.templateId){ + return Server.rand.nextInt(2); + }else if(templateId == CrystalCache.templateId){ + return Server.rand.nextInt(Math.max((int) (quality*0.3f), 2)); + }else if(templateId == DragonCache.templateId){ + if(Server.rand.nextInt(200) <= quality){ + return 1; + } + }else if(templateId == GemCache.templateId){ + return Server.rand.nextInt(Math.max((int) (quality*0.03f), 2)); + }else if(templateId == PotionCache.templateId){ + if(Server.rand.nextInt(300) <= quality){ + return 1; + } + }else if(templateId == RiftCache.templateId){ + if(Server.rand.nextInt(300) <= quality){ + return 2; + }else if(Server.rand.nextInt(100) <= quality){ + return 1; + } + } + return 0; + } + public static int getExtraItemChance(int templateId){ + if(templateId == ArmourCache.templateId){ + return 1600; + }else if(templateId == DragonCache.templateId){ + return 600; + }else if(templateId == GemCache.templateId){ + return 200; + } + return -1; + } + public static int[] getExtraTemplates(int templateId){ + if(templateId == ArmourCache.templateId){ + return new int[]{ + GlimmerscaleBoot.templateId, + GlimmerscaleGlove.templateId, + GlimmerscaleHelmet.templateId, + GlimmerscaleHose.templateId, + GlimmerscaleSleeve.templateId, + GlimmerscaleVest.templateId, + SpectralBoot.templateId, + SpectralCap.templateId, + SpectralGlove.templateId, + SpectralHose.templateId, + SpectralJacket.templateId, + SpectralSleeve.templateId + }; + }else if(templateId == DragonCache.templateId){ + return new int[]{ + ItemList.dragonLeatherBoot, + ItemList.dragonLeatherCap, + ItemList.dragonLeatherGlove, + ItemList.dragonLeatherHose, + ItemList.dragonLeatherJacket, + ItemList.dragonLeatherSleeve, + ItemList.dragonScaleBoot, + ItemList.dragonScaleGauntlet, + ItemList.dragonScaleHose, + ItemList.dragonScaleJacket, + ItemList.dragonScaleSleeve + }; + }else if(templateId == GemCache.templateId){ + return new int[]{ + ItemList.opalBlack, + ItemList.diamondStar, + ItemList.emeraldStar, + ItemList.rubyStar, + ItemList.sapphireStar + }; + } + return null; + } + + public static void adjustExtraItem(int templateId, Item item){ + if(templateId == ArmourCache.templateId){ + item.setColor(WurmColor.createColor(100, 100, 100)); + }else if(templateId == DragonCache.templateId){ + item.setMaterial(Materials.MATERIAL_LEATHER); + } + } + + public static void openCache(Creature performer, Item cache){ + int templateId = cache.getTemplateId(); + Item inv = performer.getInventory(); + float quality = cache.getCurrentQualityLevel(); + float baseQL = getBaseQuality(quality); + float randQL = getRandomQuality(quality); + if(createsCustomBasic(templateId)){ + getCustomBasic(performer, cache); + }else{ + int[] basicTemplates = getBasicTemplates(templateId); + if(basicTemplates == null){ + logger.warning("Error: Basic Templates are null for cache with template id "+templateId); + return; + } + int basicNums = getBasicNums(templateId); + basicNums += getExtraBasicNums(templateId, quality); + int i = 0; + while(i < basicNums){ + try { + float basicQuality = Math.max(baseQL+(randQL*Server.rand.nextFloat()), baseQL+(randQL*Server.rand.nextFloat())); + basicQuality = Math.min(basicQuality, 100f); + Item basicItem = ItemFactory.createItem(basicTemplates[Server.rand.nextInt(basicTemplates.length)], basicQuality, ""); + basicItem.setRarity(cache.getRarity()); + adjustBasicItem(templateId, quality, basicItem); + if(adjustBasicWeight(templateId)){ + float weightMult = getWeightMultiplier(templateId, quality); + basicItem.setWeight((int) (basicItem.getWeightGrams()*weightMult), true); + } + inv.insertItem(basicItem, true); + } catch (FailedException | NoSuchTemplateException e) { + logger.warning("Error: Failed to create item for cache with template id "+templateId); + e.printStackTrace(); + } + i++; + } + } + int chance = getExtraItemChance(templateId); + if(chance > 0 && Server.rand.nextInt(chance) <= quality){ + try { + int[] extraTemplates = getExtraTemplates(templateId); + if(extraTemplates != null){ + float extraQuality = Math.max(baseQL+(randQL*Server.rand.nextFloat()), baseQL+(randQL*Server.rand.nextFloat())); + extraQuality = Math.min(extraQuality, 100f); + Item extraItem = ItemFactory.createItem(extraTemplates[Server.rand.nextInt(extraTemplates.length)], extraQuality, ""); + extraItem.setRarity(cache.getRarity()); + adjustExtraItem(templateId, extraItem); + inv.insertItem(extraItem, true); + } + } catch (FailedException | NoSuchTemplateException e) { + logger.warning("Error: Failed to create item for cache with template id "+templateId); + e.printStackTrace(); + } + } + } + + public static void createItems(){ + try { + ANIMAL_CACHE.createTemplate(); + //CACHE_IDS.add(AnimalCache.templateId); + ARMOUR_CACHE.createTemplate(); + CACHE_IDS.add(ArmourCache.templateId); + ARTIFACT_CACHE.createTemplate(); + CACHE_IDS.add(ArtifactCache.templateId); + CRYSTAL_CACHE.createTemplate(); + CACHE_IDS.add(CrystalCache.templateId); + DRAGON_CACHE.createTemplate(); + CACHE_IDS.add(DragonCache.templateId); + GEM_CACHE.createTemplate(); + CACHE_IDS.add(GemCache.templateId); + MOON_CACHE.createTemplate(); + CACHE_IDS.add(MoonCache.templateId); + POTION_CACHE.createTemplate(); + CACHE_IDS.add(PotionCache.templateId); + RIFT_CACHE.createTemplate(); + CACHE_IDS.add(RiftCache.templateId); + TOOL_CACHE.createTemplate(); + //CACHE_IDS.add(ToolCache.templateId); + TREASUREMAP_CACHE.createTemplate(); + CACHE_IDS.add(TreasureMapCache.templateId); + WEAPON_CACHE.createTemplate(); + //CACHE_IDS.add(WeaponCache.templateId); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void registerActions(){ + ModActions.registerAction(new TreasureCacheOpenAction()); + } +} diff --git a/src/main/java/mod/sin/wyvern/Crystals.java b/src/main/java/mod/sin/wyvern/Crystals.java new file mode 100644 index 0000000..20a23ff --- /dev/null +++ b/src/main/java/mod/sin/wyvern/Crystals.java @@ -0,0 +1,130 @@ +package mod.sin.wyvern; + +import com.wurmonline.server.Server; +import com.wurmonline.server.Servers; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemSpellEffects; +import com.wurmonline.server.items.NotOwnedException; +import com.wurmonline.shared.constants.Enchants; + +import mod.sin.items.ChaosCrystal; +import mod.sin.items.EnchantersCrystal; + +public class Crystals { + public static byte[] enchs = { // Valid enchants to apply to an item with Enchanters Crystals + Enchants.BUFF_BLESSINGDARK, + Enchants.BUFF_BLOODTHIRST, + Enchants.BUFF_CIRCLE_CUNNING, + Enchants.BUFF_COURIER, + Enchants.BUFF_FLAMING_AURA, + Enchants.BUFF_FROSTBRAND, + Enchants.BUFF_LIFETRANSFER, + Enchants.BUFF_MINDSTEALER, + Enchants.BUFF_NIMBLENESS, + Enchants.BUFF_OPULENCE, + Enchants.BUFF_ROTTING_TOUCH, + Enchants.BUFF_SHARED_PAIN, + Enchants.BUFF_VENOM, + Enchants.BUFF_WEBARMOUR, + Enchants.BUFF_WIND_OF_AGES, + 110, 111 // Harden and Phasing + }; + public static byte getNewRandomEnchant(Item target){ + int i = 0; + while(i < 10){ + byte ench = enchs[Server.rand.nextInt(enchs.length)]; + if(target.getBonusForSpellEffect(ench) == 0f){ + return ench; + } + i++; + } + return -10; + } + public static double getInfusionDifficulty(Creature performer, Item source, Item target){ + double diff = (Servers.localServer.PVPSERVER ? 150 : 120)-source.getCurrentQualityLevel(); + diff += source.getRarity()*(Servers.localServer.PVPSERVER ? 50 : 30); + diff += 40f - (target.getCurrentQualityLevel()*0.4f); + diff -= performer.getSoulDepth().getKnowledge(); + if(Servers.localServer.PVPSERVER){ // Added difficulty to account for PvP epic curve: + diff *= 1.4f; + } + return diff; + } + public static double getEnchantersInfusionDifficulty(Creature performer, Item source, Item target){ + double diff = (Servers.localServer.PVPSERVER ? 220 : 180)-source.getCurrentQualityLevel(); + diff += 40f - (target.getCurrentQualityLevel()*0.4f); + diff -= performer.getSoulDepth().getKnowledge(); + if(Servers.localServer.PVPSERVER){ // Added difficulty to account for PvP epic curve: + diff *= 1.4f; + } + return diff; + } + public static boolean shouldCancelEnchantersInfusion(Creature performer, Item target){ + if(target.getOwnerId() != performer.getWurmId() && target.getLastOwnerId() != performer.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You must own the item you wish to infuse."); + return true; + } + ItemSpellEffects effs = target.getSpellEffects(); + if(effs == null || effs.getEffects().length == 0){ + performer.getCommunicator().sendNormalServerMessage("The item must be enchanted to be infused."); + return true; + } + return false; + } + public static boolean shouldCancelInfusion(Creature performer, Item source, Item target){ + if(target.getOwnerId() != performer.getWurmId() && target.getLastOwnerId() != performer.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You must own the item you wish to infuse."); + return true; + } + if(source.getRarity() > target.getRarity()+1){ + performer.getCommunicator().sendNormalServerMessage("The "+source.getName()+" is too powerful, and would outright destroy the "+target.getName()+"."); + return true; + }else if(source.getRarity() < target.getRarity()+1){ + performer.getCommunicator().sendNormalServerMessage("The "+source.getName()+" is not powerful enough to have an effect on the "+target.getName()+". You will need to combine with other crystals first."); + return true; + } + return false; + } + public static boolean shouldCancelCombine(Creature performer, Item source, Item target){ + if(source.getWurmId() == target.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You can't combine a crystal with itself, silly!"); + return true; + } + if(!Crystals.isCrystal(source) || !Crystals.isCrystal(target)){ + performer.getCommunicator().sendNormalServerMessage("Both objects must be Crystals to combine."); + return true; + } + if(source.getTemplateId() != target.getTemplateId()){ + performer.getCommunicator().sendNormalServerMessage("Both crystals must be of the same type to combine."); + return true; + } + try { + if(source.getOwner() != performer.getWurmId() || target.getOwner() != performer.getWurmId()){ + performer.getCommunicator().sendNormalServerMessage("You must hold both crystals in your hands to combine them."); + return true; + } + } catch (NotOwnedException e) { + e.printStackTrace(); + } + if(source.getRarity() < target.getRarity()){ + performer.getCommunicator().sendNormalServerMessage("That crystal is too potent for this combination."); + return true; + }else if(source.getRarity() > target.getRarity()){ + performer.getCommunicator().sendNormalServerMessage("That crystal is not potent enough for this combination."); + return true; + }else if(source.getRarity() >= 3 && target.getRarity() >= 3 && source.getCurrentQualityLevel() + target.getCurrentQualityLevel() >= 100){ + performer.getCommunicator().sendNormalServerMessage("Those crystals would be far too powerful if combined."); + return true; + } + return false; + } + public static boolean isCrystal(Item item){ + if(item.getTemplateId() == ChaosCrystal.templateId){ + return true; + }else if(item.getTemplateId() == EnchantersCrystal.templateId){ + return true; + } + return false; + } +} diff --git a/src/main/java/mod/sin/wyvern/ItemMod.java b/src/main/java/mod/sin/wyvern/ItemMod.java new file mode 100644 index 0000000..8876bf1 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/ItemMod.java @@ -0,0 +1,419 @@ +package mod.sin.wyvern; + +import java.io.IOException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modloader.ReflectionUtil; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; +import org.gotti.wurmunlimited.modloader.classhooks.InvocationHandlerFactory; +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.behaviours.ActionEntry; +import com.wurmonline.server.combat.Armour; +import com.wurmonline.server.combat.Weapon; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTemplateFactory; +import com.wurmonline.server.items.NoSuchTemplateException; +import javassist.CtClass; +import javassist.bytecode.Descriptor; +import mod.sin.actions.items.*; +import mod.sin.armour.*; +import mod.sin.items.*; +import mod.sin.weapons.*; +import mod.sin.weapons.heads.*; +import mod.sin.weapons.titan.*; + +public class ItemMod { + public static Logger logger = Logger.getLogger(ItemMod.class.getName()); + + public static AffinityOrb AFFINITY_ORB = new AffinityOrb(); + public static ArenaCache ARENA_CACHE = new ArenaCache(); + public static ArenaSupplyDepot ARENA_SUPPLY_DEPOT = new ArenaSupplyDepot(); + public static ArrowPackHunting ARROW_PACK_HUNTING = new ArrowPackHunting(); + public static ArrowPackWar ARROW_PACK_WAR = new ArrowPackWar(); + public static BattleYoyo BATTLE_YOYO = new BattleYoyo(); + public static Club CLUB = new Club(); + public static CoinDecoration COIN_DECORATION = new CoinDecoration(); + public static CorpseDecoration CORPSE_DECORATION = new CorpseDecoration(); + public static DepthDrill DEPTH_DRILL = new DepthDrill(); + public static DisintegrationRod DISINTEGRATION_ROD = new DisintegrationRod(); + public static EnchantOrb ENCHANT_ORB = new EnchantOrb(); + public static Eviscerator EVISCERATOR = new Eviscerator(); + public static FriyanTablet FRIYAN_TABLET = new FriyanTablet(); + public static HugeCrate HUGE_CRATE = new HugeCrate(); + public static Knuckles KNUCKLES = new Knuckles(); + public static MassStorageUnit MASS_STORAGE_UNIT = new MassStorageUnit(); + public static SealedMap SEALED_MAP = new SealedMap(); + public static SkeletonDecoration SKELETON_DECORATION = new SkeletonDecoration(); + public static Soul SOUL = new Soul(); + public static EternalReservoir SOUL_FORGE = new EternalReservoir(); + public static StatuetteBreyk STATUETTE_BREYK = new StatuetteBreyk(); + public static StatuetteCyberhusky STATUETTE_CYBERHUSKY = new StatuetteCyberhusky(); + public static TreasureBox TREASURE_BOX = new TreasureBox(); + public static Warhammer WARHAMMER = new Warhammer(); + public static WarhammerHead WARHAMMER_HEAD = new WarhammerHead(); + + // Crystals + public static ChaosCrystal CHAOS_CRYSTAL = new ChaosCrystal(); + public static EnchantersCrystal ENCHANTERS_CRYSTAL = new EnchantersCrystal(); + + // Titan weaponry + public static MaartensMight MAARTENS_MIGHT = new MaartensMight(); + public static RaffehsRage RAFFEHS_RAGE = new RaffehsRage(); + public static VindictivesVengeance VINDICTIVES_VENGEANCE = new VindictivesVengeance(); + public static WilhelmsWrath WILHELMS_WRATH = new WilhelmsWrath(); + + // Spectral set + public static SpectralHide SPECTRAL_HIDE = new SpectralHide(); + public static SpectralBoot SPECTRAL_BOOT = new SpectralBoot(); + public static SpectralCap SPECTRAL_CAP = new SpectralCap(); + public static SpectralGlove SPECTRAL_GLOVE = new SpectralGlove(); + public static SpectralHose SPECTRAL_HOSE = new SpectralHose(); + public static SpectralJacket SPECTRAL_JACKET = new SpectralJacket(); + public static SpectralSleeve SPECTRAL_SLEEVE = new SpectralSleeve(); + + // Glimmerscale set + public static Glimmerscale GLIMMERSCALE = new Glimmerscale(); + public static GlimmerscaleBoot GLIMMERSCALE_BOOT = new GlimmerscaleBoot(); + public static GlimmerscaleGlove GLIMMERSCALE_GLOVE = new GlimmerscaleGlove(); + public static GlimmerscaleHelmet GLIMMERSCALE_HELMET = new GlimmerscaleHelmet(); + public static GlimmerscaleHose GLIMMERSCALE_HOSE = new GlimmerscaleHose(); + public static GlimmerscaleSleeve GLIMMERSCALE_SLEEVE = new GlimmerscaleSleeve(); + public static GlimmerscaleVest GLIMMERSCALE_VEST = new GlimmerscaleVest(); + + public static void createItems(){ + logger.info("createItems()"); + try{ + AFFINITY_ORB.createTemplate(); + ARENA_CACHE.createTemplate(); + ARENA_SUPPLY_DEPOT.createTemplate(); + ARROW_PACK_HUNTING.createTemplate(); + ARROW_PACK_WAR.createTemplate(); + BATTLE_YOYO.createTemplate(); + CLUB.createTemplate(); + COIN_DECORATION.createTemplate(); + CORPSE_DECORATION.createTemplate(); + DEPTH_DRILL.createTemplate(); + DISINTEGRATION_ROD.createTemplate(); + ENCHANT_ORB.createTemplate(); + EVISCERATOR.createTemplate(); + FRIYAN_TABLET.createTemplate(); + HUGE_CRATE.createTemplate(); + KNUCKLES.createTemplate(); + MASS_STORAGE_UNIT.createTemplate(); + SEALED_MAP.createTemplate(); + SKELETON_DECORATION.createTemplate(); + SOUL.createTemplate(); + SOUL_FORGE.createTemplate(); + STATUETTE_BREYK.createTemplate(); + STATUETTE_CYBERHUSKY.createTemplate(); + TREASURE_BOX.createTemplate(); + WARHAMMER.createTemplate(); + WARHAMMER_HEAD.createTemplate(); + + // Crystals + CHAOS_CRYSTAL.createTemplate(); + ENCHANTERS_CRYSTAL.createTemplate(); + + // Titan weaponry + MAARTENS_MIGHT.createTemplate(); + RAFFEHS_RAGE.createTemplate(); + VINDICTIVES_VENGEANCE.createTemplate(); + WILHELMS_WRATH.createTemplate(); + + // Spectral set + SPECTRAL_HIDE.createTemplate(); + SPECTRAL_BOOT.createTemplate(); + SPECTRAL_CAP.createTemplate(); + SPECTRAL_GLOVE.createTemplate(); + SPECTRAL_HOSE.createTemplate(); + SPECTRAL_JACKET.createTemplate(); + SPECTRAL_SLEEVE.createTemplate(); + + // Glimmerscale set + GLIMMERSCALE.createTemplate(); + GLIMMERSCALE_BOOT.createTemplate(); + GLIMMERSCALE_GLOVE.createTemplate(); + GLIMMERSCALE_HELMET.createTemplate(); + GLIMMERSCALE_HOSE.createTemplate(); + GLIMMERSCALE_SLEEVE.createTemplate(); + GLIMMERSCALE_VEST.createTemplate(); + }catch(IOException e){ + e.printStackTrace(); + } + } + + public static void registerActions(){ + ModActions.registerAction(new AffinityOrbAction()); + ModActions.registerAction(new ArenaCacheOpenAction()); + ModActions.registerAction(new ArrowPackUnpackAction()); + ModActions.registerAction(new CrystalCombineAction()); + ModActions.registerAction(new ChaosCrystalInfuseAction()); + ModActions.registerAction(new DepthDrillAction()); + ModActions.registerAction(new DisintegrationRodAction()); + ModActions.registerAction(new EnchantersCrystalInfuseAction()); + ModActions.registerAction(new EnchantOrbAction()); + ModActions.registerAction(new FriyanTabletAction()); + ModActions.registerAction(new SealedMapAction()); + ModActions.registerAction(new SupplyDepotAction()); + ModActions.registerAction(new TreasureBoxAction()); + } + + public static void initCreationEntries(){ + logger.info("initCreationEntries()"); + ARROW_PACK_HUNTING.initCreationEntry(); + ARROW_PACK_WAR.initCreationEntry(); + BATTLE_YOYO.initCreationEntry(); + CLUB.initCreationEntry(); + COIN_DECORATION.initCreationEntry(); + CORPSE_DECORATION.initCreationEntry(); + DEPTH_DRILL.initCreationEntry(); + EVISCERATOR.initCreationEntry(); + KNUCKLES.initCreationEntry(); + MASS_STORAGE_UNIT.initCreationEntry(); + SKELETON_DECORATION.initCreationEntry(); + SOUL_FORGE.initCreationEntry(); + STATUETTE_BREYK.initCreationEntry(); + STATUETTE_CYBERHUSKY.initCreationEntry(); + WARHAMMER.initCreationEntry(); + WARHAMMER_HEAD.initCreationEntry(); + + // Spectral set + SPECTRAL_BOOT.initCreationEntry(); + SPECTRAL_CAP.initCreationEntry(); + SPECTRAL_GLOVE.initCreationEntry(); + SPECTRAL_HOSE.initCreationEntry(); + SPECTRAL_JACKET.initCreationEntry(); + SPECTRAL_SLEEVE.initCreationEntry(); + + // Glimmerscale set + GLIMMERSCALE.initCreationEntry(); + GLIMMERSCALE_BOOT.initCreationEntry(); + GLIMMERSCALE_GLOVE.initCreationEntry(); + GLIMMERSCALE_HELMET.initCreationEntry(); + GLIMMERSCALE_HOSE.initCreationEntry(); + GLIMMERSCALE_SLEEVE.initCreationEntry(); + GLIMMERSCALE_VEST.initCreationEntry(); + + // Allow sickle heads from steel & moon metals: + // [3/28/18] Disabled: Implemented in WU 1.6. + /*CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.steelBar, + ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.adamantineBar, + ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.glimmerSteelBar, + ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.seryllBar, + ItemList.sickleBlade, false, true, 0.0f, false, false, CreationCategories.BLADES); + // Allow steel staff to be created from moon metals: + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.adamantineBar, + ItemList.staffSteel, false, true, 0.0f, false, false, CreationCategories.BLADES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.glimmerSteelBar, + ItemList.staffSteel, false, true, 0.0f, false, false, CreationCategories.BLADES); + CreationEntryCreator.createSimpleEntry(SkillList.SMITHING_WEAPON_BLADES, ItemList.anvilLarge, ItemList.seryllBar, + ItemList.staffSteel, false, true, 0.0f, false, false, CreationCategories.BLADES);*/ + } + + public static void createCustomArmours(){ + try { + logger.info("Beginning custom armour creation."); + Map armours = ReflectionUtil.getPrivateField(null, ReflectionUtil.getField(Armour.class, "armours")); + + armours.put(SpectralBoot.templateId, new Armour(SpectralBoot.templateId, 0.002f, 0.3f)); + armours.put(SpectralCap.templateId, new Armour(SpectralCap.templateId, 0.003f, 0.3f)); + armours.put(SpectralGlove.templateId, new Armour(SpectralGlove.templateId, 0.002f, 0.3f)); + armours.put(SpectralHose.templateId, new Armour(SpectralHose.templateId, 0.0075f, 0.3f)); + armours.put(SpectralJacket.templateId, new Armour(SpectralJacket.templateId, 0.01f, 0.3f)); + armours.put(SpectralSleeve.templateId, new Armour(SpectralSleeve.templateId, 0.004f, 0.3f)); + + armours.put(GlimmerscaleBoot.templateId, new Armour(GlimmerscaleBoot.templateId, 0.002f, 0.15f)); + armours.put(GlimmerscaleGlove.templateId, new Armour(GlimmerscaleGlove.templateId, 0.001f, 0.15f)); + armours.put(GlimmerscaleHelmet.templateId, new Armour(GlimmerscaleHelmet.templateId, 0.008f, 0.15f)); + armours.put(GlimmerscaleHose.templateId, new Armour(GlimmerscaleHose.templateId, 0.05f, 0.15f)); + armours.put(GlimmerscaleSleeve.templateId, new Armour(GlimmerscaleSleeve.templateId, 0.008f, 0.15f)); + armours.put(GlimmerscaleVest.templateId, new Armour(GlimmerscaleVest.templateId, 0.05f, 0.15f)); + + //ReflectionUtil.setPrivateField(null, ReflectionUtil.getField(Armour.class, "armours"), armours); + } catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + + public static void createCustomWeapons(){ + try { + logger.info("Beginning custom weapon creation."); + new Weapon(BattleYoyo.templateId, 7.75f, 3.5f, 0.008f, 2, 2, 0.0f, 0d); + new Weapon(Club.templateId, 8.5f, 4.1f, 0.002f, 3, 3, 0.4f, 0.5d); + new Weapon(Knuckles.templateId, 4.1f, 1f, 0.002f, 1, 1, 0.2f, 0.5d); + new Weapon(Warhammer.templateId, 9.75f, 5.2f, 0.008f, 4, 3, 1f, 0d); + // Titan weaponry + new Weapon(MaartensMight.templateId, 11, 5, 0.02f, 4, 4, 1.0f, 0d); + new Weapon(RaffehsRage.templateId, 9.5f, 4.25f, 0.02f, 3, 3, 1.0f, 0d); + new Weapon(VindictivesVengeance.templateId, 9, 4f, 0.02f, 3, 3, 0.5f, 0d); + new Weapon(WilhelmsWrath.templateId, 6f, 4.5f, 0.02f, 6, 6, 0.5f, 0d); + // Genocide weapon + new Weapon(Eviscerator.templateId, 11, 4.5f, 0.02f, 5, 5, 0.4f, 0.5d); + } catch (IllegalArgumentException | ClassCastException e) { + e.printStackTrace(); + } + } + + public static int getModdedImproveTemplateId(Item item){ + if(item.getTemplateId() == SpectralBoot.templateId){ + return SpectralHide.templateId; + }else if(item.getTemplateId() == SpectralCap.templateId){ + return SpectralHide.templateId; + }else if(item.getTemplateId() == SpectralGlove.templateId){ + return SpectralHide.templateId; + }else if(item.getTemplateId() == SpectralHose.templateId){ + return SpectralHide.templateId; + }else if(item.getTemplateId() == SpectralJacket.templateId){ + return SpectralHide.templateId; + }else if(item.getTemplateId() == SpectralSleeve.templateId){ + return SpectralHide.templateId; + }else if(item.getTemplateId() == GlimmerscaleBoot.templateId){ + return Glimmerscale.templateId; + }else if(item.getTemplateId() == GlimmerscaleGlove.templateId){ + return Glimmerscale.templateId; + }else if(item.getTemplateId() == GlimmerscaleHelmet.templateId){ + return Glimmerscale.templateId; + }else if(item.getTemplateId() == GlimmerscaleHose.templateId){ + return Glimmerscale.templateId; + }else if(item.getTemplateId() == GlimmerscaleSleeve.templateId){ + return Glimmerscale.templateId; + }else if(item.getTemplateId() == GlimmerscaleVest.templateId){ + return Glimmerscale.templateId; + } + return -10; + } + + public static void modifyItems() throws NoSuchTemplateException, IllegalArgumentException, IllegalAccessException, ClassCastException, NoSuchFieldException{ + // Make leather able to be combined. + ItemTemplate leather = ItemTemplateFactory.getInstance().getTemplate(ItemList.leather); + ReflectionUtil.setPrivateField(leather, ReflectionUtil.getField(leather.getClass(), "combine"), true); + + // Set silver mirror price to 10 silver instead of 1 iron. + ItemTemplate handMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.handMirror); + ReflectionUtil.setPrivateField(handMirror, ReflectionUtil.getField(handMirror.getClass(), "value"), 500000); + ItemTemplate goldMirror = ItemTemplateFactory.getInstance().getTemplate(ItemList.goldenMirror); + ReflectionUtil.setPrivateField(goldMirror, ReflectionUtil.getField(goldMirror.getClass(), "value"), 3000000); + + // Set transmutation rod to 2 gold instead of 50 silver. + //ItemTemplate transmutationRod = ItemTemplateFactory.getInstance().getTemplate(668); + //ReflectionUtil.setPrivateField(transmutationRod, ReflectionUtil.getField(transmutationRod.getClass(), "value"), 2000000); + + // Make logs able to be combined. + ItemTemplate log = ItemTemplateFactory.getInstance().getTemplate(ItemList.log); + ReflectionUtil.setPrivateField(log, ReflectionUtil.getField(log.getClass(), "combine"), true); + + // " return this.isTransportable || (this.getTemplateId() >= 510 && this.getTemplateId() <= 513) || this.getTemplateId() == 722 || this.getTemplateId() == 670;" + // Make mailboxes loadable + ItemTemplate mailboxWood = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxWood); + ReflectionUtil.setPrivateField(mailboxWood, ReflectionUtil.getField(mailboxWood.getClass(), "isTransportable"), true); + ItemTemplate mailboxStone = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxStone); + ReflectionUtil.setPrivateField(mailboxStone, ReflectionUtil.getField(mailboxStone.getClass(), "isTransportable"), true); + ItemTemplate mailboxWood2 = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxWoodTwo); + ReflectionUtil.setPrivateField(mailboxWood2, ReflectionUtil.getField(mailboxWood2.getClass(), "isTransportable"), true); + ItemTemplate mailboxStone2 = ItemTemplateFactory.getInstance().getTemplate(ItemList.mailboxStoneTwo); + ReflectionUtil.setPrivateField(mailboxStone2, ReflectionUtil.getField(mailboxStone2.getClass(), "isTransportable"), true); + + // Make bell towers and trash bins loadable + ItemTemplate bellTower = ItemTemplateFactory.getInstance().getTemplate(ItemList.bellTower); + ReflectionUtil.setPrivateField(bellTower, ReflectionUtil.getField(bellTower.getClass(), "isTransportable"), true); + ItemTemplate trashBin = ItemTemplateFactory.getInstance().getTemplate(ItemList.trashBin); + ReflectionUtil.setPrivateField(trashBin, ReflectionUtil.getField(trashBin.getClass(), "isTransportable"), true); + + // Make altars loadable + ItemTemplate stoneAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarStone); + ReflectionUtil.setPrivateField(stoneAltar, ReflectionUtil.getField(stoneAltar.getClass(), "isTransportable"), true); + ItemTemplate woodAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarWood); + ReflectionUtil.setPrivateField(woodAltar, ReflectionUtil.getField(woodAltar.getClass(), "isTransportable"), true); + ItemTemplate silverAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarSilver); + ReflectionUtil.setPrivateField(silverAltar, ReflectionUtil.getField(silverAltar.getClass(), "isTransportable"), true); + ItemTemplate goldAltar = ItemTemplateFactory.getInstance().getTemplate(ItemList.altarGold); + ReflectionUtil.setPrivateField(goldAltar, ReflectionUtil.getField(goldAltar.getClass(), "isTransportable"), true); + + // Make long spears one-handed. + ItemTemplate longSpear = ItemTemplateFactory.getInstance().getTemplate(ItemList.spearLong); + ReflectionUtil.setPrivateField(longSpear, ReflectionUtil.getField(longSpear.getClass(), "isTwohanded"), false); + + // Make dirt/sand difficulty easier + ItemTemplate dirt = ItemTemplateFactory.getInstance().getTemplate(ItemList.dirtPile); + ReflectionUtil.setPrivateField(dirt, ReflectionUtil.getField(dirt.getClass(), "difficulty"), 50.0f); + + ItemTemplate sand = ItemTemplateFactory.getInstance().getTemplate(ItemList.sand); + ReflectionUtil.setPrivateField(sand, ReflectionUtil.getField(sand.getClass(), "difficulty"), 50.0f); + + ItemTemplate sandstone = ItemTemplateFactory.getInstance().getTemplate(ItemList.sandstone); + ReflectionUtil.setPrivateField(sandstone, ReflectionUtil.getField(sandstone.getClass(), "difficulty"), 50.0f); + + createCustomWeapons(); + createCustomArmours(); + + // Make huge crates larger + //ItemTemplate hugeCrate = ItemTemplateFactory.getInstance().getTemplate(HUGE_CRATE.getTemplateId()); + //ReflectionUtil.setPrivateField(hugeCrate, ReflectionUtil.getField(hugeCrate.getClass(), "combine"), true); + } + + public static void registerPermissionsHook(){ + try { + CtClass[] input = { + HookManager.getInstance().getClassPool().get("com.wurmonline.server.creatures.Creature"), + HookManager.getInstance().getClassPool().get("com.wurmonline.server.items.Item") + + }; + CtClass output = HookManager.getInstance().getClassPool().get("java.util.List"); + + HookManager.getInstance().registerHook("com.wurmonline.server.behaviours.VehicleBehaviour", "getVehicleBehaviours", + Descriptor.ofMethod(output, input), new InvocationHandlerFactory() { + @Override + public InvocationHandler createInvocationHandler() { + return new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + @SuppressWarnings("unchecked") + List original = (List) method.invoke(proxy, args); + Item item = (Item) args[1]; + Creature performer = (Creature) args[0]; + LinkedList permissions = new LinkedList(); + if (item.mayManage(performer)) { + int itemId = item.getTemplateId(); + if (itemId == MassStorageUnit.templateId) { + //debug("Adding manage permissions"); + permissions.add(new ActionEntry((short)669, "Manage Storage Unit", "viewing")); + } + } + if (item.maySeeHistory(performer)) { + int itemId = item.getTemplateId(); + if (itemId == MassStorageUnit.templateId) { + permissions.add(new ActionEntry((short)691, "History of Storage Unit", "viewing")); + } + } + if (!permissions.isEmpty()) { + if (permissions.size() > 1) { + Collections.sort(permissions); + original.add(new ActionEntry((short)(- permissions.size()), "Permissions", "viewing")); + } + original.addAll(permissions); + } + return original; + } + + }; + } + }); + } + catch (Exception e) { + logger.info("Permission hook: " + e.toString()); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/MiscChanges.java b/src/main/java/mod/sin/wyvern/MiscChanges.java new file mode 100644 index 0000000..25cf00f --- /dev/null +++ b/src/main/java/mod/sin/wyvern/MiscChanges.java @@ -0,0 +1,943 @@ +package mod.sin.wyvern; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modloader.ReflectionUtil; +import org.gotti.wurmunlimited.modloader.classhooks.HookException; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; +import org.gotti.wurmunlimited.modloader.classhooks.InvocationHandlerFactory; +import org.nyxcode.wurm.discordrelay.DiscordRelay; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Items; +import com.wurmonline.server.NoSuchItemException; +import com.wurmonline.server.NoSuchPlayerException; +import com.wurmonline.server.Players; +import com.wurmonline.server.Server; +import com.wurmonline.server.Servers; +import com.wurmonline.server.TimeConstants; +import com.wurmonline.server.WurmId; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTemplate; +import com.wurmonline.server.creatures.CreatureTemplateFactory; +import com.wurmonline.server.creatures.MovementScheme; +import com.wurmonline.server.creatures.NoSuchCreatureException; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.modifiers.DoubleValueModifier; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.NoSuchSkillException; +import com.wurmonline.server.skills.Skill; +import com.wurmonline.server.webinterface.WcKingdomChat; +import com.wurmonline.server.zones.NoSuchZoneException; +import com.wurmonline.server.zones.Zone; +import com.wurmonline.server.zones.Zones; +import com.wurmonline.shared.constants.Enchants; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.NotFoundException; +import javassist.bytecode.Descriptor; +import javassist.expr.ExprEditor; +import javassist.expr.FieldAccess; +import javassist.expr.MethodCall; +import mod.sin.creatures.Avenger; +import mod.sin.creatures.Charger; +import mod.sin.creatures.SpiritTroll; +import mod.sin.creatures.WyvernBlack; +import mod.sin.creatures.WyvernGreen; +import mod.sin.creatures.WyvernRed; +import mod.sin.creatures.WyvernWhite; +import mod.sin.items.SealedMap; +import mod.sin.lib.Util; +import mod.sin.wyvern.arena.Arena; +import mod.sin.wyvern.bestiary.MethodsBestiary; + +public class MiscChanges { + public static Logger logger = Logger.getLogger(MiscChanges.class.getName()); + + public static byte newCreatureType(int templateid, byte ctype) throws Exception{ + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateid); + if(ctype == 0 && (template.isAggHuman() || template.getBaseCombatRating() > 10) && !template.isUnique() && !Arena.isTitan(templateid)){ + if(Server.rand.nextInt(5) == 0){ + ctype = (byte) (Server.rand.nextInt(11)+1); + if(Server.rand.nextInt(50) == 0){ + ctype = 99; + } + } + } + return ctype; + } + + protected static HashMap defDamage = new HashMap(); + public static void setDefDamage(Creature cret, double damage){ + defDamage.put(cret, damage); + } + public static double getDefDamage(Creature cret){ + if(defDamage.containsKey(cret)){ + double theDamage = defDamage.get(cret); + defDamage.remove(cret); + return theDamage; + } + logger.severe("Severe error: could not find defDamage for creature "+cret); + return 0d; + } + + public static void sendRumour(Creature creature){ + DiscordRelay.sendToDiscord("rumors", "Rumours of " + creature.getName() + " are starting to spread."); + } + + public static int getNewVillageTiles(int tiles){ + float power = 2f; + float changeRate = 1000; + float maxNumTiles = 50000; + float tilesFloat = tiles; + // =(C2) * (1-POW(C2/$C$16, $A$24)) + (SQRT(C2)*$A$26) * POW(C2/$C$16, $A$24) + int newTiles = (int) (tilesFloat * (1-Math.pow(tilesFloat/maxNumTiles, power)) + (Math.sqrt(tilesFloat)*changeRate) * Math.pow(tilesFloat/maxNumTiles, power)); + return newTiles; + } + + private static final float PRICE_MARKUP = 1f/1.4f; + public static int getNewValue(Item item){ + if(item.getTemplateId() == SealedMap.templateId){ + float qual = item.getQualityLevel(); + float dam = item.getDamage(); + // =($A$25*A2*A2 / 10000) + float initialValue = ((float)item.getTemplate().getValue())*qual*qual/10000f; + float baseCost = 100000f; + float power = 11.0f; + // =((10+B2/4.5)*(1-POW(A2/100, $A$27)) + B2*POW(A2/100, $A$27)) * ((100 - $A$29) / 100) + int newValue = (int) (((baseCost+(initialValue/4.5f)) * (1f-Math.pow(qual/100f, power)) + initialValue*Math.pow(qual/100f, power)) * ((100f-dam)/100f) * PRICE_MARKUP); + return newValue; + } + return -10; + } + + public static void checkEnchantedBreed(Creature creature){ + int tile = Server.surfaceMesh.getTile(creature.getTileX(), creature.getTileY()); + byte type = Tiles.decodeType((int)tile); + if (type == Tiles.Tile.TILE_ENCHANTED_GRASS.id){ + logger.info("Creature "+creature.getName()+" was born on enchanted grass, and has a negative trait removed!"); + Server.getInstance().broadCastAction(creature.getName()+" was born on enchanted grass, and feels more healthy!", creature, 10); + creature.removeRandomNegativeTrait(); + } + } + + public static boolean hasCustomCorpseSize(Creature creature){ + int templateId = creature.getTemplate().getTemplateId(); + if(templateId == Avenger.templateId){ + return true; + }else if(Arena.isTitan(creature)){ + return true; + } + return false; + } + + public static boolean insertItemIntoVehicle(Item item, Item vehicle, Creature performer) { + // If can put into crates, try that + if (item.getTemplate().isBulk() && item.getRarity() == 0) { + for (Item container : vehicle.getAllItems(true)) { + if(container.getTemplateId() == ItemList.bulkContainer){ + if(container.getFreeVolume() >= item.getVolume()){ + if (item.AddBulkItem(performer, container)) { + performer.getCommunicator().sendNormalServerMessage(String.format("You put the %s in the %s in your %s.", item.getName(), container.getName(), vehicle.getName())); + return true; + } + } + } + if (container.isCrate() && container.canAddToCrate(item)) { + if (item.AddBulkItemToCrate(performer, container)) { + performer.getCommunicator().sendNormalServerMessage(String.format("You put the %s in the %s in your %s.", item.getName(), container.getName(), vehicle.getName())); + return true; + } + } + } + } + // No empty crates or disabled, try the vehicle itself + if (vehicle.getNumItemsNotCoins() < 100 && vehicle.getFreeVolume() >= item.getVolume() && vehicle.insertItem(item)) { + performer.getCommunicator().sendNormalServerMessage(String.format("You put the %s in the %s.", item.getName(), vehicle.getName())); + return true; + } else { + // Send message if the vehicle is too full + performer.getCommunicator().sendNormalServerMessage(String.format("The %s is too full to hold the %s.", vehicle.getName(), item.getName())); + return false; + } + } + public static Item getVehicleSafe(Creature pilot) { + try { + if (pilot.getVehicle() != -10) + return Items.getItem(pilot.getVehicle()); + } catch (NoSuchItemException ignored) { + } + return null; + } + + public static void miningHook(Creature performer, Item ore){ + Item vehicleItem = getVehicleSafe(performer); + if(vehicleItem != null && vehicleItem.isHollow()){ + if(insertItemIntoVehicle(ore, vehicleItem, performer)){ + return; + } + } + + // Last resort, if no suitable vehicle is found. + try { + ore.putItemInfrontof(performer); + } catch (NoSuchCreatureException | NoSuchItemException | NoSuchPlayerException | NoSuchZoneException e) { + e.printStackTrace(); + } + } + + public static void setCorpseSizes(Creature creature, Item corpse){ + if(corpse.getTemplateId() != ItemList.corpse){ + return; + } + int templateId = creature.getTemplate().getTemplateId(); + boolean sendStatus = false; + int size = 50000; + if(templateId == Avenger.templateId){ + size *= 1.2; + corpse.setSizes(size); + sendStatus = true; + }else if(Arena.isTitan(creature)){ + size *= 1.5; + corpse.setSizes(size); + sendStatus = true; + }else{ + corpse.setSizes((int)((float)(corpse.getSizeX() * (creature.getSizeModX() & 255)) / 64.0f), (int)((float)(corpse.getSizeY() * (creature.getSizeModY() & 255)) / 64.0f), (int)((float)(corpse.getSizeZ() * (creature.getSizeModZ() & 255)) / 64.0f)); + } + if(sendStatus){ + try { + Zone zone = Zones.getZone((int)corpse.getPosX() >> 2, (int)corpse.getPosY() >> 2, corpse.isOnSurface()); + zone.removeItem(corpse, true, true); + zone.addItem(corpse, true, false, false); + } catch (NoSuchZoneException e) { + e.printStackTrace(); + } + } + return; + } + + public static void setNewMoveLimits(Creature cret){ + try { + Skill strength = cret.getSkills().getSkill(102); + ReflectionUtil.setPrivateField(cret, ReflectionUtil.getField(cret.getClass(), "moveslow"), strength.getKnowledge()*4000); + ReflectionUtil.setPrivateField(cret, ReflectionUtil.getField(cret.getClass(), "encumbered"), strength.getKnowledge()*7000); + ReflectionUtil.setPrivateField(cret, ReflectionUtil.getField(cret.getClass(), "cantmove"), strength.getKnowledge()*14000); + MovementScheme moveScheme = cret.getMovementScheme(); + DoubleValueModifier stealthMod = ReflectionUtil.getPrivateField(moveScheme, ReflectionUtil.getField(moveScheme.getClass(), "stealthMod")); + if (stealthMod == null) { + stealthMod = new DoubleValueModifier((- 80.0 - Math.min(79.0, cret.getBodyControl())) / 100.0); + } else { + stealthMod.setModifier((- 80.0 - Math.min(79.0, cret.getBodyControl())) / 100.0); + } + ReflectionUtil.setPrivateField(moveScheme, ReflectionUtil.getField(moveScheme.getClass(), "stealthMod"), stealthMod); + } + catch (NoSuchSkillException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException nss) { + logger.log(Level.WARNING, "No strength skill for " + cret, (Throwable)((Object)nss)); + } + } + + public static boolean shouldBreedName(Creature creature){ + if(creature.getTemplate().getTemplateId() == WyvernBlack.templateId){ + return true; + }else if(creature.getTemplate().getTemplateId() == WyvernGreen.templateId){ + return true; + }else if(creature.getTemplate().getTemplateId() == WyvernRed.templateId){ + return true; + }else if(creature.getTemplate().getTemplateId() == WyvernWhite.templateId){ + return true; + }else if(creature.getTemplate().getTemplateId() == Charger.templateId){ + return true; + } + return creature.isHorse(); + } + + public static boolean isGhostCorpse(Creature creature){ + if(creature.getTemplate().getTemplateId() == Avenger.templateId){ + return true; + }else if(creature.getTemplate().getTemplateId() == SpiritTroll.templateId){ + return true; + } + return false; + } + + public static void doLifeTransfer(Creature creature, Item attWeapon, double defdamage, float armourMod){ + Wound[] w; + if (attWeapon.getSpellLifeTransferModifier() > 0.0f && defdamage * (double)armourMod * (double)attWeapon.getSpellLifeTransferModifier() / (double)(creature.isChampion() ? 1000.0f : 500.0f) > 500.0 && creature.getBody() != null && creature.getBody().getWounds() != null && (w = creature.getBody().getWounds().getWounds()).length > 0) { + w[0].modifySeverity(- (int)(defdamage * (double)attWeapon.getSpellLifeTransferModifier() / (double)(creature.isChampion() ? 1000.0f : (creature.getCultist() != null && creature.getCultist().healsFaster() ? 250.0f : 500.0f)))); + } + } + + public static int getWeaponType(Item weapon){ + if(weapon.enchantment == Enchants.ACID_DAM){ + return Wound.TYPE_ACID; + }else if(weapon.enchantment == Enchants.FROST_DAM){ + return Wound.TYPE_COLD; + }else if(weapon.enchantment == Enchants.FIRE_DAM){ + return Wound.TYPE_BURN; + } + return -1; + } + + public static void sendServerTabMessage(final String message, final int red, final int green, final int blue){ + DiscordRelay.sendToDiscord("event", message); + Runnable r = new Runnable(){ + public void run(){ + com.wurmonline.server.Message mess; + for(Player rec : Players.getInstance().getPlayers()){ + mess = new com.wurmonline.server.Message(rec, (byte)16, "Server", message, red, green, blue); + rec.getCommunicator().sendMessage(mess); + } + } + }; + r.run(); + } + + public static void sendGlobalFreedomChat(final Creature sender, final String message, final int red, final int green, final int blue){ + Runnable r = new Runnable(){ + public void run(){ + com.wurmonline.server.Message mess; + for(Player rec : Players.getInstance().getPlayers()){ + mess = new com.wurmonline.server.Message(sender, (byte)10, "GL-Freedom", "<"+sender.getNameWithoutPrefixes()+"> "+message, red, green, blue); + rec.getCommunicator().sendMessage(mess); + } + if (message.trim().length() > 1) { + WcKingdomChat wc = new WcKingdomChat(WurmId.getNextWCCommandId(), sender.getWurmId(), sender.getNameWithoutPrefixes(), message, false, (byte) 4, red, green, blue); + if (!Servers.isThisLoginServer()) { + wc.sendToLoginServer(); + } else { + wc.sendFromLoginServer(); + } + } + } + }; + r.run(); + } + public static void sendImportantMessage(Creature sender, String message, int red, int green, int blue){ + sendServerTabMessage("<"+sender.getNameWithoutPrefixes()+"> "+message, red, green, blue); + sendGlobalFreedomChat(sender, message, red, green, blue); + } + + public static void broadCastDeaths(Creature player, String slayers){ + sendGlobalFreedomChat(player, "slain by "+slayers, 200, 25, 25); + DiscordRelay.sendToDiscord("deaths", player+" slain by "+slayers); + } + + public static void preInit(){ + try{ + ClassPool classPool = HookManager.getInstance().getClassPool(); + final Class thisClass = MiscChanges.class; + String replace; + + // - 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/155981-wyvern-reborn-modded-pve-pvp-3x5x/", + "Custom Server Data: https://goo.gl/QRVJyC", + "Server Discord: https://discordapp.com/invite/wxEeS7d", + "Server Maps: https://www.sarcasuals.com/"}; + String str = "{" + + " com.wurmonline.server.Message mess;"; + for(int i = 0; i < infoTabLine.length; i++){ + str = str + " mess = new com.wurmonline.server.Message(player, (byte)16, \"" + infoTabTitle + "\",\"" + infoTabLine[i] + "\", 0, 255, 0);" + + " player.getCommunicator().sendMessage(mess);"; + } + str = str + "}"; + m.insertAfter(str); + + // - 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); + /*ctPlanBridgeChecks.getDeclaredMethod("checkForBuildings").setBody("{" + + " return new com.wurmonline.server.structures.PlanBridgeCheckResult(false);" + + "}");*/ + + // - Allow mailboxes and bell towers to be loaded - // + // [Disabled 10/30 by Sindusk] - Added to ItemMod using reflection instead of editing the method. + /*CtClass ctItemTemplate = classPool.get("com.wurmonline.server.items.ItemTemplate"); + ctItemTemplate.getDeclaredMethod("isTransportable").setBody("{" + + " return this.isTransportable || (this.getTemplateId() >= 510 && this.getTemplateId() <= 513) || this.getTemplateId() == 722 || this.getTemplateId() == 670;" + + "}");*/ + + // - 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); + /*ctItem.getDeclaredMethod("moveToItem").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getOwnerId")) { + m.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;" + + " }" + + "}"); + return; + } + } + });*/ + + // - Enable creature custom colors - (Used for creating custom color creatures eg. Lilith) - // + CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); + Util.setBodyDeclared(thisClass, ctCreature, "hasCustomColor", "{ return true; }"); + //ctCreature.getDeclaredMethod("hasCustomColor").setBody("{ return true; }"); + + // - Increase the amount of checks for new unique spawns by 5x - // + CtClass ctServer = classPool.get("com.wurmonline.server.Server"); + replace = "for(int i = 0; i < 5; i++){" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctServer, "run", "checkDens", replace); + /*ctServer.getDeclaredMethod("run").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("checkDens")) { + m.replace("for(int i = 0; i < 5; i++){$_ = $proceed($$);}"); + return; + } + } + });*/ + + // - Change rarity odds when a player obtains a rarity window - // + // [3/27] Removed: Merged to ServerTweaks + /*CtClass ctPlayer = classPool.get("com.wurmonline.server.players.Player"); + replace = "{ return "+MiscChanges.class.getName()+".newGetPlayerRarity(this); }"; + Util.setBodyDeclared(thisClass, ctPlayer, "getRarity", replace);*/ + //ctPlayer.getDeclaredMethod("getRarity").setBody("{ return mod.sin.wyvern.MiscChanges.newGetPlayerRarity(this); }"); + + // - Add Facebreyker to the list of spawnable uniques - // + 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);"); + + // - 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){" + + " "+MiscChanges.class.getName()+".sendServerTabMessage(this.getName()+\" just earned the title of \"+title.getName(this.isNotFemale())+\"!\", 200, 100, 0);" + + "}"; + Util.instrumentDeclared(thisClass, ctPlayer, "addTitle", "sendNormalServerMessage", replace); + /*ctPlayer.getDeclaredMethod("addTitle").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("sendNormalServerMessage")) { + m.replace("$_ = $proceed($$);" + + "if(!com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " mod.sin.wyvern.MiscChanges.sendServerTabMessage(this.getName()+\" just earned the title of \"+title.getName(this.isNotFemale())+\"!\", 200, 100, 0);" + + "}"); + return; + } + } + });*/ + + // - 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); + /*ctMethodsItems.getDeclaredMethod("improveItem").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isCombine")) { + m.replace("if(com.wurmonline.server.behaviours.MethodsItems.getImproveTemplateId(target) != 72){" + + " $_ = $proceed($$);" + + "}else{" + + " $_ = false;" + + "}"); + return; + } + } + });*/ + + // - Check new improve materials - // + replace = "int temp = "+ItemMod.class.getName()+".getModdedImproveTemplateId($1);" + + "if(temp != -10){" + + " return temp;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctMethodsItems, "getImproveTemplateId", replace); + /*ctMethodsItems.getDeclaredMethod("getImproveTemplateId").insertBefore("" + + "int temp = mod.sin.wyvern.ItemMod.getModdedImproveTemplateId($1);" + + "if(temp != -10){" + + " return temp;" + + "}");*/ + + // - Make food/drink affinities based on Item ID instead of creature ID - // + // [3/27] Removed: Merged to ServerTweaks + /*CtClass ctAffinitiesTimed = classPool.get("com.wurmonline.server.skills.AffinitiesTimed"); + replace = "if(item.getCreatorName() != null){" + + " $_ = $proceed("+MiscChanges.class.getName()+".getTimedAffinitySeed(item));" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctAffinitiesTimed, "getTimedAffinitySkill", "setSeed", replace); + CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); + replace = "$_ = $proceed($1, $2, $3, $4, performer.getName());"; + Util.instrumentDeclared(thisClass, ctItemBehaviour, "handleRecipe", "createItem", replace); + replace = "$_ = $proceed($1, $2, $3, $4, com.wurmonline.server.players.PlayerInfoFactory.getPlayerName(lastowner));"; + Util.instrumentDeclared(thisClass, ctItem, "pollFermenting", "createItem", replace); + Util.instrumentDeclared(thisClass, ctItem, "pollDistilling", "createItem", replace); + CtClass ctTempStates = classPool.get("com.wurmonline.server.items.TempStates"); + Util.instrumentDeclared(thisClass, ctTempStates, "checkForChange", "createItem", replace);*/ + + // - Fix de-priesting when gaining faith below 30 - // + // [Disabled 10/30 Sindusk] - Added to SpellCraft.SpellcraftTweaks + /*CtClass ctDbPlayerInfo = classPool.get("com.wurmonline.server.players.DbPlayerInfo"); + ctDbPlayerInfo.getDeclaredMethod("setFaith").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("min")) { + m.replace("if($2 == 20.0f && $1 < 30){" + + " $_ = $proceed(30.0f, lFaith);" + + "}else{" + + " $_ = $proceed($$);" + + "}"); + return; + } + } + }); + ctDbPlayerInfo.getDeclaredMethod("setFaith").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("setPriest")) { + m.replace("$_ = $proceed(true);"); + return; + } + } + }); + ctDbPlayerInfo.getDeclaredMethod("setFaith").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("sendAlertServerMessage")) { + m.replace("$_ = null;"); + return; + } + } + });*/ + + // - Removal of eye/face shots to headshots instead - // + HookManager.getInstance().registerHook("com.wurmonline.server.combat.Armour", "getArmourPosForPos", "(I)I", new InvocationHandlerFactory() { + + @Override + public InvocationHandler createInvocationHandler() { + return new InvocationHandler() { + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + int pos = (int) args[0]; + + if (pos == 18 || pos == 19 || pos == 20 || pos == 17) { + args[0] = 34; + //System.out.println("changed eye or face shot into headshot"); + } + + return method.invoke(proxy, args); + } + }; + } + }); + + // - Remove requirement to bless for Libila taming - // + CtClass ctMethodsCreatures = classPool.get("com.wurmonline.server.behaviours.MethodsCreatures"); + Util.instrumentDeclared(thisClass, ctMethodsCreatures, "tame", "isPriest", "$_ = false;"); + /*ctMethodsCreatures.getDeclaredMethod("tame").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isPriest")) { + m.replace("$_ = false;"); + return; + } + } + });*/ + + // - 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("$_ = false;"); + logger.info("Set isFatigue to false in action constructor."); + return; + } + } + }); + } + + // - Allow all creatures to be displayed in the Mission Ruler - // + CtClass ctMissionManager = classPool.get("com.wurmonline.server.questions.MissionManager"); + ctMissionManager.getDeclaredMethod("dropdownCreatureTemplates").instrument(new ExprEditor() { + @Override + public void edit(FieldAccess fieldAccess) throws CannotCompileException { + if (Objects.equals("baseCombatRating", fieldAccess.getFieldName())) + fieldAccess.replace("$_ = 1.0f;"); + //logger.info("Instrumented Mission Ruler to display all creatures."); + } + }); + + 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); + + Util.setReason("Allow ghost creatures to breed (Chargers)."); + Util.instrumentDeclared(thisClass, ctMethodsCreatures, "breed", "isGhost", "$_ = false;"); + + Util.setReason("Allow Life Transfer to stack with Rotting Touch."); + replace = MiscChanges.class.getName()+".doLifeTransfer(this.creature, attWeapon, defdamage, armourMod);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isWeaponCrush", replace); + + /* - REMOVED: Added to core game - + Util.setReason("Fix dragon armour dropping on logout."); + Util.instrumentDeclared(thisClass, ctItem, "sleep", "isDragonArmour", "$_ = false;"); + Util.setReason("Fix dragon armour dropping on logout."); + Util.instrumentDeclared(thisClass, ctItem, "sleepNonRecursive", "isDragonArmour", "$_ = false;");*/ + + // - Type creatures randomly in the wild - // + CtClass[] params1 = { + CtClass.intType, + CtClass.booleanType, + CtClass.floatType, + CtClass.floatType, + CtClass.floatType, + CtClass.intType, + classPool.get("java.lang.String"), + CtClass.byteType, + CtClass.byteType, + CtClass.byteType, + CtClass.booleanType, + CtClass.byteType, + CtClass.intType + }; + String desc1 = Descriptor.ofMethod(ctCreature, params1); + replace = "$10 = "+MiscChanges.class.getName()+".newCreatureType($1, $10);"; + Util.insertBeforeDescribed(thisClass, ctCreature, "doNew", desc1, replace); + + // - Send rumour messages to discord - // + Util.setReason("Send rumour messages to Discord."); + replace = MiscChanges.class.getName()+".sendRumour(toReturn);" + + "$proceed($$);"; + Util.instrumentDescribed(thisClass, ctCreature, "doNew", desc1, "broadCastSafe", replace); + + // - Allow custom creatures to be given special names when bred - // + replace = "$_ = "+MiscChanges.class.getName()+".shouldBreedName(this);"; + Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "isHorse", replace); + /*ctCreature.getDeclaredMethod("checkPregnancy").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isHorse")) { + m.replace("$_ = mod.sin.wyvern.MiscChanges.shouldBreedName(this);"); + return; + } + } + });*/ + + // - Auto-Genesis a creature born on enchanted grass - // + Util.setReason("Auto-Genesis a creature born on enchanted grass"); + replace = MiscChanges.class.getName()+".checkEnchantedBreed(newCreature);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCreature, "checkPregnancy", "saveCreatureName", replace); + /*ctCreature.getDeclaredMethod("checkPregnancy").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("saveCreatureName")) { + m.replace("mod.sin.wyvern.MiscChanges.checkEnchantedBreed(newCreature);" + + "$_ = $proceed($$);"); + return; + } + } + });*/ + + // - Allow statuettes to be used for casting even when not silver/gold - // + String desc2 = Descriptor.ofMethod(CtClass.booleanType, new CtClass[]{}); + Util.setBodyDescribed(thisClass, ctItem, "isHolyItem", desc2, "return this.template.holyItem;"); + //ctItem.getMethod("isHolyItem", desc2).setBody("return this.template.holyItem;"); + + // - Allow GM's to bypass the 5 second emote sound limit. - // + replace = "if(this.getPower() > 0){" + + " return true;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "mayEmote", replace); + /*ctPlayer.getDeclaredMethod("mayEmote").insertBefore("" + + "if(this.getPower() > 0){" + + " return true;" + + "}");*/ + + // - Allow archery against ghost targets - // + CtClass ctArchery = classPool.get("com.wurmonline.server.combat.Archery"); + CtMethod[] archeryAttacks = ctArchery.getDeclaredMethods("attack"); + for(CtMethod method : archeryAttacks){ + method.instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isGhost")) { + m.replace("$_ = false;"); + logger.info("Enabled archery against ghost targets in archery attack method."); + return; + } + } + }); + } + + // - Prevent archery altogether against certain creatures - // + CtClass[] params3 = { + ctCreature, + ctCreature, + ctItem, + CtClass.floatType, + ctAction + }; + String desc3 = Descriptor.ofMethod(CtClass.booleanType, params3); + replace = "if("+MethodsBestiary.class.getName()+".isArcheryImmune($1, $2)){" + + " return true;" + + "}"; + Util.insertBeforeDescribed(thisClass, ctArchery, "attack", desc3, 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."); + Util.insertBeforeDeclared(thisClass, ctPlayers, "broadCastDeathInfo", MiscChanges.class.getName()+".broadCastDeaths($1, $2);"); + //ctPlayers.getDeclaredMethod("broadCastDeathInfo").insertBefore("mod.sin.wyvern.MiscChanges.broadCastDeaths($1, $2);"); + + // - Reduce meditation cooldowns - // + CtClass ctCultist = classPool.get("com.wurmonline.server.players.Cultist"); + replace = "return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*8)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayRefresh", replace); + //ctCultist.getDeclaredMethod("mayRefresh").setBody("return this.path == 1 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > 28800000;"); + replace = "return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*8)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayEnchantNature", replace); + //ctCultist.getDeclaredMethod("mayEnchantNature").setBody("return this.path == 1 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 28800000;"); + replace = "return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*4)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartLoveEffect", replace); + //ctCultist.getDeclaredMethod("mayStartLoveEffect").setBody("return this.path == 1 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > 14400000;"); + replace = "return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*6)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleWarDamage", replace); + //ctCultist.getDeclaredMethod("mayStartDoubleWarDamage").setBody("return this.path == 2 && this.level > 6 && System.currentTimeMillis() - this.cooldown1 > 21600000;"); + replace = "return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*4)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartDoubleStructDamage", replace); + //ctCultist.getDeclaredMethod("mayStartDoubleStructDamage").setBody("return this.path == 2 && this.level > 3 && System.currentTimeMillis() - this.cooldown2 > 14400000;"); + replace = "return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*6)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartFearEffect", replace); + //ctCultist.getDeclaredMethod("mayStartFearEffect").setBody("return this.path == 2 && this.level > 8 && System.currentTimeMillis() - this.cooldown3 > 21600000;"); + replace = "return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*6)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartNoElementalDamage", replace); + //ctCultist.getDeclaredMethod("mayStartNoElementalDamage").setBody("return this.path == 5 && this.level > 8 && System.currentTimeMillis() - this.cooldown1 > 21600000;"); + replace = "return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*8)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "maySpawnVolcano", replace); + //ctCultist.getDeclaredMethod("maySpawnVolcano").setBody("return this.path == 5 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 28800000;"); + replace = "return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > "+(TimeConstants.HOUR_MILLIS*4)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayStartIgnoreTraps", replace); + //ctCultist.getDeclaredMethod("mayStartIgnoreTraps").setBody("return this.path == 5 && this.level > 3 && System.currentTimeMillis() - this.cooldown3 > 14400000;"); + replace = "return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > "+(TimeConstants.HOUR_MILLIS*4)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayCreatureInfo", replace); + //ctCultist.getDeclaredMethod("mayCreatureInfo").setBody("return this.path == 3 && this.level > 3 && System.currentTimeMillis() - this.cooldown1 > 14400000;"); + replace = "return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > "+(TimeConstants.HOUR_MILLIS*4)+";"; + Util.setBodyDeclared(thisClass, ctCultist, "mayInfoLocal", replace); + //ctCultist.getDeclaredMethod("mayInfoLocal").setBody("return this.path == 3 && this.level > 6 && System.currentTimeMillis() - this.cooldown2 > 14400000;"); + + Util.setReason("Adjust weapon damage type based on the potion/salve applied."); + replace = "int wt = mod.sin.wyvern.MiscChanges.getWeaponType($1);" + + "if(wt != -1){" + + " type = wt;" + + " return wt;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctCombatHandler, "getType", 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); + + 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."); + } + } + }); + + Util.setReason("Increase deed upkeep by modifying the amount of tiles it thinks it has."); + CtClass ctGuardPlan = classPool.get("com.wurmonline.server.villages.GuardPlan"); + replace = "$_ = "+MiscChanges.class.getName()+".getNewVillageTiles(vill.getNumTiles());"; + Util.instrumentDeclared(thisClass, ctGuardPlan, "getMonthlyCost", "getNumTiles", replace); + + Util.setReason("Adjust value for certain items."); + replace = "int newVal = "+MiscChanges.class.getName()+".getNewValue(this);" + + "if(newVal > 0){" + + " return newVal;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctItem, "getValue", replace); + + //Util.setReason("Fix Glimmersteel & Adamantine veins from being depleted rapidly."); + CtClass ctCaveWallBehaviour = classPool.get("com.wurmonline.server.behaviours.CaveWallBehaviour"); + CtClass[] params6 = { + ctAction, + ctCreature, + ctItem, + CtClass.intType, + CtClass.intType, + CtClass.booleanType, + CtClass.intType, + CtClass.intType, + CtClass.intType, + CtClass.shortType, + CtClass.floatType + }; + String desc6 = Descriptor.ofMethod(CtClass.booleanType, params6); + // [3/27] Removed: Merged to ServerTweaks. + /*replace = "resource = com.wurmonline.server.Server.getCaveResource(tilex, tiley);" + + "if (resource == 65535) {" + + " resource = com.wurmonline.server.Server.rand.nextInt(10000);" + + "}" + + "if (resource > 1000 && (itemTemplateCreated == 693 || itemTemplateCreated == 697)) {" + + " resource = com.wurmonline.server.Server.rand.nextInt(1000);" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctCaveWallBehaviour, "action", desc6, "getDifficultyForTile", replace);*/ + + Util.setReason("Allow players to mine directly to BSB's in vehicles."); + replace = "$_ = null;" + + MiscChanges.class.getName()+".miningHook(performer, newItem);"; + Util.instrumentDescribed(thisClass, ctCaveWallBehaviour, "action", desc6, "putItemInfrontof", replace); + + // -- 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); + + Util.setReason("Allow ghost creatures to drop corpses."); + replace = "if("+MiscChanges.class.getName()+".isGhostCorpse(this)){" + + " $_ = false;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCreature, "die", "isGhost", replace); + + Util.setReason("Set custom corpse sizes."); + replace = "$_ = $proceed($$);" + + "if("+MiscChanges.class.getName()+".hasCustomCorpseSize(this)){" + + " "+MiscChanges.class.getName()+".setCorpseSizes(this, corpse);" + + "}"; + Util.instrumentDeclared(thisClass, ctCreature, "die", "addItem", replace); + + Util.setReason("Fix permissions in structures so players cannot cast spells unless they have enter permission."); + CtClass ctStructure = classPool.get("com.wurmonline.server.structures.Structure"); + replace = "if(com.wurmonline.server.behaviours.Actions.isActionDietySpell(action)){" + + " return this.mayPass(performer);" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctStructure, "isActionAllowed", "isActionImproveOrRepair", replace); + + //1f+0.5f*(1f-Math.pow(2, -Math.pow((eff-1f), pow1)/pow2)) + Util.setReason("Fix 100+ quality or power making certain interaction broken."); + replace = "{" + + "double pow1 = 1.0;" + + "double pow2 = 3.0;" + + "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.setReason("Fix Oakshell glance rates from going above 100% when cast power is above 100."); + replace = "if(defender.getBonusForSpellEffect((byte)22) >= 0.0f){" + + " evasionChance = Math.min(0.4f, evasionChance);" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isTowerBasher", replace);*/ + + /*Util.setReason("Ensure players always deal a wound and are not limited by 'does no real damage' messages."); + replace = MiscChanges.class.getName()+".setDefDamage(this.creature, defdamage);" + + "defdamage = 99999d;" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "isTowerBasher", replace); + replace = "defdamage = "+MiscChanges.class.getName()+".getDefDamage(this.creature);" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCombatHandler, "setDamage", "getBattle", replace);*/ + + } catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { + throw new HookException((Throwable)e); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/Soulstealing.java b/src/main/java/mod/sin/wyvern/Soulstealing.java new file mode 100644 index 0000000..13b8455 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/Soulstealing.java @@ -0,0 +1,92 @@ +package mod.sin.wyvern; + +import java.util.ArrayList; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modsupport.actions.ModActions; + +import com.wurmonline.server.Items; +import com.wurmonline.server.Server; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.zones.VolaTile; +import com.wurmonline.server.zones.Zones; + +import mod.sin.actions.items.EternalReservoirCheckFuelAction; +import mod.sin.actions.items.EternalReservoirRefuelAction; +import mod.sin.actions.items.SoulstealAction; +import mod.sin.items.EternalReservoir; + +public class Soulstealing { + public static final Logger logger = Logger.getLogger(Soulstealing.class.getName()); + public static ArrayList soulForges = new ArrayList(); + public static void pollSoulForge(Item soulForge){ + int tilex = soulForge.getTileX(); + int tiley = soulForge.getTileY(); + int range = (int) (soulForge.getCurrentQualityLevel()/10f); + int fuel = soulForge.getData1(); + logger.info("Polling eternal reservoir at ("+tilex+", "+tiley+") [range "+range+"] "); + if(fuel > 15){ + int sx = Zones.safeTileX(tilex - range); + int sy = Zones.safeTileY(tiley - range); + int ex = Zones.safeTileX(tilex + range); + int ey = Zones.safeTileY(tiley + range); + int x, y; + for (x = sx; x <= ex; ++x) { + for (y = sy; y <= ey; ++y) { + VolaTile t = Zones.getTileOrNull(x, y, soulForge.isOnSurface()); + if (t == null){ + continue; + } + Creature[] crets2 = t.getCreatures(); + for (Creature lCret : crets2) { + if(lCret.isBranded() && lCret.isCarnivore()){ + int hunger = lCret.getStatus().getHunger(); + if(hunger > 10000 && fuel > 50){ + logger.info("Detected branded carnivore "+lCret.getName()+" at "+lCret.getTileX()+", "+lCret.getTileY()+" with hunger "+hunger); + lCret.getStatus().modifyHunger(-10000, 1); + Server.getInstance().broadCastAction("The "+lCret.getName()+" is visited by an ethereal creature, and seems less hungry.", lCret, 10); + fuel -= 50; + } + } + } + Item[] items = t.getItems(); + for(Item item : items){ + if(item.isForgeOrOven()){ + if(item.isOnFire()){ + if(item.getTemperature() < 20000 && fuel > 15){ + logger.info("Found lit container "+item.getName()+" at "+item.getTileX()+", "+item.getTileY()+" with temperature "+item.getTemperature()); + item.setTemperature((short) (item.getTemperature()+10000)); + Server.getInstance().broadCastMessage("The "+item.getName()+" is visited by an ethereal creature, and is refueled.", item.getTileX(), item.getTileY(), item.isOnSurface(), 10); + fuel -= 15; + } + } + } + } + } + } + soulForge.setData1(fuel); + }else{ + logger.info("Eternal Reservoir is low on fuel, skipping the poll."); + } + } + public static void pollSoulForges(){ + logger.info("Polling eternal reservoirs..."); + for(Item item : Items.getAllItems()){ + if(item.getTemplateId() == EternalReservoir.templateId){ + if(!soulForges.contains(item)){ + logger.info("Found eternal reservoir that was not in the list, adding it now..."); + soulForges.add(item); + } // Need to check for culling after, don't know how + } + } + for(Item soulForge : soulForges){ + pollSoulForge(soulForge); + } + } + public static void registerActions(){ + ModActions.registerAction(new EternalReservoirCheckFuelAction()); + ModActions.registerAction(new EternalReservoirRefuelAction()); + ModActions.registerAction(new SoulstealAction()); + } +} diff --git a/src/main/java/mod/sin/wyvern/TreasureChests.java b/src/main/java/mod/sin/wyvern/TreasureChests.java new file mode 100644 index 0000000..113a91b --- /dev/null +++ b/src/main/java/mod/sin/wyvern/TreasureChests.java @@ -0,0 +1,382 @@ +package mod.sin.wyvern; + +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; + +import com.wurmonline.server.FailedException; +import com.wurmonline.server.Server; +import com.wurmonline.server.creatures.CreatureTemplate; +import com.wurmonline.server.creatures.CreatureTemplateCreator; +import com.wurmonline.server.creatures.CreatureTemplateFactory; +import com.wurmonline.server.creatures.CreatureTemplateIds; +import com.wurmonline.server.creatures.NoSuchCreatureTemplateException; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.NoSuchTemplateException; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.NotFoundException; +import javassist.expr.ExprEditor; +import javassist.expr.MethodCall; +import mod.sin.items.AffinityOrb; + +public class TreasureChests { + public static void doItemSpawn(Item inventory, int[] templateTypes, float startQl, float qlValRange, int maxNums) { + /*if (item.getOwnerId() != -10) { + return; + }*/ + /*Item[] currentItems = item.getAllItems(true); + boolean[] hasTypes = new boolean[templateTypes.length]; + block2 : for (Item it : currentItems) { + for (int x = 0; x < templateTypes.length; ++x) { + if (templateTypes[x] != it.getTemplateId()) continue; + hasTypes[x] = true; + continue block2; + } + } + for (int x = 0; x < hasTypes.length; ++x) {*/ + for (int x = 0; x < templateTypes.length; ++x){ + //if (hasTypes[x]) continue; // Disabled so it doesn't mess with my things + for (int nums = 0; nums < maxNums; ++nums) { + try{ + byte rrarity; + int templateType = templateTypes[x]; + /*if (onGround) { + ItemFactory.createItem(templateType, startQl + Server.rand.nextFloat() * qlValRange, item.getPosX() + 0.3f, item.getPosY() + 0.3f, 65.0f, item.isOnSurface(), (byte) 0, -10, ""); + continue; + }*/ + boolean isBoneCollar = templateType == 867; + rrarity = (byte) (Server.rand.nextInt(100) == 0 || isBoneCollar ? 1 : 0); + if (rrarity > 0) { + rrarity = (byte) (Server.rand.nextInt(100) == 0 && isBoneCollar ? 2 : 1); + } + if (rrarity > 1) { + rrarity = (byte) (Server.rand.nextInt(100) == 0 && isBoneCollar ? 3 : 2); + } + float newql = startQl + Server.rand.nextFloat() * qlValRange; + + Item toInsert = ItemFactory.createItem(templateType, newql, rrarity, ""); + + if (templateType == ItemList.statueHota){ + toInsert.setAuxData((byte)Server.rand.nextInt(10)); + toInsert.setWeight(50000, true); + } + if (templateType == ItemList.eggLarge) { + toInsert.setData1(CreatureTemplateCreator.getRandomDragonOrDrakeId()); + } + if (templateType == ItemList.drakeHide) { + int colorId = CreatureTemplateCreator.getRandomDrakeId(); + toInsert.setData1(colorId); + CreatureTemplate cTemplate = CreatureTemplateFactory.getInstance().getTemplate(colorId); + String creatureName = cTemplate.getName().toLowerCase(); + if (!toInsert.getName().contains(creatureName)){ + toInsert.setName(creatureName.toLowerCase() + " " + toInsert.getTemplate().getName()); + } + toInsert.setWeight(50+Server.rand.nextInt(100), true); + } + if (templateType == ItemList.dragonScale) { + int[] dragonIds = new int[]{CreatureTemplateIds.DRAGON_BLACK_CID, CreatureTemplateIds.DRAGON_BLUE_CID, CreatureTemplateIds.DRAGON_GREEN_CID, + CreatureTemplateIds.DRAGON_RED_CID, CreatureTemplateIds.DRAGON_WHITE_CID}; + int colorId = dragonIds[Server.rand.nextInt(dragonIds.length)]; + toInsert.setData1(colorId); + CreatureTemplate cTemplate = CreatureTemplateFactory.getInstance().getTemplate(colorId); + String creatureName = cTemplate.getName().toLowerCase(); + if (!toInsert.getName().contains(creatureName)){ + toInsert.setName(creatureName.toLowerCase() + " " + toInsert.getTemplate().getName()); + } + toInsert.setWeight(100+Server.rand.nextInt(150), true); + } // if + if (templateType == ItemList.riftCrystal || templateType == ItemList.riftWood || templateType == ItemList.riftStone) { + toInsert.setHasNoDecay(true); + } // if + inventory.insertItem(toInsert, true); + continue; + } catch (NoSuchTemplateException | FailedException | NoSuchCreatureTemplateException e) { + e.printStackTrace(); + } + } + } + } + + public static void newFillTreasureChest(Item item, int auxdata) { + // AuxData = random value 0-99 + // 0-59 = rare, 60-89 = supreme, 90-99 = fantastic + int[] normalGems = new int[]{ItemList.emerald, ItemList.ruby, ItemList.opal, ItemList.diamond, ItemList.sapphire}; + int[] starGems = new int[]{375, 377, 379, 381, 383}; + int[] lumps = new int[]{44, 45, 46, 47, 48, 49, 205, 220, 221, 223, 694, 698, 837}; + int[] potions = new int[]{871, 874, 875, 876, 877, 878, 879, 881, 883}; + + /*int[] usefulItems = {ItemList.axeSmall, ItemList.shieldMedium, ItemList.hatchet, ItemList.knifeCarving, + ItemList.pickAxe, ItemList.swordLong, ItemList.saw, ItemList.shovel, ItemList.rake, ItemList.hammerMetal, + ItemList.hammerWood, ItemList.anvilSmall, ItemList.cheeseDrill, ItemList.swordShort, ItemList.swordTwoHander, + ItemList.shieldSmallWood, ItemList.shieldSmallMetal, ItemList.shieldMediumWood, ItemList.shieldLargeWood, + ItemList.shieldLargeMetal, ItemList.axeHuge, ItemList.axeMedium, ItemList.knifeButchering, + ItemList.fishingRodIronHook, ItemList.stoneChisel, ItemList.leatherGlove, ItemList.leatherJacket, + ItemList.leatherBoot, ItemList.leatherSleeve, ItemList.leatherCap, ItemList.leatherHose, ItemList.clothGlove, + ItemList.clothShirt, ItemList.clothSleeve, ItemList.clothJacket, ItemList.clothHose, ItemList.clothShoes, + ItemList.studdedLeatherSleeve, ItemList.studdedLeatherBoot, ItemList.studdedLeatherCap, + ItemList.studdedLeatherHose, ItemList.studdedLeatherGlove, ItemList.studdedLeatherJacket, + ItemList.spindle, ItemList.flintSteel, ItemList.fishingRodWoodenHook, ItemList.stoneOven, ItemList.forge, + ItemList.anvilLarge, ItemList.cartSmall, ItemList.needleIron, ItemList.loom, ItemList.sickle, ItemList.scythe, + ItemList.gloveSteel, ItemList.chainBoot, ItemList.chainHose, ItemList.chainJacket, ItemList.chainSleeve, + ItemList.chainGlove, ItemList.chainCoif, ItemList.plateBoot, ItemList.plateHose, ItemList.plateJacket, + ItemList.plateSleeve, ItemList.plateGauntlet, ItemList.helmetBasinet, ItemList.helmetGreat, ItemList.helmetOpen, + ItemList.maulLarge, ItemList.maulSmall, ItemList.maulMedium, ItemList.whetStone, ItemList.pelt, ItemList.ropeTool, + ItemList.guardTower, ItemList.file, ItemList.awl, ItemList.leatherKnife, ItemList.scissors, ItemList.clayShaper, + ItemList.spatula, ItemList.bowShort, ItemList.bowMedium, ItemList.bowLong, ItemList.dragonLeatherSleeve, + ItemList.dragonLeatherBoot, ItemList.dragonLeatherCap, ItemList.dragonLeatherHose, ItemList.dragonLeatherGlove, + ItemList.dragonLeatherJacket, ItemList.dragonScaleBoot, ItemList.dragonScaleHose, ItemList.dragonScaleJacket, + ItemList.dragonScaleSleeve, ItemList.dragonScaleGauntlet, ItemList.boatRowing, ItemList.boatSailing, + ItemList.trowel, ItemList.statuetteFo, ItemList.statuetteLibila, ItemList.statuetteMagranon, + ItemList.statuetteVynora, ItemList.cartLarge, ItemList.cog, ItemList.corbita, ItemList.knarr, ItemList.caravel, + ItemList.saddle, ItemList.horseShoe, ItemList.meditationRugOne, ItemList.meditationRugTwo, + ItemList.meditationRugThree, ItemList.meditationRugFour, ItemList.groomingBrush, ItemList.spearLong, + ItemList.halberd, ItemList.spearSteel, ItemList.clothHood, ItemList.wagon, ItemList.boneCollar, + ItemList.spinningWheel, ItemList.smelter, ItemList.halterRope};*/ + + // Generate Rare Chest + if (auxdata < 60) { + if(item.getTemplateId() == ItemList.treasureChest){ + item.setRarity((byte)1); + } + // Generate source, addy / glimmer, gem + int[] templateTypes = new int[]{ItemList.sourceCrystal, ItemList.adamantineBar, + ItemList.glimmerSteelBar, normalGems[Server.rand.nextInt(5)]}; + doItemSpawn(item, templateTypes, 70.0f, 30.0f, 1); + + // Generate seryll + if (Server.rand.nextBoolean()) { + doItemSpawn(item, new int[]{ItemList.seryllBar}, 60.0f, 20.0f, 1); + } // if + + /*// Generate meal + if (Server.rand.nextBoolean()) { + this.doItemSpawn(item, new int[]{ItemList.steak}, (float)auxdata, 60.0f-(float)auxdata, 1, false); + } // if*/ + + // Generate random lump + if (Server.rand.nextBoolean()) { + doItemSpawn(item, new int[]{lumps[Server.rand.nextInt(13)]}, 80.0f, 20.0f, 1); + } // if + + // Generate yellow potion + if (Server.rand.nextInt(5) == 0) { + doItemSpawn(item, new int[]{ItemList.potionIllusion}, 10.0f, 90.0f, 1); + } // if + + // Generate fireworks + if (Server.rand.nextInt(20) == 0) { + doItemSpawn(item, new int[]{ItemList.fireworks}, (float)auxdata, 60.0f-(float)auxdata, 1); + } // if + + // Generate affinity orb + if (Server.rand.nextInt(200-auxdata) == 0){ + doItemSpawn(item, new int[]{22767}, 80.0f, 10.0f, 1); // Affinity Orb + } + + /*// Generate random tool + if (Server.rand.nextInt(4) == 0) { + // generate random tool thingy + this.doItemSpawn(item, templateTypes6, 25.0f, 50.0f, 1, false); + } // if*/ + + /*// Generate source + if (Server.rand.nextInt(4) == 0) { + int[] templateTypes7 = new int[]{ItemList.skinWater}; + // put 0.1-0.2kg of source in the water skin + this.doItemSpawn(item, templateTypes7, 25.0f, 50.0f, 1, false); + } // if*/ + + // Generate random potion + if (Server.rand.nextInt(10) == 0) { + doItemSpawn(item, new int[]{potions[Server.rand.nextInt(potions.length)]}, 50.0f, 50.0f, 1); + } // if + + // Generate rift items + switch (Server.rand.nextInt(3)) { + case 0: + doItemSpawn(item, new int[]{ItemList.riftStone}, 90.0f, 10.0f, 1); + break; + case 1: + doItemSpawn(item, new int[]{ItemList.riftCrystal}, 90.0f, 10.0f, 1); + break; + case 2: + doItemSpawn(item, new int[]{ItemList.riftWood}, 90.0f, 10.0f, 1); + break; + } // switch + + // Generate Supreme Chest + } else if (auxdata < 90) { + if(item.getTemplateId() == ItemList.treasureChest){ + item.setRarity((byte)2); + } + // Generate source, gem + int[] templateTypes = new int[]{ItemList.sourceCrystal, 374 + Server.rand.nextInt(10)}; + // vessel the gem + doItemSpawn(item, templateTypes, 80.0f, 20.0f, 1); + + // Spawn addy / glimmer + int[] templateTypes2 = new int[]{ItemList.adamantineBar, ItemList.glimmerSteelBar}; + doItemSpawn(item, templateTypes2, 80.0f, 20.0f, 2 + Server.rand.nextInt(2)); + + // Generate seryll + int[] templateTypes3 = new int[]{ItemList.seryllBar}; + doItemSpawn(item, templateTypes3, 80.0f, 20.0f, 1 + Server.rand.nextInt(3)); + + /*// Generate meal + if (Server.rand.nextBoolean()) { + this.doItemSpawn(item, new int[]{ItemList.steak}, (float)auxdata, 90.0f-(float)auxdata, 2, false); + } // if*/ + + // Generate fireworks + if (Server.rand.nextInt(10) == 0) { + doItemSpawn(item, new int[]{ItemList.fireworks}, (float)auxdata, 90.0f-(float)auxdata, 1); + } // if + + // Generate affinity orb + if (Server.rand.nextInt(150-auxdata) == 0){ + doItemSpawn(item, new int[]{22767}, 90.0f, 5.0f, 1); // Affinity Orb + } + + /*// Generate source + if (Server.rand.nextBoolean()) { + int[] templateTypes6 = new int[]{ItemList.skinWater}; + // put 0.2-0.3kg of source in the water skin + this.doItemSpawn(item, templateTypes6, 25.0f, 50.0f, 1, false); + } // if*/ + + // Generate dragon hide / scale + if (Server.rand.nextInt(10) == 0) { + doItemSpawn(item, new int[]{371 + (Server.rand.nextBoolean() ? 0 : 1)}, 80.0f, 20.0f, 1); + } // if + + // Generate rift items + doItemSpawn(item, new int[]{ItemList.riftStone}, 90.0f, 10.0f, 1); + doItemSpawn(item, new int[]{ItemList.riftCrystal}, 90.0f, 10.0f, 1); + doItemSpawn(item, new int[]{ItemList.riftWood}, 90.0f, 10.0f, 1); + + // Generate Fantastic Chest + } else { + if(item.getTemplateId() == ItemList.treasureChest){ + item.setRarity((byte)3); + } + // Generate source, gem + int[] templateTypes = new int[]{ItemList.sourceCrystal, starGems[Server.rand.nextInt(starGems.length)]}; + doItemSpawn(item, templateTypes, 90.0f, 10.0f, 1); + + // Generate addy / glimmer + int[] templateTypes2 = new int[]{ItemList.adamantineBar, ItemList.glimmerSteelBar}; + doItemSpawn(item, templateTypes2, 80.0f, 20.0f, 3 + Server.rand.nextInt(3)); + + // Generate seryll + int[] templateTypes3 = new int[]{ItemList.seryllBar}; + doItemSpawn(item, templateTypes3, 80.0f, 20.0f, 2 + Server.rand.nextInt(3)); + + // Generate affinity orb + if(Server.rand.nextBoolean()){ + doItemSpawn(item, new int[]{AffinityOrb.templateId}, 99.0f, 1.0f, 1); // Affinity Orb + } + + /*// Generate source + if (Server.rand.nextInt(4) != 0) { + int[] templateTypes5 = new int[]{ItemList.skinWater}; + // put 0.5-0.7kg of source in the water skin + this.doItemSpawn(item, templateTypes5, 25.0f, 50.0f, 1, false); + } // if*/ + + // Generate fireworks + if (Server.rand.nextInt(5) == 0) { + doItemSpawn(item, new int[]{ItemList.fireworks}, (float)auxdata, 100.0f-(float)auxdata, 1); + } // if + + /* + // Generate inscriber + if (Server.rand.nextInt(4) == 0) { + int[] templateTypes7 = new int[]{ItemList.inscriber}; + this.doItemSpawn(item, templateTypes7, 99.0f, 1.0f, 1, false); + } // if + */ + + // Generate dragon hide / scale + if (Server.rand.nextInt(10) == 0) { + doItemSpawn(item, new int[]{371 + (Server.rand.nextBoolean() ? 0 : 1)}, 90.0f, 10.0f, 1); + } // if + + // Generate spyglass + if (Server.rand.nextInt(100) == 0) { + doItemSpawn(item, new int[]{ItemList.spyglass}, 99.0f, 1.0f, 1); + } // if + + // Generate BoK + if (Server.rand.nextInt(100) == 0) { + doItemSpawn(item, new int[]{ItemList.bagKeeping}, 99.0f, 1.0f, 1); + } // if + + // Generate rift items + doItemSpawn(item, new int[]{ItemList.riftStone}, 90.0f, 10.0f, 1 + Server.rand.nextInt(3)); + doItemSpawn(item, new int[]{ItemList.riftCrystal}, 90.0f, 10.0f, 1 + Server.rand.nextInt(3)); + doItemSpawn(item, new int[]{ItemList.riftWood}, 90.0f, 10.0f, 1 + Server.rand.nextInt(3)); + + // Generate OP items + int rand = Server.rand.nextInt(500); + int[] fantasticLoot = {}; + int amount = 1; + if(rand < 249){ + fantasticLoot = new int[]{ItemList.drakeHide}; + amount = 3; + // Three chunks of random color dragon scale. + } else if(rand < 349){ + fantasticLoot = new int[]{ItemList.dragonScale}; + amount = 3; + // Random hota statue. + } else if(rand < 414){ + fantasticLoot = new int[]{ItemList.statueHota}; + // Rare Bone & Helmet + } else if (rand < 464) { + fantasticLoot = new int[]{ItemList.boneCollar/*, Server.rand.nextBoolean() ? ItemList.helmetBasinet : ItemList.helmetGreat*/}; + // 1/100 chance of supreme, 1/10,000 of fantastic + // Sorcery + } else if (rand < 490) { + fantasticLoot = new int[]{795 + Server.rand.nextInt(16)}; + // Dragon Egg + } else { + fantasticLoot = new int[]{ItemList.eggLarge}; + } // else + doItemSpawn(item, fantasticLoot, 99.0f, 1.0f, amount); + } + } // fillTreasureChest + + public static void preInit() throws NotFoundException, CannotCompileException{ + ClassPool classPool = HookManager.getInstance().getClassPool(); + + CtClass ctZone = classPool.get("com.wurmonline.server.zones.Zone"); + CtMethod ctCreateTreasureChest = ctZone.getDeclaredMethod("createTreasureChest"); + // Increase treasure chest AuxData by 2. + ctCreateTreasureChest.instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("setAuxData")) { + m.replace("$_ = $proceed((byte)(com.wurmonline.server.Server.rand.nextInt(100)));"); + return; + } + } + }); + + // New treasure chest fill. + CtClass ctItem = classPool.get("com.wurmonline.server.items.Item"); + ctItem.getDeclaredMethod("fillTreasureChest").setBody("{" + + " mod.sin.wyvern.TreasureChests.newFillTreasureChest(this, this.getAuxData());" + + " logger.info(\"Spawned treasure chest level \"+this.getAuxData()+\" at \"+(this.getPosX()/4)+\", \"+(this.getPosY()/4));" + + "}"); + + // Add an Affinity Orb to the chest. + /*ctItem.getDeclaredMethod("fillTreasureChest").insertAfter("" + + "if(this.getAuxData() >= 8){" + + " int[] templateTypes8 = new int[]{22767};" + + " this.spawnItemSpawn(templateTypes8, 99.0f, 1.0f, 1, false);" + + "}" + + "logger.info(\"Spawned treasure chest level \"+this.getAuxData()+\" at \"+(this.getPosX()/4)+\", \"+(this.getPosY()/4));");*/ + } +} diff --git a/src/main/java/mod/sin/wyvern/WyvernMods.java b/src/main/java/mod/sin/wyvern/WyvernMods.java new file mode 100644 index 0000000..a3e1387 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/WyvernMods.java @@ -0,0 +1,322 @@ +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 org.gotti.wurmunlimited.modloader.ReflectionUtil; +import org.gotti.wurmunlimited.modloader.classhooks.HookException; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; +import org.gotti.wurmunlimited.modloader.interfaces.Configurable; +import org.gotti.wurmunlimited.modloader.interfaces.Initable; +import org.gotti.wurmunlimited.modloader.interfaces.ItemTemplatesCreatedListener; +import org.gotti.wurmunlimited.modloader.interfaces.PreInitable; +import org.gotti.wurmunlimited.modloader.interfaces.ServerPollListener; +import org.gotti.wurmunlimited.modloader.interfaces.ServerStartedListener; +import org.gotti.wurmunlimited.modloader.interfaces.WurmServerMod; +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.deities.Deities; +import com.wurmonline.server.deities.Deity; +import com.wurmonline.server.items.NoSuchTemplateException; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.skills.SkillList; +import com.wurmonline.server.skills.SkillSystem; +import com.wurmonline.server.skills.SkillTemplate; + +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.arena.Arena; +import mod.sin.wyvern.arena.SupplyDepots; +import mod.sin.wyvern.bestiary.MethodsBestiary; +import mod.sin.wyvern.mastercraft.Mastercraft; + +public class WyvernMods +implements WurmServerMod, Configurable, PreInitable, Initable, ItemTemplatesCreatedListener, ServerStartedListener, ServerPollListener { + private static Logger logger = Logger.getLogger(WyvernMods.class.getName()); + public static boolean espCounter = false; + public static boolean enableDepots = false; + + boolean bDebug = false; + + public static boolean customCommandHandler(ByteBuffer byteBuffer, Player player) throws UnsupportedEncodingException{ + byte[] tempStringArr = new byte[byteBuffer.get() & 255]; + byteBuffer.get(tempStringArr); + String message = new String(tempStringArr, "UTF-8"); + tempStringArr = new byte[byteBuffer.get() & 255]; + byteBuffer.get(tempStringArr); + //String title = new String(tempStringArr, "UTF-8"); + if(player.mayMute() && message.startsWith("!")){ + logger.info("Player "+player.getName()+" used custom WyvernMods command: "+message); + if(message.startsWith("!toggleESP") && player.getPower() >= 5){ + espCounter = !espCounter; + player.getCommunicator().sendSafeServerMessage("ESP counter for this server is now = "+espCounter); + }else if(message.startsWith("!toggleDepots") && player.getPower() >= 5){ + enableDepots = !enableDepots; + player.getCommunicator().sendSafeServerMessage("Arena depots for this server is now = "+enableDepots); + }else{ + player.getCommunicator().sendSafeServerMessage("Custom command not found: "+message); + } + return true; + } + return false; + } + + 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."); + } + + 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); + } + } + + public void preInit() { + logger.info("Pre-Initializing."); + try { + ModActions.init(); + //Bounty.preInit(this); + TreasureChests.preInit(); + MiscChanges.preInit(); + Arena.preInit(); + AntiCheat.preInit(); + Mastercraft.preInit(); + Mastercraft.addNewTitles(); + SupplyDepots.preInit(); + + ClassPool classPool = HookManager.getInstance().getClassPool(); + + // - Enable custom command handler - // + CtClass ctCommunicator = classPool.get("com.wurmonline.server.creatures.Communicator"); + ctCommunicator.getDeclaredMethod("reallyHandle").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("reallyHandle_CMD_MESSAGE")) { + m.replace("java.nio.ByteBuffer tempBuffer = $1.duplicate();" + + "if(!mod.sin.wyvern.WyvernMods.customCommandHandler($1, this.player)){" + + " $_ = $proceed(tempBuffer);" + + "}"); + return; + } + } + }); + } catch (CannotCompileException | NotFoundException | IllegalArgumentException | ClassCastException e) { + throw new HookException((Throwable)e); + } + } + + @Override + public void init() { + logger.info("Initializing."); + ModCreatures.init(); + ModVehicleBehaviours.init(); + + // Vanilla: + logger.info("Registering Vanilla creature changes."); + ModCreatures.addCreature(new Bison()); + + // Epic: + logger.info("Registering Epic creatures."); + ModCreatures.addCreature(new LavaFiend()); + ModCreatures.addCreature(new SolDemon()); + ModCreatures.addCreature(new Worg()); + + // Wyverns: + ModCreatures.addCreature(new WyvernBlack()); + ModCreatures.addCreature(new WyvernGreen()); + ModCreatures.addCreature(new WyvernRed()); + ModCreatures.addCreature(new WyvernWhite()); + + // Flavor Mobs: + ModCreatures.addCreature(new Avenger()); + ModCreatures.addCreature(new Charger()); + ModCreatures.addCreature(new ForestSpider()); + ModCreatures.addCreature(new Giant()); + ModCreatures.addCreature(new HornedPony()); + ModCreatures.addCreature(new LargeBoar()); + ModCreatures.addCreature(new SpiritTroll()); + + // Bosses: + logger.info("Registering Custom Boss creatures."); + ModCreatures.addCreature(new Reaper()); + ModCreatures.addCreature(new SpectralDrake()); + // Uniques: + ModCreatures.addCreature(new Facebreyker()); + + // Titans: + ModCreatures.addCreature(new Ifrit()); + ModCreatures.addCreature(new Lilith()); + // Titan Spawns: + ModCreatures.addCreature(new IfritFiend()); + ModCreatures.addCreature(new IfritSpider()); + ModCreatures.addCreature(new LilithWraith()); + ModCreatures.addCreature(new LilithZombie()); + + // NPC's + logger.info("Registering Custom NPC creatures."); + ModCreatures.addCreature(new RobZombie()); + ModCreatures.addCreature(new MacroSlayer()); + + Bounty.init(); + + Mastercraft.changeExistingTitles(); + } + + @Override + public void onItemTemplatesCreated() { + logger.info("Creating Item Mod items."); + ItemMod.createItems(); + logger.info("Creating Cache items."); + Caches.createItems(); + try { + logger.info("Editing existing item templates."); + ItemMod.modifyItems(); + logger.info("Registering permissions hook for custom items."); + ItemMod.registerPermissionsHook(); + } catch (NoSuchTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + + @Override + public void onServerStarted() { + try { + logger.info("Registering Item Mod creation entries."); + ItemMod.initCreationEntries(); + logger.info("Registering Item Mod actions."); + ItemMod.registerActions(); + logger.info("Registering Cache actions."); + Caches.registerActions(); + logger.info("Registering Soulstealer actions."); + Soulstealing.registerActions(); + logger.info("Registering Custom actions."); + ModActions.registerAction(new UnequipAllAction()); + ModActions.registerAction(new ReceiveMailAction()); + logger.info("Registering Arena actions."); + //ModActions.registerAction(new VillageTeleportAction()); // [3/28/18] Disabled - Highway Portals added instead. + ModActions.registerAction(new ArenaTeleportAction()); + ModActions.registerAction(new ArenaEscapeAction()); + logger.info("Setting custom creature corpse models."); + MethodsBestiary.setTemplateVariables(); + if(Deities.getDeity(101) != null){ // Edit Breyk player god + Deity breyk = Deities.getDeity(101); + // Add some defining affinities + breyk.repairer = true; + breyk.learner = true; + breyk.deathProtector = true; + breyk.befriendCreature = true; + // Remove some affinities + breyk.warrior = false; + breyk.healer = false; + breyk.clayAffinity = false; + } + if(Deities.getDeity(102) != null){ // Edit Cyberhusky player god + Deity cyberhusky = Deities.getDeity(102); + // Add some defining affinities + cyberhusky.hateGod = true; + cyberhusky.allowsButchering = true; + cyberhusky.warrior = true; + // Remove some affinities + cyberhusky.woodAffinity = false; + cyberhusky.befriendCreature = false; + } + + //espCounter = Servers.localServer.PVPSERVER; // Enables on PvP server by default. + //espCounter = false; + + SkillTemplate stealing = SkillSystem.templates.get(SkillList.STEALING); + try { + ReflectionUtil.setPrivateField(stealing, ReflectionUtil.getField(stealing.getClass(), "tickTime"), 0); + } catch (IllegalAccessException | NoSuchFieldException e) { + logger.info("Failed to set tickTime for stealing!"); + e.printStackTrace(); + } + + } catch (IllegalArgumentException | ClassCastException e) { + e.printStackTrace(); + } + } + + public static long lastSecondPolled = 0; + public static long lastPolledTitanSpawn = 0; + public static final long pollTitanSpawnTime = TimeConstants.MINUTE_MILLIS*10; + public static long lastPolledTitans = 0; + public static final long pollTitanTime = TimeConstants.SECOND_MILLIS; + public static long lastPolledDepots = 0; + public static final long pollDepotTime = TimeConstants.MINUTE_MILLIS; + public static long lastPolledEternalReservoirs = 0; + public static final long pollEternalReservoirTime = TimeConstants.MINUTE_MILLIS*10; + @Override + public void onServerPoll() { + if((lastSecondPolled + TimeConstants.SECOND_MILLIS) < System.currentTimeMillis()){ + if(lastPolledDepots + pollDepotTime < System.currentTimeMillis()){ + SupplyDepots.pollDepotSpawn(); + lastPolledDepots += pollDepotTime; + } + if(lastPolledTitanSpawn + pollTitanSpawnTime < System.currentTimeMillis()){ + Arena.pollTitanSpawn(); + lastPolledTitanSpawn += pollTitanSpawnTime; + } + if(lastPolledTitans + pollTitanTime < System.currentTimeMillis()){ + Arena.pollTitans(); + lastPolledTitans += pollTitanTime; + } + if(lastPolledEternalReservoirs + pollEternalReservoirTime < System.currentTimeMillis()){ + Soulstealing.pollSoulForges(); + lastPolledEternalReservoirs += pollEternalReservoirTime; + } + + // Update counter + if(lastSecondPolled + TimeConstants.SECOND_MILLIS*10 > System.currentTimeMillis()){ + lastSecondPolled += TimeConstants.SECOND_MILLIS; + }else{ + logger.info("Time between last poll was greater than 10 seconds. Resetting all poll counters..."); + lastSecondPolled = System.currentTimeMillis(); + lastPolledTitanSpawn = System.currentTimeMillis(); + lastPolledTitans = System.currentTimeMillis(); + lastPolledDepots = System.currentTimeMillis(); + lastPolledEternalReservoirs = System.currentTimeMillis(); + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/mod/sin/wyvern/arena/Arena.java b/src/main/java/mod/sin/wyvern/arena/Arena.java new file mode 100644 index 0000000..3b081cd --- /dev/null +++ b/src/main/java/mod/sin/wyvern/arena/Arena.java @@ -0,0 +1,1166 @@ +package mod.sin.wyvern.arena; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modloader.classhooks.HookException; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.Players; +import com.wurmonline.server.Server; +import com.wurmonline.server.ServerEntry; +import com.wurmonline.server.Servers; +import com.wurmonline.server.TimeConstants; +import com.wurmonline.server.bodys.Wound; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.Creatures; +import com.wurmonline.server.creatures.MineDoorPermission; +import com.wurmonline.server.creatures.SpellEffects; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.spells.SpellEffect; +import com.wurmonline.server.zones.AreaSpellEffect; +import com.wurmonline.server.zones.VolaTile; +import com.wurmonline.server.zones.Zones; + +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import javassist.bytecode.Descriptor; +import mod.sin.creatures.titans.*; +import mod.sin.lib.Util; +import mod.sin.wyvern.MiscChanges; + +public class Arena { + public static Logger logger = Logger.getLogger(Arena.class.getName()); + public static byte getArenaAttitude(Player player, Creature aTarget){ + if (player.getPower() > 0) { + if (player.getPower() >= 5) { + return 6; + } + return 3; + } + if (player == aTarget){ + return 1; + } + if (player.opponent == aTarget) { + return 2; + } + if (player.getSaveFile().pet != -10 && aTarget.getWurmId() == player.getSaveFile().pet) { + return 1; + } + if (aTarget.getDominator() != null && aTarget.getDominator() != player) { + return player.getAttitude(aTarget.getDominator()); + } + if (aTarget.isReborn() && player.getKingdomTemplateId() == 3) { + return 0; + } + if (aTarget.hasAttackedUnmotivated() && (aTarget.isPlayer() || !aTarget.isDominated() || aTarget.getDominator() != player)) { + return 2; + } + if (aTarget.isPlayer() && player.getTeam() != null && player.getTeam().contains(aTarget)){ + return 1; + } + if (aTarget.isPlayer() && player.isFriend(aTarget.getWurmId())) { + return 1; + } + if (aTarget.isPlayer()){ + return 2; + } + if (aTarget.isAggHuman()) { + return 2; + } + return 0; + } + + public static void respawnPlayer(Creature player, ServerEntry server){ + ServerEntry targetserver = server.serverWest; + if(player instanceof Player){ + Player p = (Player) player; + int tilex = targetserver.SPAWNPOINTJENNX; + int tiley = targetserver.SPAWNPOINTJENNY; + p.sendTransfer(Server.getInstance(), targetserver.INTRASERVERADDRESS, Integer.parseInt(targetserver.INTRASERVERPORT), targetserver.INTRASERVERPASSWORD, targetserver.id, tilex, tiley, true, false, p.getKingdomId()); + } + } + + public static boolean isTitan(int templateId){ + if(templateId == Lilith.templateId){ + return true; + }else if(templateId == Ifrit.templateId){ + return true; + } + return false; + } + public static boolean isTitan(Creature creature){ + return isTitan(creature.getTemplate().getTemplateId()); + } + + public static boolean isTitanMinion(Creature creature){ + int templateId = creature.getTemplate().getTemplateId(); + if(templateId == LilithWraith.templateId){ + return true; + }else if(templateId == LilithZombie.templateId){ + return true; + }else if(templateId == IfritFiend.templateId){ + return true; + }else if(templateId == IfritSpider.templateId){ + return true; + } + return false; + } + + public static void checkDestroyMineDoor(Creature titan, int x, int y){ + int tile = Server.surfaceMesh.getTile(x, y); + if(Tiles.isMineDoor((byte)Tiles.decodeType((int)tile))){ + if (Tiles.decodeType((int)Server.caveMesh.getTile(x, y)) == Tiles.Tile.TILE_CAVE_EXIT.id) { + Server.setSurfaceTile(x, y, Tiles.decodeHeight((int)Server.surfaceMesh.getTile(x, y)), Tiles.Tile.TILE_HOLE.id, (byte) 0); + } else { + Server.setSurfaceTile(x, y, Tiles.decodeHeight((int)Server.surfaceMesh.getTile(x, y)), Tiles.Tile.TILE_ROCK.id, (byte) 0); + } + Players.getInstance().sendChangedTile(x, y, true, true); + MineDoorPermission.deleteMineDoor(x, y); + Server.getInstance().broadCastAction(titan.getName() + "'s ability destroys a mine door!", titan, 50); + } + } + public static Creature[] getUndergroundCreatures(int x, int y){ + VolaTile tCave = Zones.getOrCreateTile(x, y, false); + if(tCave == null){ + return null; + } + int tileCave = Server.caveMesh.getTile(x, y); + byte typeCave = Tiles.decodeType(tileCave); + if(typeCave != Tiles.Tile.TILE_CAVE.id && typeCave != Tiles.Tile.TILE_CAVE_EXIT.id && typeCave != Tiles.Tile.TILE_CAVE_FLOOR_REINFORCED.id && typeCave != Tiles.Tile.TILE_CAVE_PREPATED_FLOOR_REINFORCED.id){ + return null; + } + return tCave.getCreatures(); + } + + // --- Advanced Abilities --- // + public static void lilithMyceliumVoidAttack(Creature titan, Creature lCret, int tilex, int tiley){ + if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)){ + return; + } + if (!lCret.addWoundOfType(lCret, Wound.TYPE_INTERNAL, 1, true, 1.0f, true, 60000f)) { + Creatures.getInstance().setCreatureDead(lCret); + Players.getInstance().setCreatureDead(lCret); + lCret.setTeleportPoints((short)tilex, (short)tiley, titan.getLayer(), 0); + lCret.startTeleporting(); + lCret.getCommunicator().sendAlertServerMessage("You are absorbed by the Mycelium and brought to Lilith!"); + lCret.getCommunicator().sendTeleport(false); + if (!lCret.isPlayer()) { + lCret.getMovementScheme().resumeSpeedModifier(); + } + } + } + public static void ifritMassIncinerateAttack(Creature titan, Creature lCret){ + if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)){ + return; + } + SpellEffect eff; + SpellEffects effs = lCret.getSpellEffects(); + if (effs == null) { + effs = lCret.createSpellEffects(); + } + eff = effs.getSpellEffect((byte) 94); + if (eff == null) { + lCret.getCommunicator().sendAlertServerMessage("You are engulfed by the flames of Ifrit!", (byte) 4); + eff = new SpellEffect(lCret.getWurmId(), (byte) 94, 80f, 180, (byte) 9, (byte) 1, true); + effs.addSpellEffect(eff); + Server.getInstance().broadCastAction(titan.getName() + " has engulfed " + lCret.getNameWithGenus() + " in flames!", titan, 50); + } else { + lCret.getCommunicator().sendAlertServerMessage("The heat around you increases. The pain is excruciating!", (byte) 4); + eff.setPower(eff.getPower()+200f); + eff.setTimeleft(180); + lCret.sendUpdateSpellEffect(eff); + Server.getInstance().broadCastAction(titan.getName() + " has engulfed " + lCret.getNameWithGenus() + " in flames again, increasing the intensity!", titan, 50); + } + } + + public static void performAdvancedAbility(Creature titan){ + int tilex = titan.getTileX(); + int tiley = titan.getTileY(); + if(titan.getTemplate().getTemplateId() == Lilith.templateId){ // Lilith Ability + int tarx = (tilex-3)+(Server.rand.nextInt(7)); + int tary = (tiley-3)+(Server.rand.nextInt(7)); + int sx = Zones.safeTileX(tarx - 1); + int ex = Zones.safeTileX(tarx + 1); + int sy = Zones.safeTileY(tary - 1); + int ey = Zones.safeTileY(tary + 1); + Zones.flash(tarx, tary, false); + Server.getInstance().broadCastAction(titan.getName() + " casts Mycelium Void, turning the earth to fungus and pulling enemies to "+titan.getHimHerItString()+"!", titan, 50); + for (int x = sx; x <= ex; ++x) { + for (int y = sy; y <= ey; ++y) { + VolaTile t = Zones.getOrCreateTile(x, y, true); + if (t == null){ + continue; + } + checkDestroyMineDoor(titan, x, y); + int tile = Server.surfaceMesh.getTile(x, y); + byte type = Tiles.decodeType((int)tile); + Tiles.Tile theTile = Tiles.getTile((byte)type); + byte data = Tiles.decodeData((int)tile); + // Copied from Fungus to prevent wacko behaviours like deleting minedoors and glitching tunnels: + if (type != Tiles.Tile.TILE_FIELD.id && type != Tiles.Tile.TILE_FIELD2.id && type != Tiles.Tile.TILE_GRASS.id && type != Tiles.Tile.TILE_REED.id && type != Tiles.Tile.TILE_DIRT.id && type != Tiles.Tile.TILE_LAWN.id && type != Tiles.Tile.TILE_STEPPE.id && !theTile.isNormalTree() && !theTile.isEnchanted() && !theTile.isNormalBush()){ + // + }else{ + if (theTile.isNormalTree()) { + Server.setSurfaceTile(x, y, Tiles.decodeHeight((int)tile), theTile.getTreeType(data).asMyceliumTree(), data); + } else if (theTile.isEnchantedTree()) { + Server.setSurfaceTile(x, y, Tiles.decodeHeight((int)tile), theTile.getTreeType(data).asNormalTree(), data); + } else if (theTile.isNormalBush()) { + Server.setSurfaceTile(x, y, Tiles.decodeHeight((int)tile), theTile.getBushType(data).asMyceliumBush(), data); + } else if (theTile.isEnchantedBush()) { + Server.setSurfaceTile(x, y, Tiles.decodeHeight((int)tile), theTile.getBushType(data).asNormalBush(), data); + } else if (type == Tiles.Tile.TILE_LAWN.id) { + Server.setSurfaceTile(x, y, Tiles.decodeHeight((int)tile), Tiles.Tile.TILE_MYCELIUM_LAWN.id, (byte) 0); + } else { + Server.setSurfaceTile(x, y, Tiles.decodeHeight((int)tile), Tiles.Tile.TILE_MYCELIUM.id, (byte) 0); + } + Players.getInstance().sendChangedTile(x, y, true, false); + } + Creature[] crets2 = t.getCreatures(); + for (Creature lCret : crets2) { + lilithMyceliumVoidAttack(titan, lCret, tilex, tiley); + } + VolaTile tCave = Zones.getOrCreateTile(x, y, false); + if(tCave == null){ + continue; + } + int tileCave = Server.caveMesh.getTile(x, y); + byte typeCave = Tiles.decodeType(tileCave); + if(typeCave != Tiles.Tile.TILE_CAVE.id && typeCave != Tiles.Tile.TILE_CAVE_EXIT.id && typeCave != Tiles.Tile.TILE_CAVE_FLOOR_REINFORCED.id && typeCave != Tiles.Tile.TILE_CAVE_PREPATED_FLOOR_REINFORCED.id){ + continue; + } + Creature[] crets3 = tCave.getCreatures(); + for (Creature lCret : crets3) { + lilithMyceliumVoidAttack(titan, lCret, tilex, tiley); + } + } + } + }else if(titan.getTemplate().getTemplateId() == Ifrit.templateId){ // Ifrit Ability + int tarx = (tilex-4)+(Server.rand.nextInt(9)); + int tary = (tiley-4)+(Server.rand.nextInt(9)); + int sx = Zones.safeTileX(tarx - 1); + int ex = Zones.safeTileX(tarx + 1); + int sy = Zones.safeTileY(tary - 1); + int ey = Zones.safeTileY(tary + 1); + Zones.flash(tarx, tary, false); + Server.getInstance().broadCastAction(titan.getName() + " casts Mass Incinerate, burning enemies near "+titan.getHimHerItString()+"!", titan, 50); + for (int x = sx; x <= ex; ++x) { + for (int y = sy; y <= ey; ++y) { + VolaTile t = Zones.getOrCreateTile(x, y, true); + if (t == null){ + continue; + } + checkDestroyMineDoor(titan, x, y); + new AreaSpellEffect(titan.getWurmId(), x, y, titan.getLayer(), (byte) 35, System.currentTimeMillis() + 5000, 200.0f, titan.getLayer(), 0, true); + Creature[] crets2 = t.getCreatures(); + for (Creature lCret : crets2) { + ifritMassIncinerateAttack(titan, lCret); + } + Creature[] undergroundCreatures = getUndergroundCreatures(x, y); + if(undergroundCreatures != null){ + for(Creature lCret : undergroundCreatures){ + ifritMassIncinerateAttack(titan, lCret); + } + } + } + } + } + } + + // --- Basic Abilities --- // + public static void lilithPainRainAttack(Creature titan, Creature lCret, VolaTile t){ + if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)){ + return; + } + t.sendAttachCreatureEffect((Creature)lCret, (byte) 8, (byte) 0, (byte) 0, (byte) 0, (byte) 0); + try { + if (lCret.addWoundOfType(titan, (byte) 9, lCret.getBody().getRandomWoundPos(), false, 1.0f, false, 25000.0 * (double)lCret.addSpellResistance((short) 448))){ + return; + } + } catch (Exception e) { + e.printStackTrace(); + } + lCret.setTarget(titan.getWurmId(), false); + } + + public static void performBasicAbility(Creature titan){ + int tilex = titan.getTileX(); + int tiley = titan.getTileY(); + if(titan.getTemplate().getTemplateId() == Lilith.templateId){ // Lilith Ability + int sx = Zones.safeTileX(tilex - 10); + int sy = Zones.safeTileY(tiley - 10); + int ex = Zones.safeTileX(tilex + 10); + int ey = Zones.safeTileY(tiley + 10); + //this.calculateArea(sx, sy, ex, ey, tilex, tiley, layer, currstr); + int x, y; + Server.getInstance().broadCastAction(titan.getName() + " casts Pain Rain, harming all around "+titan.getHimHerItString()+"!", titan, 50); + for (x = sx; x <= ex; ++x) { + for (y = sy; y <= ey; ++y) { + VolaTile t = Zones.getTileOrNull(x, y, titan.isOnSurface()); + if (t == null){ + continue; + } + Creature[] crets2 = t.getCreatures(); + for (Creature lCret : crets2) { + lilithPainRainAttack(titan, lCret, t); + } + Creature[] undergroundCreatures = getUndergroundCreatures(x, y); + if(undergroundCreatures != null){ + for(Creature lCret : undergroundCreatures){ + lilithPainRainAttack(titan, lCret, t); + } + } + } + } + }else if(titan.getTemplate().getTemplateId() == Ifrit.templateId){ + int sx = Zones.safeTileX(tilex - 10); + int sy = Zones.safeTileY(tiley - 10); + int ex = Zones.safeTileX(tilex + 10); + int ey = Zones.safeTileY(tiley + 10); + int x, y; + ArrayList targets = new ArrayList(); + for (x = sx; x <= ex; ++x) { + for (y = sy; y <= ey; ++y) { + VolaTile t = Zones.getTileOrNull(x, y, titan.isOnSurface()); + if (t == null){ + continue; + } + Creature[] crets2 = t.getCreatures(); + for (Creature lCret : crets2) { + if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)){ + continue; + } + targets.add(lCret); + } + Creature[] undergroundCreatures = getUndergroundCreatures(x, y); + if(undergroundCreatures != null){ + for(Creature lCret : undergroundCreatures){ + if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)){ + continue; + } + targets.add(lCret); + } + } + } + } + if(!targets.isEmpty()){ + Creature target = targets.get(Server.rand.nextInt(targets.size())); + int damage = target.getStatus().damage; + int minhealth = 65435; + float maxdam = (float)Math.max(0, minhealth - damage); + if (maxdam > 500.0f) { + Server.getInstance().broadCastAction(titan.getName() + " picks a target at random and Smites "+target.getName()+"!", titan, 50); + target.getCommunicator().sendAlertServerMessage(titan.getName() + " smites you.", (byte) 4); + try { + target.addWoundOfType(titan, Wound.TYPE_BURN, target.getBody().getRandomWoundPos(), false, 1.0f, false, maxdam); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + } + + public static void summonChampions(Creature titan, int nums){ + int templateType = -10; + String spellName = ""; + if(titan.getTemplate().getTemplateId() == Lilith.templateId){ + templateType = LilithWraith.templateId; + spellName = "Raise Wraith"; + }else if(titan.getTemplate().getTemplateId() == Ifrit.templateId){ + templateType = IfritFiend.templateId; + spellName = "Summon Fiend"; + } + if(templateType == -10){ + logger.severe("[ERROR]: Template type not set in summonChampions()"); + return; + } + try { + Server.getInstance().broadCastAction(titan.getName() + " casts "+spellName+", calling champions to "+titan.getHimHerItString()+" aid!", titan, 50); + for(int i = 0; i < nums; i++){ + int tilex = ((titan.getTileX()*4)+3)-Server.rand.nextInt(7); + int tiley = ((titan.getTileY()*4)+3)-Server.rand.nextInt(7); + int sx = Zones.safeTileX(tilex - 2); + int sy = Zones.safeTileY(tiley - 2); + int ex = Zones.safeTileX(tilex + 2); + int ey = Zones.safeTileY(tiley + 2); + Creature target = null; + for (int x = sx; x <= ex; ++x) { + for (int y = sy; y <= ey; ++y) { + VolaTile t = Zones.getTileOrNull(x, y, titan.isOnSurface()); + if (t == null){ + continue; + } + Creature[] crets2 = t.getCreatures(); + for (Creature lCret : crets2) { + if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)) continue; + if(Server.rand.nextInt(3) == 0){ + target = lCret; + break; + } + } + Creature[] undergroundCreatures = getUndergroundCreatures(x, y); + if(undergroundCreatures != null){ + for(Creature lCret : undergroundCreatures){ + if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)) continue; + if(Server.rand.nextInt(3) == 0){ + target = lCret; + break; + } + } + } + if(target != null){ + break; + } + } + if(target != null){ + break; + } + } + // public static Creature doNew(int templateid, float aPosX, float aPosY, float aRot, int layer, String name, byte gender) throws Exception { + Creature champion = Creature.doNew(templateType, tilex, tiley, 360f*Server.rand.nextFloat(), 1, "", (byte)0); + if(target != null){ + champion.setOpponent(target); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + public static void summonMinions(Creature titan, int nums){ + int templateType = -10; + String spellName = ""; + if(titan.getTemplate().getTemplateId() == Lilith.templateId){ + templateType = LilithZombie.templateId; + spellName = "Raise Zombie"; + }else if(titan.getTemplate().getTemplateId() == Ifrit.templateId){ + templateType = IfritSpider.templateId; + spellName = "Summon Spider"; + } + if(templateType == -10){ + logger.severe("[ERROR]: Template type not set in summonMinions()"); + return; + } + try { + Server.getInstance().broadCastAction(titan.getName() + " casts "+spellName+", calling minions to "+titan.getHimHerItString()+" aid!", titan, 50); + for(int i = 0; i < nums; i++){ + int tilex = ((titan.getTileX()*4)+3)-Server.rand.nextInt(7); + int tiley = ((titan.getTileY()*4)+3)-Server.rand.nextInt(7); + int sx = Zones.safeTileX(tilex - 10); + int sy = Zones.safeTileY(tiley - 10); + int ex = Zones.safeTileX(tilex + 10); + int ey = Zones.safeTileY(tiley + 10); + Creature target = null; + for (int x = sx; x <= ex; ++x) { + for (int y = sy; y <= ey; ++y) { + VolaTile t = Zones.getTileOrNull(x, y, titan.isOnSurface()); + if (t == null){ + continue; + } + Creature[] crets2 = t.getCreatures(); + for (Creature lCret : crets2) { + if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)) continue; + if(Server.rand.nextInt(3) == 0){ + target = lCret; + break; + } + } + Creature[] undergroundCreatures = getUndergroundCreatures(x, y); + if(undergroundCreatures != null){ + for(Creature lCret : undergroundCreatures){ + if (lCret.isUnique() || lCret.isInvulnerable() || lCret == titan || isTitanMinion(lCret)) continue; + if(Server.rand.nextInt(3) == 0){ + target = lCret; + break; + } + } + } + if(target != null){ + break; + } + } + if(target != null){ + break; + } + } + // public static Creature doNew(int templateid, float aPosX, float aPosY, float aRot, int layer, String name, byte gender) throws Exception { + Creature minion = Creature.doNew(templateType, tilex, tiley, 360f*Server.rand.nextFloat(), 1, "", (byte)0); + if(target != null){ + minion.setOpponent(target); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static HashMap titanDamage = new HashMap(); + public static void pollTitan(Creature titan){ + if(titanDamage.containsKey(titan)){ + int prevDamage = titanDamage.get(titan); + int currentDamage = titan.getStatus().damage; + if(titan.isOnSurface() && Server.rand.nextInt(60) == 0){ + performAdvancedAbility(titan); + }else if(!titan.isOnSurface() && Server.rand.nextInt(20) == 0){ + performAdvancedAbility(titan); + } + if(currentDamage > prevDamage){ + // Health threshold actions + if(currentDamage > 0 && prevDamage == 0){ // First attack + String msg = "<"+titan.getName()+" [100%]> Mere mortals dare to face me?"; + MiscChanges.sendGlobalFreedomChat(titan, msg, 255, 105, 180); + MiscChanges.sendServerTabMessage(msg, 255, 105, 180); + Zones.flash(titan.getTileX(), titan.getTileY(), false); + } + if(currentDamage > 8191 && prevDamage < 8191){ // 87.5% + String msg = "<"+titan.getName()+" [88%]> You actually think you can defeat me?"; + MiscChanges.sendGlobalFreedomChat(titan, msg, 255, 105, 180); + MiscChanges.sendServerTabMessage(msg, 255, 105, 180); + Zones.flash(titan.getTileX(), titan.getTileY(), false); + } + if(currentDamage > 16383 && prevDamage < 16383){ // 75% + String msg = "<"+titan.getName()+" [75%]> I am not alone."; + MiscChanges.sendGlobalFreedomChat(titan, msg, 255, 105, 180); + MiscChanges.sendServerTabMessage(msg, 255, 105, 180); + Zones.flash(titan.getTileX(), titan.getTileY(), false); + summonMinions(titan, Server.rand.nextInt(2)+2); + } + if(currentDamage > 26214 && prevDamage < 26214){ // 60% + String msg = "<"+titan.getName()+" [60%]> You will feel my wrath!"; + MiscChanges.sendGlobalFreedomChat(titan, msg, 255, 105, 180); + MiscChanges.sendServerTabMessage(msg, 255, 105, 180); + Zones.flash(titan.getTileX(), titan.getTileY(), false); + performBasicAbility(titan); + } + if(currentDamage > 32767 && prevDamage < 32767){ // 50% + String msg = "<"+titan.getName()+" [50%]> I've had enough of you. Minions, assemble!"; + MiscChanges.sendGlobalFreedomChat(titan, msg, 255, 105, 180); + MiscChanges.sendServerTabMessage(msg, 255, 105, 180); + Zones.flash(titan.getTileX(), titan.getTileY(), false); + summonMinions(titan, Server.rand.nextInt(4)+4); + performBasicAbility(titan); + } + if(currentDamage > 39321 && prevDamage < 39321){ // 40% + String msg = "<"+titan.getName()+" [40%]> Let's try something new, shall we?"; + MiscChanges.sendGlobalFreedomChat(titan, msg, 255, 105, 180); + MiscChanges.sendServerTabMessage(msg, 255, 105, 180); + Zones.flash(titan.getTileX(), titan.getTileY(), false); + performAdvancedAbility(titan); + } + if(currentDamage > 45874 && prevDamage < 45874){ // 30% + String msg = "<"+titan.getName()+" [30%]> Perhaps minions aren't enough. Now, try my champions!"; + MiscChanges.sendGlobalFreedomChat(titan, msg, 255, 105, 180); + MiscChanges.sendServerTabMessage(msg, 255, 105, 180); + Zones.flash(titan.getTileX(), titan.getTileY(), false); + summonChampions(titan, Server.rand.nextInt(2)+2); + performBasicAbility(titan); + } + if(currentDamage > 52428 && prevDamage < 52428){ // 20% + String msg = "<"+titan.getName()+" [20%]> Enough! I will end you!"; + MiscChanges.sendGlobalFreedomChat(titan, msg, 255, 105, 180); + MiscChanges.sendServerTabMessage(msg, 255, 105, 180); + Zones.flash(titan.getTileX(), titan.getTileY(), false); + performBasicAbility(titan); + performAdvancedAbility(titan); + } + if(currentDamage > 58981 && prevDamage < 58981){ // 10% + String msg = "<"+titan.getName()+" [10%]> Minions... Champions... Only one way to win a battle: An army!"; + MiscChanges.sendGlobalFreedomChat(titan, msg, 255, 105, 180); + MiscChanges.sendServerTabMessage(msg, 255, 105, 180); + Zones.flash(titan.getTileX(), titan.getTileY(), false); + summonMinions(titan, Server.rand.nextInt(5)+7); + summonChampions(titan, Server.rand.nextInt(3)+3); + performBasicAbility(titan); + performAdvancedAbility(titan); + } + // Extra abilities + if(currentDamage > 16383 && Server.rand.nextInt(10) == 0){ + if(currentDamage > 45874){ + summonMinions(titan, Server.rand.nextInt(2)+2); + }else if(currentDamage > 32767){ + summonMinions(titan, Server.rand.nextInt(3)+1); + }else{ + summonMinions(titan, Server.rand.nextInt(2)+1); + } + } + if(currentDamage > 16383 && Server.rand.nextInt(15) == 0){ + if(currentDamage > 45874){ // 30% + if(Server.rand.nextInt(10) == 0){ + performBasicAbility(titan); + } + }else if(currentDamage > 32767){ // 50% + if(Server.rand.nextInt(12) == 0){ + performBasicAbility(titan); + } + }else{ // 75% + if(Server.rand.nextInt(10) == 0){ + performBasicAbility(titan); + } + } + } + if(currentDamage > 32767 && Server.rand.nextInt(20) == 0){ + if(currentDamage > 45874){ + if(Server.rand.nextInt(15) == 0){ + performAdvancedAbility(titan); + } + }else{ + if(Server.rand.nextInt(20) == 0){ + performAdvancedAbility(titan); + } + } + } + if(currentDamage > 45874 && Server.rand.nextInt(15) == 0){ + summonChampions(titan, 1); + } + titanDamage.put(titan, currentDamage); + } + }else{ + titanDamage.put(titan, titan.getStatus().damage); + } + } + + public static ArrayList titans = new ArrayList(); + public static long lastPolledTitans = 0; + public static final long titanRespawnTime = TimeConstants.HOUR_MILLIS*26L; + public static void addTitan(Creature mob){ + if(isTitan(mob) && !titans.contains(mob)){ + titans.add(mob); + } + } + public static void removeTitan(Creature mob){ + if(isTitan(mob) && titans.contains(mob)){ + titans.remove(mob); + } + } + public static void pollTitanSpawn(){ + Creature[] crets = Creatures.getInstance().getCreatures(); + for(Creature c : crets){ + if(isTitan(c) && !titans.contains(c)){ + titans.add(c); + } + } + for(Creature c : titans){ + if(c.isDead()){ + titans.remove(c); + } + } + if(titans.isEmpty() && Servers.localServer.PVPSERVER){ + if(lastPolledTitans + titanRespawnTime < System.currentTimeMillis()){ + logger.info("No Titan was found, and the timer has expired. Spawning a new one."); + float worldSizeX = Zones.worldTileSizeX; + float worldSizeY = Zones.worldTileSizeY; + float minX = worldSizeX*0.25f; + float minY = worldSizeY*0.25f; + int tilex = (int) (minX+(minX*2*Server.rand.nextFloat()))*4; + int tiley = (int) (minY+(minY*2*Server.rand.nextFloat()))*4; + int[] titanTemplates = {Lilith.templateId, Ifrit.templateId}; + try { + Creature.doNew(titanTemplates[Server.rand.nextInt(titanTemplates.length)], tilex, tiley, 360f*Server.rand.nextFloat(), 1, "", (byte)0); + } catch (Exception e) { + logger.severe("Failed to create Titan."); + e.printStackTrace(); + } + } + }else{ + lastPolledTitans = System.currentTimeMillis(); + } + } + public static void pollTitans(){ + for(Creature c : titans){ + if(isTitan(c)){ + pollTitan(c); + } + } + } + + public static void preInit(){ + try { + ClassPool classPool = HookManager.getInstance().getClassPool(); + Class thisClass = Arena.class; + String replace; + + // - Add poll for Titans - // + /*CtClass ctServer = classPool.get("com.wurmonline.server.Server"); + ctServer.getDeclaredMethod("run").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("pruneTransfers")) { + m.replace("mod.sin.wyvern.arena.Arena.pollTitanSpawn();" + + "$_ = $proceed($$);"); + return; + } + } + });*/ + /*ctServer.getDeclaredMethod("run").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("pollValreiData")) { + m.replace("mod.sin.wyvern.arena.Arena.pollTitans();" + + "$_ = $proceed($$);"); + return; + } + } + });*/ + + // - Remove regeneration from titans - // + CtClass ctWound = classPool.get("com.wurmonline.server.bodys.Wound"); + /*CtClass[] params = { CtClass.intType, CtClass.booleanType }; + String desc = Descriptor.ofMethod(CtClass.booleanType, params); + ctWound.getMethod("modifySeverity", desc).insertBefore("if(mod.sin.wyvern.arena.Arena.isTitan(this.creature) && $1 < 0){" + + " logger.info(\"Skipping regeneration and setting poll counter for wound on titan \"+creature.getName());" + + " this.setLastPolled(System.currentTimeMillis()+System.currentTimeMillis());" + + " return false;" + + "}");*/ + replace = "if(!"+Arena.class.getName()+".isTitan(this.creature)){" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctWound, "poll", "modifySeverity", replace); + /*ctWound.getDeclaredMethod("poll").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("modifySeverity")) { + m.replace("if(!mod.sin.wyvern.arena.Arena.isTitan(this.creature)){" + + " $_ = $proceed($$);" + + "}"); + return; + } + } + });*/ + Util.instrumentDeclared(thisClass, ctWound, "poll", "checkInfection", replace); + /*ctWound.getDeclaredMethod("poll").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("checkInfection")) { + m.replace("if(!mod.sin.wyvern.arena.Arena.isTitan(this.creature)){" + + " $_ = $proceed($$);" + + "}"); + return; + } + } + });*/ + Util.instrumentDeclared(thisClass, ctWound, "poll", "checkPoison", replace); + /*ctWound.getDeclaredMethod("poll").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("checkPoison")) { + m.replace("if(!mod.sin.wyvern.arena.Arena.isTitan(this.creature)){" + + " $_ = $proceed($$);" + + "}"); + return; + } + } + });*/ + + // - 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(com.wurmonline.server.Servers.isThisAPvpServer() && owner.getDominator() != this.player){" + + " $_ = owner.getLeader();" + + "}else{" + + " if(this.player.getPower() > 0){" + + " $_ = this.player;" + + " }else{" + + " $_ = $proceed($$);" + + " }" + + "}"; + Util.instrumentDeclared(thisClass, ctCommunicator, "reallyHandle_CMD_MOVE_INVENTORY", "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; + } + } + });*/ + + // - Allow lockpicking on PvP server, as well as treasure chests on PvE - // + CtClass ctItemBehaviour = classPool.get("com.wurmonline.server.behaviours.ItemBehaviour"); + 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"); + CtClass[] params1 = { + ctAction, + ctCreature, + ctItem, + ctItem, + CtClass.shortType, + CtClass.floatType + }; + String desc1 = Descriptor.ofMethod(CtClass.booleanType, params1); + /*String actionDescriptor = Descriptor.ofMethod(CtClass.booleanType, new CtClass[] + {classPool.get("com.wurmonline.server.behaviours.Action"), classPool.get("com.wurmonline.server.creatures.Creature"), + classPool.get("com.wurmonline.server.items.Item"), classPool.get("com.wurmonline.server.items.Item"), CtClass.shortType, CtClass.floatType});*/ + 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); + /*ctItemBehaviour.getMethod("action", actionDescriptor).instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isInPvPZone")) { + m.replace("if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = target.getLastOwnerId() == -10 || target.getLastOwnerId() == 0 || target.getTemplateId() == 995;" + + "}"); + return; + } + } + });*/ + 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; + } + } + });*/ + + // - Disable villages and PMK's on the PvP server - // + CtClass ctVillageFoundationQuestion = classPool.get("com.wurmonline.server.questions.VillageFoundationQuestion"); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " this.getResponder().getCommunicator().sendSafeServerMessage(\"Villages are disabled on this server.\");" + + " return;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctVillageFoundationQuestion, "sendQuestion", replace); + /*ctVillageFoundationQuestion.getDeclaredMethod("sendQuestion").insertBefore("" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " this.getResponder().getCommunicator().sendSafeServerMessage(\"Villages are disabled on this server.\");" + + " return;" + + "}");*/ + CtClass ctKingdomFoundationQuestion = classPool.get("com.wurmonline.server.questions.KingdomFoundationQuestion"); + 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); + /*ctKingdomFoundationQuestion.getDeclaredMethod("sendQuestion").insertBefore("" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " this.getResponder().getCommunicator().sendSafeServerMessage(\"Player-Made Kingdoms are disabled on this server.\");" + + " return;" + + "}");*/ + + // - Disable champion players altogether - // + CtClass ctRealDeathQuestion = classPool.get("com.wurmonline.server.questions.RealDeathQuestion"); + replace = "this.getResponder().getCommunicator().sendSafeServerMessage(\"Champion players are disabled on this server.\");" + + "return;"; + Util.insertBeforeDeclared(thisClass, ctRealDeathQuestion, "sendQuestion", replace); + /*ctRealDeathQuestion.getDeclaredMethod("sendQuestion").insertBefore("" + + "this.getResponder().getCommunicator().sendSafeServerMessage(\"Champion players are disabled on this server.\");" + + "return;");*/ + + // - 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); + /*ctPlayer.getDeclaredMethod("getAttitude").insertBefore("" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return mod.sin.wyvern.arena.Arena.getArenaAttitude(this, $1);" + + "}");*/ + + // - Hook for (ENEMY) declaration to allow for enemy presence blocking - // + CtClass ctVirtualZone = classPool.get("com.wurmonline.server.zones.VirtualZone"); + CtClass[] params2 = { + CtClass.longType, + CtClass.booleanType, + CtClass.longType, + CtClass.floatType, + CtClass.floatType, + CtClass.floatType + }; + String desc2 = Descriptor.ofMethod(CtClass.booleanType, params2); + 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){" + + " suff = \" (ENEMY)\";" + + " enemy = true;" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDescribed(thisClass, ctVirtualZone, "addCreature", desc2, "getTitle", replace); + /*ctVirtualZone.getMethod("addCreature", desc2).instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("getTitle")) { + m.replace("if(this.watcher.isPlayer() && creature.isPlayer() && com.wurmonline.server.Servers.localServer.PVPSERVER && mod.sin.wyvern.arena.Arena.getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" + + " suff = \" (ENEMY)\";" + + " enemy = true;" + + "}" + + "$_ = $proceed($$);"); + return; + } + } + });*/ + + // - 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.Arena.getArenaAttitude((com.wurmonline.server.players.Player)this.watcher, creature) == 2){" + + " $_ = 1;" + + "}else{" + + " $_ = $proceed($$);" + + "}"); + return; + } + } + });*/ + + // - Block twigs and stones on the PvP server - // + CtClass ctMethodsCreatures = classPool.get("com.wurmonline.server.behaviours.MethodsCreatures"); + Util.instrumentDeclared(thisClass, ctMethodsCreatures, "teleportCreature", "isInPvPZone", "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"); + /*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.Arena.respawnPlayer(this.getResponder(), com.wurmonline.server.Servers.localServer);" + + " return;" + + "}");*/ + + // - 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); + /*ctPlayer.getDeclaredMethod("modifyRanking").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isEnemyOnChaos")) { + m.replace("if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"); + return; + } + } + });*/ + + // - Triple fightskill gains on PvP server - // + //CtClass ctCreature = classPool.get("com.wurmonline.server.creatures.Creature"); + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " p.getFightingSkill().setKnowledge(pskill + (skillGained*2.5d), false);" + + "}" + + "$_ = $proceed($$);"; + Util.instrumentDeclared(thisClass, ctCreature, "modifyFightSkill", "checkInitialTitle", replace); + /*ctCreature.getDeclaredMethod("modifyFightSkill").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("checkInitialTitle")) { + m.replace("if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " p.getFightingSkill().setKnowledge(pskill + (skillGained*2.5d), false);" + + "}" + + "$_ = $proceed($$);"); + return; + } + } + });*/ + + // - Fix nearby enemy check to find aggression instead of kingdom - // + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = c.getAttitude(performer) != 2;" + + "}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; + } + } + });*/ + + // - Ensure corpses are not loot protected on PvP - // + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = $proceed(false);" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCreature, "die", "setProtected", replace); + /*ctCreature.getDeclaredMethod("die").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("setProtected")) { + m.replace("if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = $proceed(false);" + + "}else{" + + " $_ = $proceed($$);" + + "}"); + return; + } + } + });*/ + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"; + Util.instrumentDeclared(thisClass, ctCreature, "die", "isInPvPZone", replace); + /*ctCreature.getDeclaredMethod("die").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isInPvPZone")) { + m.replace("if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " $_ = true;" + + "}else{" + + " $_ = $proceed($$);" + + "}"); + return; + } + } + });*/ + + // - Disable Smiting Titans - // + CtClass ctSmite = classPool.get("com.wurmonline.server.spells.Smite"); + replace = "if("+Arena.class.getName()+".isTitan($3)){" + + " $2.getCommunicator().sendNormalServerMessage(\"You cannot smite a Titan!\");" + + " return false;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctSmite, "precondition", replace); + /*ctSmite.getDeclaredMethod("precondition").insertBefore("" + + "if(mod.sin.wyvern.arena.Arena.isTitan($3)){" + + " $2.getCommunicator().sendNormalServerMessage(\"You cannot smite a Titan!\");" + + " return false;" + + "}");*/ + + // - Allow players to do actions in PvP houses - // + CtClass ctMethods = classPool.get("com.wurmonline.server.behaviours.Methods"); + Util.instrumentDeclared(thisClass, ctMethods, "isNotAllowedMessage", "isEnemy", "$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"); + /*ctMethods.getDeclaredMethod("isNotAllowedMessage").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isEnemy")) { + m.replace("$_ = com.wurmonline.server.Servers.localServer.PVPSERVER;"); + return; + } + } + });*/ + + // - Allow stealing against deity wishes without being punished on Arena - // + //CtClass ctAction = classPool.get("com.wurmonline.server.behaviours.Action"); + Util.instrumentDeclared(thisClass, ctAction, "checkLegalMode", "isLibila", "$_ = $proceed($$) || com.wurmonline.server.Servers.localServer.PVPSERVER;"); + /*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; + } + } + });*/ + + // - Allow taking ownership of vehicles on Arena - // + 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); + + // - Allow managing animals on Arena - // + CtClass ctManageMenu = classPool.get("com.wurmonline.server.behaviours.ManageMenu"); + replace = "$_ = false;"; + Util.instrumentDeclared(thisClass, ctManageMenu, "getBehavioursFor", "isThisAPvpServer", replace); + /*ctManageMenu.getDeclaredMethod("getBehavioursFor").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isThisAPvpServer")) { + m.replace("$_ = false;"); + return; + } + } + });*/ + Util.instrumentDeclared(thisClass, ctManageMenu, "action", "isThisAPvpServer", replace); + /*ctManageMenu.getDeclaredMethod("action").instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("isThisAPvpServer")) { + m.replace("$_ = false;"); + return; + } + } + });*/ + + // - 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; + } + } + });*/ + + // - 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;" + + "}");*/ + + // - Disable CA Help on Arena - // + replace = "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return false;" + + "}"; + Util.insertBeforeDeclared(thisClass, ctPlayer, "seesPlayerAssistantWindow", replace); + /*ctPlayer.getDeclaredMethod("seesPlayerAssistantWindow").insertBefore("" + + "if(com.wurmonline.server.Servers.localServer.PVPSERVER){" + + " return false;" + + "}");*/ + + }catch (NotFoundException e) { + throw new HookException((Throwable)e); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/arena/SupplyDepots.java b/src/main/java/mod/sin/wyvern/arena/SupplyDepots.java new file mode 100644 index 0000000..9d68df1 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/arena/SupplyDepots.java @@ -0,0 +1,211 @@ +package mod.sin.wyvern.arena; + +import java.util.ArrayList; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modloader.classhooks.HookException; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.FailedException; +import com.wurmonline.server.Items; +import com.wurmonline.server.Players; +import com.wurmonline.server.Server; +import com.wurmonline.server.Servers; +import com.wurmonline.server.TimeConstants; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.Creatures; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.NoSuchTemplateException; +import com.wurmonline.server.players.Player; +import com.wurmonline.server.zones.Zones; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.NotFoundException; +import mod.sin.items.ArenaSupplyDepot; +import mod.sin.items.caches.*; +import mod.sin.wyvern.MiscChanges; +import mod.sin.wyvern.WyvernMods; +import mod.sin.wyvern.util.ItemUtil; + +public class SupplyDepots { + private static Logger logger = Logger.getLogger(SupplyDepots.class.getName()); + public static ArrayList depots = new ArrayList(); + public static Creature host = null; + public static final long depotRespawnTime = TimeConstants.HOUR_MILLIS*7L; + public static long lastSpawnedDepot = 0; + public static void sendDepotEffect(Player player, Item depot){ + player.getCommunicator().sendAddEffect(depot.getWurmId(), (byte) 25, depot.getPosX(), depot.getPosY(), depot.getPosZ(), (byte) 0); + } + public static void sendDepotEffectsToPlayer(Player player){ + logger.info("Sending depot effects to player "+player.getName()); + for(Item depot : depots){ + sendDepotEffect(player, depot); + } + } + public static void sendDepotEffectsToPlayers(Item depot){ + for(Player p : Players.getInstance().getPlayers()){ + sendDepotEffect(p, depot); + } + } + public static void removeDepotEffect(Item depot){ + for(Player player : Players.getInstance().getPlayers()){ + player.getCommunicator().sendRemoveEffect(depot.getWurmId()); + } + } + public static void removeSupplyDepot(Item depot){ + if(depots.contains(depot)){ + depots.remove(depot); + } + removeDepotEffect(depot); + } + private static boolean isSupplyDepot(Item item){ + return item.getTemplateId() == ArenaSupplyDepot.templateId; + } + public static void pollDepotSpawn(){ + if(!Servers.localServer.PVPSERVER && !WyvernMods.enableDepots){ + return; + } + for(int i = 0; i < depots.size(); i++){ + Item depot = depots.get(i); + if(!Items.exists(depot)){ + logger.info("Supply depot was destroyed, removing from list."); + depots.remove(depot); + removeDepotEffect(depot); + } + } + for(Item item : Items.getAllItems()){ + if(isSupplyDepot(item) && !depots.contains(item)){ + logger.info("Found existing supply depots, adding to list and sending data to players."); + depots.add(item); + sendDepotEffectsToPlayers(item); + } + } + if(depots.isEmpty()){ + if(host == null){ + ArrayList uniques = new ArrayList(); + for(Creature c : Creatures.getInstance().getCreatures()){ + if(c.isUnique()){ + uniques.add(c); + } + } + if(uniques.size() > 0){ + host = uniques.get(Server.rand.nextInt(uniques.size())); + MiscChanges.sendImportantMessage(host, "Greetings! I'll be your host, informing you of the next depot to appear over here on the Arena!", 255, 128, 0); + } + } + if(System.currentTimeMillis() > lastSpawnedDepot + depotRespawnTime){ + logger.info("No Depots were found, and the timer has expired. Spawning a new one."); + boolean spawned = false; + int i = 0; + while(!spawned && i < 20){ + float worldSizeX = Zones.worldTileSizeX; + float worldSizeY = Zones.worldTileSizeY; + float minX = worldSizeX*0.25f; + float minY = worldSizeY*0.25f; + int tilex = (int) (minX+(minX*2*Server.rand.nextFloat())); + int tiley = (int) (minY+(minY*2*Server.rand.nextFloat())); + int tile = Server.surfaceMesh.getTile(tilex, tiley); + try { + if(Tiles.decodeHeight((int)tile) > 0){ + Item depot = ItemFactory.createItem(ArenaSupplyDepot.templateId, 50+Server.rand.nextFloat()*40f, (float)(tilex << 2) + 2.0f, (float)(tiley << 2) + 2.0f, Server.rand.nextFloat() * 360.0f, true, (byte) 0, -10, null); + depots.add(depot); + sendDepotEffectsToPlayers(depot); + if(host != null){ + MiscChanges.sendImportantMessage(host, "A new depot has appeared on the Arena!", 255, 128, 0); + } + logger.info("New supply depot being placed at "+tilex+", "+tiley); + spawned = true; + host = null; + lastSpawnedDepot = System.currentTimeMillis(); + }else{ + logger.info("Position "+tilex+", "+tiley+" was invalid, attempting another spawn..."); + i++; + } + } catch (Exception e) { + logger.severe("Failed to create Arena Depot."); + e.printStackTrace(); + } + } + if(i >= 20){ + logger.warning("Could not find a valid location within 20 tries for a supply depot."); + } + }else if(host != null){ + long timeleft = (lastSpawnedDepot + depotRespawnTime) - System.currentTimeMillis(); + long minutesLeft = timeleft/TimeConstants.MINUTE_MILLIS; + if(minutesLeft > 0){ + if(minutesLeft == 1){ + MiscChanges.sendImportantMessage(host, "Come quickly! The next Arena depot will appear in 5 minutes!", 255, 128, 0); + }else if(minutesLeft == 19){ + MiscChanges.sendImportantMessage(host, "Best start heading over, the next Arena depot will appear in 20 minutes!", 255, 128, 0); + }else if(minutesLeft == 59){ + MiscChanges.sendImportantMessage(host, "Heads up! The next Arena depot will appear in 60 minutes!", 255, 128, 0); + } + } + } + } + } + + public static long lastAttemptedDepotCapture = 0; + public static final long captureMessageInterval = TimeConstants.MINUTE_MILLIS*3L; + public static void maybeBroadcastOpen(Creature performer){ + if(System.currentTimeMillis() > lastAttemptedDepotCapture + captureMessageInterval){ + MiscChanges.sendImportantMessage(performer, performer.getName()+" is begnning to capture an Arena depot!", 255, 128, 0); + lastAttemptedDepotCapture = System.currentTimeMillis(); + } + } + public static void giveCacheReward(Creature performer){ + Item inv = performer.getInventory(); + Item enchantOrb = ItemUtil.createEnchantOrb(130f+(Server.rand.nextFloat()*20)); + inv.insertItem(enchantOrb); + try { + // Add a special caches as a reward. + int[] cacheIds = { + ArmourCache.templateId, + ArtifactCache.templateId, + CrystalCache.templateId, + DragonCache.templateId, + GemCache.templateId, + MoonCache.templateId, + RiftCache.templateId, + TreasureMapCache.templateId + }; + int i = 1+Server.rand.nextInt(3); // 2-4 caches extra. + while(i >= 0){ + Item cache = ItemFactory.createItem(cacheIds[Server.rand.nextInt(cacheIds.length)], 80f+(20f*Server.rand.nextFloat()), ""); + inv.insertItem(cache, true); + i--; + } + if(Server.rand.nextFloat()*100f <= 10f){ + Item hotaStatue = ItemFactory.createItem(ItemList.statueHota, 80f+(20f*Server.rand.nextFloat()), ""); + hotaStatue.setAuxData((byte)Server.rand.nextInt(10)); + hotaStatue.setWeight(50000, true); + inv.insertItem(hotaStatue, true); + } + if(Server.rand.nextFloat()*100f <= 3f){ + Item sorcery = ItemFactory.createItem(ItemUtil.sorceryIds[Server.rand.nextInt(ItemUtil.sorceryIds.length)], 80f+(20f*Server.rand.nextFloat()), ""); + sorcery.setAuxData((byte)2); + inv.insertItem(sorcery, true); + } + } catch (FailedException | NoSuchTemplateException e) { + e.printStackTrace(); + } + } + + public static void preInit(){ + try{ + ClassPool classPool = HookManager.getInstance().getClassPool(); + + // - Add light effects for the supply depots, since they are unique - // + CtClass ctPlayers = classPool.get("com.wurmonline.server.Players"); + ctPlayers.getDeclaredMethod("sendAltarsToPlayer").insertBefore("mod.sin.wyvern.arena.SupplyDepots.sendDepotEffectsToPlayer($1);"); + + }catch (CannotCompileException | NotFoundException e) { + throw new HookException((Throwable)e); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java b/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java new file mode 100644 index 0000000..4754e4c --- /dev/null +++ b/src/main/java/mod/sin/wyvern/bestiary/MethodsBestiary.java @@ -0,0 +1,470 @@ +package mod.sin.wyvern.bestiary; + +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modloader.ReflectionUtil; + +import com.wurmonline.server.FailedException; +import com.wurmonline.server.Server; +import com.wurmonline.server.combat.Archery; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureStatus; +import com.wurmonline.server.creatures.CreatureTemplate; +import com.wurmonline.server.creatures.CreatureTemplateFactory; +import com.wurmonline.server.creatures.NoSuchCreatureTemplateException; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemSpellEffects; +import com.wurmonline.server.items.Materials; +import com.wurmonline.server.items.NoSuchTemplateException; +import com.wurmonline.server.skills.SkillList; +import com.wurmonline.server.skills.Skills; +import com.wurmonline.server.skills.SkillsFactory; +import com.wurmonline.server.spells.SpellEffect; +import com.wurmonline.shared.constants.Enchants; + +import mod.sin.creatures.*; +import mod.sin.creatures.titans.*; +import mod.sin.weapons.Club; +import mod.sin.weapons.titan.*; +import mod.sin.wyvern.MiscChanges; +import mod.sin.wyvern.arena.Arena; + +public class MethodsBestiary { + protected static Logger logger = Logger.getLogger(MethodsBestiary.class.getName()); + + public static boolean checkColorTemplate(CreatureTemplate template){ + try { + int templateId = template.getTemplateId(); + if(templateId == Lilith.templateId){ + return true; + }else if(templateId == ForestSpider.templateId){ + return true; + }else if(templateId == Avenger.templateId){ + return true; + }else if(templateId == HornedPony.templateId){ + return true; + }else if(templateId == LilithZombie.templateId){ + return true; + } + } catch (IllegalArgumentException | ClassCastException e) { + e.printStackTrace(); + } + return false; + } + + public static byte getCreatureColorRed(CreatureTemplate template){ + try { + int templateId = template.getTemplateId(); + if(templateId == ForestSpider.templateId){ + return (byte)0; + }else if(templateId == Avenger.templateId){ + return (byte)70; + } + } catch (IllegalArgumentException | ClassCastException e) { + e.printStackTrace(); + } + return (byte)127; + } + + public static byte getCreatureColorGreen(CreatureTemplate template){ + try { + int templateId = template.getTemplateId(); + if(templateId == Lilith.templateId){ + return (byte)0; + }else if(templateId == Avenger.templateId){ + return (byte)70; + }else if(templateId == HornedPony.templateId){ + return (byte)10; + }else if(templateId == LilithZombie.templateId){ + return (byte)0; + } + } catch (IllegalArgumentException | ClassCastException e) { + e.printStackTrace(); + } + return (byte)127; + } + + public static byte getCreatureColorBlue(CreatureTemplate template){ + try { + int templateId = template.getTemplateId(); + if(templateId == Lilith.templateId){ + return (byte)0; + }else if(templateId == ForestSpider.templateId){ + return (byte)0; + }else if(templateId == HornedPony.templateId){ + return (byte)70; + }else if(templateId == LilithZombie.templateId){ + return (byte)0; + } + } catch (IllegalArgumentException | ClassCastException e) { + e.printStackTrace(); + } + return (byte)127; + } + + public static float getAdjustedSizeMod(CreatureStatus status){ + try { + float floatToRet = 1.0f; + Creature statusHolder = ReflectionUtil.getPrivateField(status, ReflectionUtil.getField(status.getClass(), "statusHolder")); + byte modtype = ReflectionUtil.getPrivateField(status, ReflectionUtil.getField(status.getClass(), "modtype")); + float ageSizeModifier = ReflectionUtil.callPrivateMethod(status, ReflectionUtil.getMethod(status.getClass(), "getAgeSizeModifier")); + if ((!statusHolder.isVehicle() || statusHolder.isDragon()) && modtype > 0) { + switch (modtype) { + case 3: { + floatToRet = 1.4f; + break; + } + case 4: { + floatToRet = 2.0f; + break; + } + case 6: { + floatToRet = 2.0f; + break; + } + case 7: { + floatToRet = 0.8f; + break; + } + case 8: { + floatToRet = 0.9f; + break; + } + case 9: { + floatToRet = 1.5f; + break; + } + case 10: { + floatToRet = 1.3f; + break; + } + case 99: { + floatToRet = 3.0f; + break; + } + default: { + //return floatToRet * ageSizeModifier; + } + } + } + int templateId = statusHolder.getTemplate().getTemplateId(); + if(templateId == Lilith.templateId){ + floatToRet *= 0.45f; + }else if(templateId == Ifrit.templateId){ + floatToRet *= 0.15f; // The base model is way too big. I'm tilted. + }else if(templateId == WyvernBlack.templateId){ + floatToRet *= 0.6f; + }else if(templateId == WyvernGreen.templateId){ + floatToRet *= 0.6f; + }else if(templateId == WyvernRed.templateId){ + floatToRet *= 0.6f; + }else if(templateId == WyvernWhite.templateId){ + floatToRet *= 0.6f; + }else if(templateId == MacroSlayer.templateId){ + floatToRet *= 1.5f; + }else if(templateId == ForestSpider.templateId){ + floatToRet *= 0.4f; + }else if(templateId == Avenger.templateId){ + floatToRet *= 0.35f; + }else if(templateId == LargeBoar.templateId){ + floatToRet *= 1.8f; + }else if(templateId == SpiritTroll.templateId){ + floatToRet *= 1.2f; + }else if(templateId == Giant.templateId){ + floatToRet *= 0.75f; + }else if(templateId == LilithZombie.templateId){ + floatToRet *= 0.75f; + }else if(templateId == Charger.templateId){ + floatToRet *= 1.5f; + } + + return floatToRet * ageSizeModifier; + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + return 1.0f; + } + + public static Item createNewTitanWeapon(String name, int[] templates){ + try { + Item titanWeapon; + int templateId = templates[Server.rand.nextInt(templates.length)]; + titanWeapon = ItemFactory.createItem(templateId, 90f+(Server.rand.nextFloat()*5f), Materials.MATERIAL_ADAMANTINE, Server.rand.nextBoolean() ? (byte) 2 : (byte) 3, name); + ItemSpellEffects effs = titanWeapon.getSpellEffects(); + if(effs == null){ + effs = new ItemSpellEffects(titanWeapon.getWurmId()); + } + if(templateId == MaartensMight.templateId){ + effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_NIMBLENESS, 250, 20000000)); + effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), (byte) 111, 200, 20000000)); // Phasing + }else if(templateId == RaffehsRage.templateId){ + effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_FLAMING_AURA, 150, 20000000)); + effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_FROSTBRAND, 150, 20000000)); + }else if(templateId == VindictivesVengeance.templateId){ + effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_BLESSINGDARK, 300, 20000000)); + effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_NIMBLENESS, 200, 20000000)); + }else if(templateId == WilhelmsWrath.templateId){ + effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_ROTTING_TOUCH, 300, 20000000)); + effs.addSpellEffect(new SpellEffect(titanWeapon.getWurmId(), Enchants.BUFF_BLOODTHIRST, 100, 20000000)); + } + if(titanWeapon != null){ + return titanWeapon; + } + } catch (FailedException | NoSuchTemplateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + public static boolean isArcheryImmune(Creature performer, Creature defender){ + if(Arena.isTitan(defender) || Arena.isTitanMinion(defender)){ + performer.getCommunicator().sendCombatNormalMessage("You cannot archer "+defender.getName()+", as it is protected by a Titan."); + return true; + } + String message = "The "+defender.getName()+" would be unaffected by your arrows."; + boolean immune = false; + Item arrow = Archery.getArrow(performer); + if(arrow == null){ // Copied directly from the attack() method in Archery. + performer.getCommunicator().sendCombatNormalMessage("You have no arrows left to shoot!"); + return true; + } + //int defenderTemplateId = defender.getTemplate().getTemplateId(); + if(defender.isRegenerating() && arrow.getTemplateId() == ItemList.arrowShaft){ + message = "The "+defender.getName()+" would be unaffected by the "+arrow.getName()+"."; + immune = true; + }else if(defender.getTemplate().isNotRebirthable()){ + immune = true; + }else if(defender.isUnique()){ + immune = true; + } + if(immune){ + performer.getCommunicator().sendCombatNormalMessage(message); + } + return immune; + } + + public static void modifyNewCreature(Creature creature){ + try{ + if(Arena.isTitan(creature)){ + Arena.addTitan(creature); + MiscChanges.sendGlobalFreedomChat(creature, "The titan "+creature.getName()+" has stepped into the mortal realm. Challenge "+creature.getHimHerItString()+" in the Arena if you dare.", 255, 105, 180); + if(creature.getTemplate().getTemplateId() == Lilith.templateId){ + Item titanWeapon = createNewTitanWeapon(creature.getName(), new int[]{VindictivesVengeance.templateId, WilhelmsWrath.templateId}); + creature.getInventory().insertItem(titanWeapon); + }else if(creature.getTemplate().getTemplateId() == Ifrit.templateId){ + Item titanWeapon = createNewTitanWeapon(creature.getName(), new int[]{MaartensMight.templateId, RaffehsRage.templateId}); + creature.getInventory().insertItem(titanWeapon); + } + }else if(creature.getTemplate().getTemplateId() == Facebreyker.templateId){ + Item club = ItemFactory.createItem(Club.templateId, 80f+(Server.rand.nextFloat()*15f), Server.rand.nextBoolean() ? Materials.MATERIAL_GLIMMERSTEEL : Materials.MATERIAL_ADAMANTINE, Server.rand.nextBoolean() ? (byte) 1 : (byte) 2, "Facebreyker"); + creature.getInventory().insertItem(club); + } + }catch(Exception e){ + e.printStackTrace(); + } + } + + private static void setNaturalArmour(int templateId, float value){ + try{ + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId); + if(template != null){ + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "naturalArmour"), value); + } + } catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + + private static void setCorpseModel(int templateId, String model){ + try{ + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId); + if(template != null){ + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "corpsename"), model); + } + } catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + + private static void setGhost(int templateId){ + try{ + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId); + if(template != null){ + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "ghost"), true); + } + } catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + + private static void setGrazer(int templateId){ + try{ + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId); + if(template != null){ + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "grazer"), true); + } + } catch (NoSuchCreatureTemplateException | IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + + private static void setWorgFields(int templateId) { + try { + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(templateId); + if(template != null) { + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "isVehicle"), true); + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "dominatable"), true); + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "isHorse"), true); + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "isDetectInvis"), false); + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "monster"), true); + Skills skills = SkillsFactory.createSkills("Worg"); + skills.learnTemp(SkillList.BODY_STRENGTH, 40.0f); + skills.learnTemp(SkillList.BODY_CONTROL, 25.0f); + skills.learnTemp(SkillList.BODY_STAMINA, 35.0f); + skills.learnTemp(SkillList.MIND_LOGICAL, 10.0f); + skills.learnTemp(SkillList.MIND_SPEED, 15.0f); + skills.learnTemp(SkillList.SOUL_STRENGTH, 20.0f); + skills.learnTemp(SkillList.SOUL_DEPTH, 12.0f); + skills.learnTemp(SkillList.WEAPONLESS_FIGHTING, 50.0f); + ReflectionUtil.setPrivateField(template, ReflectionUtil.getField(template.getClass(), "skills"), skills); + } // if + } catch (Exception e) { + e.printStackTrace(); + } // catch + } // setWorgFields + + public static void setTemplateVariables(){ + // Set corpse models + setCorpseModel(Avenger.templateId, "fogspider."); + setCorpseModel(SpiritTroll.templateId, "fogspider."); + setCorpseModel(SpectralDrake.templateId, "fogspider."); + /*CreatureTemplate spectralDrake = CreatureTemplateFactory.getInstance().getTemplate(SpectralDrake.templateId); + if(spectralDrake != null){ + ReflectionUtil.setPrivateField(spectralDrake, ReflectionUtil.getField(spectralDrake.getClass(), "corpsename"), "fogspider."); + }*/ + setCorpseModel(WyvernBlack.templateId, "blackdragonhatchling."); + /*CreatureTemplate blackWyvern = CreatureTemplateFactory.getInstance().getTemplate(WyvernBlack.templateId); + if(blackWyvern != null){ + ReflectionUtil.setPrivateField(blackWyvern, ReflectionUtil.getField(blackWyvern.getClass(), "corpsename"), "blackdragonhatchling."); + }*/ + setCorpseModel(WyvernGreen.templateId, "greendragonhatchling."); + /*CreatureTemplate greenWyvern = CreatureTemplateFactory.getInstance().getTemplate(WyvernGreen.templateId); + if(greenWyvern != null){ + ReflectionUtil.setPrivateField(greenWyvern, ReflectionUtil.getField(greenWyvern.getClass(), "corpsename"), "greendragonhatchling."); + }*/ + setCorpseModel(WyvernRed.templateId, "reddragonhatchling."); + /*CreatureTemplate redWyvern = CreatureTemplateFactory.getInstance().getTemplate(WyvernRed.templateId); + if(redWyvern != null){ + ReflectionUtil.setPrivateField(redWyvern, ReflectionUtil.getField(redWyvern.getClass(), "corpsename"), "reddragonhatchling."); + }*/ + setCorpseModel(WyvernWhite.templateId, "whitedragonhatchling."); + /*CreatureTemplate whiteWyvern = CreatureTemplateFactory.getInstance().getTemplate(WyvernWhite.templateId); + if(whiteWyvern != null){ + ReflectionUtil.setPrivateField(whiteWyvern, ReflectionUtil.getField(whiteWyvern.getClass(), "corpsename"), "whitedragonhatchling."); + }*/ + setCorpseModel(Facebreyker.templateId, "riftogre."); + /*CreatureTemplate facebreyker = CreatureTemplateFactory.getInstance().getTemplate(Facebreyker.templateId); + if(facebreyker != null){ + ReflectionUtil.setPrivateField(facebreyker, ReflectionUtil.getField(facebreyker.getClass(), "corpsename"), "riftogre."); + }*/ + setCorpseModel(ForestSpider.templateId, "hugespider."); + /*CreatureTemplate forestSpider = CreatureTemplateFactory.getInstance().getTemplate(ForestSpider.templateId); + if(forestSpider != null){ + ReflectionUtil.setPrivateField(forestSpider, ReflectionUtil.getField(forestSpider.getClass(), "corpsename"), "hugespider."); + }*/ + setCorpseModel(Giant.templateId, "forestgiant."); + /*CreatureTemplate giant = CreatureTemplateFactory.getInstance().getTemplate(Giant.templateId); + if(giant != null){ + ReflectionUtil.setPrivateField(giant, ReflectionUtil.getField(giant.getClass(), "corpsename"), "forestgiant."); + }*/ + setCorpseModel(LargeBoar.templateId, "wildboar."); + /*CreatureTemplate largeBoar = CreatureTemplateFactory.getInstance().getTemplate(LargeBoar.templateId); + if(largeBoar != null){ + ReflectionUtil.setPrivateField(largeBoar, ReflectionUtil.getField(largeBoar.getClass(), "corpsename"), "wildboar."); + }*/ + setCorpseModel(HornedPony.templateId, "unicorn."); + /*CreatureTemplate hornedPony = CreatureTemplateFactory.getInstance().getTemplate(HornedPony.templateId); + if(hornedPony != null){ + ReflectionUtil.setPrivateField(hornedPony, ReflectionUtil.getField(hornedPony.getClass(), "corpsename"), "unicorn."); + }*/ + setCorpseModel(IfritSpider.templateId, "lavaspider."); + /*CreatureTemplate ifritSpider = CreatureTemplateFactory.getInstance().getTemplate(IfritSpider.templateId); + if(ifritSpider != null){ + ReflectionUtil.setPrivateField(ifritSpider, ReflectionUtil.getField(ifritSpider.getClass(), "corpsename"), "lavaspider."); + }*/ + setCorpseModel(IfritFiend.templateId, "lavafiend."); + /*CreatureTemplate ifritFiend = CreatureTemplateFactory.getInstance().getTemplate(IfritFiend.templateId); + if(ifritFiend != null){ + ReflectionUtil.setPrivateField(ifritFiend, ReflectionUtil.getField(ifritFiend.getClass(), "corpsename"), "lavafiend."); + }*/ + // Also apply the ghost modifier + setGhost(SpiritTroll.templateId); + setGhost(Avenger.templateId); + setGhost(LilithWraith.templateId); + setGhost(Charger.templateId); + /*CreatureTemplate spiritTroll = CreatureTemplateFactory.getInstance().getTemplate(SpiritTroll.templateId); + if(spiritTroll != null){ + ReflectionUtil.setPrivateField(spiritTroll, ReflectionUtil.getField(spiritTroll.getClass(), "ghost"), true); + } + CreatureTemplate avenger = CreatureTemplateFactory.getInstance().getTemplate(Avenger.templateId); + if(avenger != null){ + ReflectionUtil.setPrivateField(avenger, ReflectionUtil.getField(avenger.getClass(), "ghost"), true); + } + CreatureTemplate lilithWight = CreatureTemplateFactory.getInstance().getTemplate(LilithWraith.templateId); + if(lilithWight != null){ + ReflectionUtil.setPrivateField(lilithWight, ReflectionUtil.getField(lilithWight.getClass(), "ghost"), true); + } + CreatureTemplate charger = CreatureTemplateFactory.getInstance().getTemplate(Charger.templateId); + if(charger != null){ + ReflectionUtil.setPrivateField(charger, ReflectionUtil.getField(charger.getClass(), "ghost"), true); + }*/ + + // Dragon natural armour increases: + setNaturalArmour(CreatureTemplate.DRAGON_BLUE_CID, 0.04f); + /*CreatureTemplate dragonBlue = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAGON_BLUE_CID); + ReflectionUtil.setPrivateField(dragonBlue, ReflectionUtil.getField(dragonBlue.getClass(), "naturalArmour"), 0.05f);*/ + setNaturalArmour(CreatureTemplate.DRAGON_WHITE_CID, 0.04f); + /*CreatureTemplate dragonGreen = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAGON_WHITE_CID); + ReflectionUtil.setPrivateField(dragonGreen, ReflectionUtil.getField(dragonGreen.getClass(), "naturalArmour"), 0.05f);*/ + setNaturalArmour(CreatureTemplate.DRAGON_BLACK_CID, 0.055f); + /*CreatureTemplate dragonBlack = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAGON_BLACK_CID); + ReflectionUtil.setPrivateField(dragonBlack, ReflectionUtil.getField(dragonBlack.getClass(), "naturalArmour"), 0.07f);*/ + setNaturalArmour(CreatureTemplate.DRAGON_WHITE_CID, 0.04f); + /*CreatureTemplate dragonWhite = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAGON_WHITE_CID); + ReflectionUtil.setPrivateField(dragonWhite, ReflectionUtil.getField(dragonWhite.getClass(), "naturalArmour"), 0.05f);*/ + // Drake natural armour increases: + setNaturalArmour(CreatureTemplate.DRAKE_RED_CID, 0.075f); + /*CreatureTemplate drakeRed = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_RED_CID); + ReflectionUtil.setPrivateField(drakeRed, ReflectionUtil.getField(drakeRed.getClass(), "naturalArmour"), 0.085f);*/ + setNaturalArmour(CreatureTemplate.DRAKE_BLUE_CID, 0.075f); + /*CreatureTemplate drakeBlue = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_BLUE_CID); + ReflectionUtil.setPrivateField(drakeBlue, ReflectionUtil.getField(drakeBlue.getClass(), "naturalArmour"), 0.085f);*/ + setNaturalArmour(CreatureTemplate.DRAKE_WHITE_CID, 0.085f); + /*CreatureTemplate drakeWhite = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_WHITE_CID); + ReflectionUtil.setPrivateField(drakeWhite, ReflectionUtil.getField(drakeWhite.getClass(), "naturalArmour"), 0.1f);*/ + setNaturalArmour(CreatureTemplate.DRAKE_GREEN_CID, 0.075f); + /*CreatureTemplate drakeGreen = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_GREEN_CID); + ReflectionUtil.setPrivateField(drakeGreen, ReflectionUtil.getField(drakeGreen.getClass(), "naturalArmour"), 0.085f);*/ + setNaturalArmour(CreatureTemplate.DRAKE_BLACK_CID, 0.065f); + /*CreatureTemplate drakeBlack = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.DRAKE_BLACK_CID); + ReflectionUtil.setPrivateField(drakeBlack, ReflectionUtil.getField(drakeBlack.getClass(), "naturalArmour"), 0.065f);*/ + // Goblin leader natural armour increase: + setNaturalArmour(CreatureTemplate.GOBLIN_LEADER_CID, 0.075f); + /*CreatureTemplate goblinLeader = CreatureTemplateFactory.getInstance().getTemplate(CreatureTemplate.GOBLIN_LEADER_CID); + ReflectionUtil.setPrivateField(goblinLeader, ReflectionUtil.getField(goblinLeader.getClass(), "naturalArmour"), 0.085f);*/ + + // Set hens and roosters as grazers + setGrazer(CreatureTemplate.HEN_CID); + setGrazer(CreatureTemplate.CHICKEN_CID); + setGrazer(CreatureTemplate.ROOSTER_CID); + setGrazer(CreatureTemplate.PIG_CID); + + // Set worg fields + setWorgFields(CreatureTemplate.WORG_CID); + } +} diff --git a/src/main/java/mod/sin/wyvern/bounty/LootBounty.java b/src/main/java/mod/sin/wyvern/bounty/LootBounty.java new file mode 100644 index 0000000..5550965 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/bounty/LootBounty.java @@ -0,0 +1,572 @@ +package mod.sin.wyvern.bounty; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Random; +import java.util.logging.Logger; + +import com.wurmonline.mesh.Tiles; +import com.wurmonline.server.FailedException; +import com.wurmonline.server.HistoryManager; +import com.wurmonline.server.Players; +import com.wurmonline.server.Server; +import com.wurmonline.server.Servers; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.creatures.CreatureTemplate; +import com.wurmonline.server.creatures.CreatureTemplateFactory; +import com.wurmonline.server.creatures.Creatures; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemTemplate; +import com.wurmonline.server.items.ItemTemplateFactory; +import com.wurmonline.server.items.NoSuchTemplateException; +import com.wurmonline.server.villages.Village; +import com.wurmonline.server.villages.Villages; +import mod.sin.armour.SpectralHide; +import mod.sin.creatures.Reaper; +import mod.sin.creatures.SpectralDrake; +import mod.sin.items.ChaosCrystal; +import mod.sin.items.EnchantersCrystal; +import mod.sin.items.FriyanTablet; +import mod.sin.wyvern.Bounty; +import mod.sin.wyvern.MiscChanges; +import mod.sin.wyvern.arena.Arena; +import mod.sin.wyvern.util.ItemUtil; + +public class LootBounty { + public static final Logger logger = Logger.getLogger(LootBounty.class.getName()); + protected static final Random random = new Random(); + + public static void displayLootAssistance(Creature mob){ + if(Bounty.dealtDamage.containsKey(mob.getWurmId())){ + logger.info("Found the damageDealt entry, parsing..."); + ArrayList names = new ArrayList(); + ArrayList damages = new ArrayList(); + for(long creatureId : Bounty.dealtDamage.get(mob.getWurmId()).keySet()){ + if(Players.getInstance().getPlayerOrNull(creatureId) != null){ + names.add(Players.getInstance().getPlayerOrNull(creatureId).getName()); + damages.add(Bounty.dealtDamage.get(mob.getWurmId()).get(creatureId)); + }else{ + if(Creatures.getInstance().getCreatureOrNull(creatureId) != null){ + logger.info("Skipping creature "+Creatures.getInstance().getCreatureOrNull(creatureId).getName()+" in loot assistance."); + } + } + } + logger.info("Names have been added: "+names); + String strBuilder = "Loot Assistance ("+mob.getName()+"): "; + DecimalFormat formatter = new DecimalFormat("#,###,###"); + while(names.size() > 0){ + int index = Server.rand.nextInt(names.size()); + strBuilder += names.get(index); + strBuilder += " ["+formatter.format(Math.round(damages.get(index)))+"]"; + names.remove(index); + damages.remove(index); + if(names.size() > 0){ + strBuilder += ", "; + } + } + MiscChanges.sendServerTabMessage(strBuilder, 0, 128, 255); + logger.info("Broadcast loot assistance message success [Damage]."); + }else{ + logger.warning("Powerful creature "+mob.getName()+" died, but no players were credited to its death [Damage]."); + } + } + + public static int doRollingCrystalReward(Creature mob, Item corpse, double cretStr, int templateId, int chance, double reductionPerRoll){ + try { + double rollingCounter = cretStr; + int addedCrystals = 0; + /*if(mob.isUnique()){ // Uniques will drop 3x as many, and have special properties to enable dropping rare and possibly supreme versions as well. + rollingCounter *= 3; + }else if(Servers.localServer.PVPSERVER){ // Arena gives double the amount of crystals. + rollingCounter *= 2; + }*/ + while(rollingCounter > 0){ + if(random.nextInt(chance+addedCrystals) == 0){ // Give a chance at a crystal, decreasing with the amount of crystals contained. + // The crystal quality is the cube root of the rolling counter, capped at 100 of course + Item chaosCrystal = ItemFactory.createItem(templateId, (float) (random.nextFloat()*Math.min(100, Math.cbrt(rollingCounter))), ""); + if(random.nextInt(40) == 0){ + chaosCrystal.setRarity((byte) 1); + }else if(mob.isUnique() && random.nextInt(5) == 0){ + if(random.nextInt(5) == 0){ + chaosCrystal.setRarity((byte) 2); + }else{ + chaosCrystal.setRarity((byte) 1); + } + } + corpse.insertItem(chaosCrystal); + addedCrystals++; + } + rollingCounter -= reductionPerRoll; + } + return addedCrystals; + } catch (FailedException | NoSuchTemplateException e) { + e.printStackTrace(); + } + return 0; + } + + public static void blessWorldWithMoonVeins(Creature mob){ + int i = 20; + while(i > 0){ + int x = random.nextInt(Server.surfaceMesh.getSize()); + int y = random.nextInt(Server.surfaceMesh.getSize()); + short height = Tiles.decodeHeight(Server.surfaceMesh.getTile(x, y)); + int type = Tiles.decodeType((int)Server.caveMesh.getTile(x, y)); + if(height >= 100 && (type == Tiles.Tile.TILE_CAVE_WALL.id || type == Tiles.Tile.TILE_CAVE.id)){ + Tiles.Tile tileType = random.nextBoolean() ? Tiles.Tile.TILE_CAVE_WALL_ORE_ADAMANTINE : Tiles.Tile.TILE_CAVE_WALL_ORE_GLIMMERSTEEL; + Server.caveMesh.setTile(x, y, Tiles.encode(Tiles.decodeHeight(Server.caveMesh.getTile(x, y)), tileType.id, Tiles.decodeData(Server.caveMesh.getTile(x, y)))); + Players.getInstance().sendChangedTile(x, y, false, true); + Server.setCaveResource(x, y, 400+random.nextInt(600)); + Village v = Villages.getVillage(x, y, true); + if (v == null) { + for (int vx = -50; vx < 50; vx += 5) { + for (int vy = -50; vy < 50 && (v = Villages.getVillage(x + vx, y + vy, true)) == null; vy += 5) { + } + } + } + if(v != null){ + HistoryManager.addHistory(mob.getTemplate().getName(), "blesses the world with a "+tileType.getName()+" near "+v.getName()+"!"); + } + logger.info("Placed a "+tileType.getName()+" at "+x+", "+y+" - "+height+" height"); + i--; + } + } + Server.getInstance().broadCastAlert("The death of the "+mob.getTemplate().getName()+" has blessed the world with valuable ores!"); + } + + public static void spawnFriyanTablets(){ + int i = 5+random.nextInt(5); + while(i > 0){ + int x = random.nextInt(Server.surfaceMesh.getSize()); + int y = random.nextInt(Server.surfaceMesh.getSize()); + short height = Tiles.decodeHeight(Server.surfaceMesh.getTile(x, y)); + if(height > 0 && height < 1000 && Creature.getTileSteepness(x, y, true)[1] < 30){ + try { + ItemFactory.createItem(FriyanTablet.templateId, 80f+random.nextInt(20), (float)x*4, (float)y*4, random.nextFloat()*360f, true, (byte)0, -10, "Friyanouce"); + logger.info("Created a Tablet of Friyan at "+x+", "+y+"."); + } catch (NoSuchTemplateException | FailedException e) { + e.printStackTrace(); + } + i--; + } + } + } + + public static void handleDragonLoot(Creature mob, Item corpse){ + try{ + int mTemplate = mob.getTemplate().getTemplateId(); + int lootTemplate = ItemList.drakeHide; + byte ctype = 0; + if(mTemplate == CreatureTemplateFactory.DRAGON_BLACK_CID || mTemplate == CreatureTemplateFactory.DRAGON_BLUE_CID || mTemplate == CreatureTemplateFactory.DRAGON_GREEN_CID + || mTemplate == CreatureTemplateFactory.DRAGON_RED_CID || mTemplate == CreatureTemplateFactory.DRAGON_WHITE_CID){ + //if(mTemplate == 16 || mTemplate == 89 || mTemplate == 91 || mTemplate == 90 || mTemplate == 92){ + ctype = 99; // Champion creature type + lootTemplate = ItemList.dragonScale; + //lootTemplate = 372; + }else{ + ctype = (byte)Math.max(0, Server.rand.nextInt(17) - 5); + } + + float x = mob.getPosX(); + float y = mob.getPosY(); + + // Spawn the spectral drake. + //logger.info("Spawning a spectral drake."); + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(SpectralDrake.templateId); // Spectral Drake ID: 2147483646 + Creature spectralDrake = Creature.doNew(template.getTemplateId(), true, x, y, random.nextFloat()*360.0f, mob.getLayer(), + template.getName(), (byte)0, mob.getKingdomId(), ctype, false, (byte)150); + Server.getInstance().broadCastAction("The spirit of the "+mob.getTemplate().getName()+" is released into the world!", mob, 20); + Server.getInstance().broadCastAlert(spectralDrake.getName()+" is released from the soul of the "+mob.getTemplate().getName()+", seeking vengeance for its physical form!"); + + // Insert extra hide / scale + + logger.info("Generating extra hide & scale to insert on the corpse of "+mob.getName()+"."); + ItemTemplate itemTemplate = ItemTemplateFactory.getInstance().getTemplate(lootTemplate); + for(int i = 0; i < 2; i++){ + Item loot = ItemFactory.createItem(lootTemplate, 80+(15*random.nextFloat()), ""); + String creatureName = mob.getTemplate().getName().toLowerCase(); + if (!loot.getName().contains(creatureName)){ + loot.setName(creatureName.toLowerCase() + " " + itemTemplate.getName()); + } + loot.setData2(mTemplate); + int weightGrams = itemTemplate.getWeightGrams() * (lootTemplate == 371 ? 3 : 1); + loot.setWeight((int)((weightGrams*0.1f)+(weightGrams*0.1f*random.nextFloat())), true); + corpse.insertItem(loot); + } + for(int i = 0; i < 4; i++){ + Item loot = ItemFactory.createItem(lootTemplate, 80+(15*random.nextFloat()), ""); + String creatureName = mob.getTemplate().getName().toLowerCase(); + if (!loot.getName().contains(creatureName)){ + loot.setName(creatureName.toLowerCase() + " " + itemTemplate.getName()); + } + loot.setData2(mTemplate); + int weightGrams = itemTemplate.getWeightGrams() * (lootTemplate == 371 ? 3 : 1); + loot.setWeight((int)((weightGrams*0.05f)+(weightGrams*0.05f*random.nextFloat())), true); + spectralDrake.getInventory().insertItem(loot); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void handleChampionLoot(Item corpse){ + try{ + corpse.insertItem(ItemUtil.createRandomLootTool()); + if(random.nextInt(100) < 75){ + corpse.insertItem(ItemFactory.createItem((random.nextBoolean() ? 694 : 698), 30+(30*random.nextFloat()), "")); + } + if(random.nextInt(100) < 5){ + //int[] maskTemplates = {973, 974, 975, 976, 977, 978, 1099}; + int[] maskTemplates = { + ItemList.maskEnlightended, + ItemList.maskRavager, + ItemList.maskPale, + ItemList.maskShadow, + ItemList.maskChallenge, + ItemList.maskIsles, + ItemList.maskOfTheReturner + }; + corpse.insertItem(ItemFactory.createItem(maskTemplates[random.nextInt(maskTemplates.length)], 90+(9*random.nextFloat()), "")); + } + if(random.nextInt(100) < 1){ + Item bone = ItemFactory.createItem(867, 90+(10*random.nextFloat()), ""); + bone.setRarity((byte)1); + if(random.nextInt(100) < 1){ + bone.setRarity((byte)2); + } + corpse.insertItem(bone); + } + } catch (FailedException | NoSuchTemplateException e) { + e.printStackTrace(); + } + } + + public static void checkLootTable(Creature mob, Item corpse){ + double cretStr = Bounty.getCreatureStrength(mob); + int numCrystals = 0; + double crystalStr = cretStr; + if(mob.isUnique()){ // Uniques will drop 3x as many, and have special properties to enable dropping rare and possibly supreme versions as well. + crystalStr *= 3; + }else if(Servers.localServer.PVPSERVER){ // Arena gives double the amount of crystals. + crystalStr *= 2.5; + } + // Award chaos crystals if the strength is high enough: + if(crystalStr > 3000){ // 30 copper + numCrystals += doRollingCrystalReward(mob, corpse, crystalStr, ChaosCrystal.templateId, 4, 5000); + /*double rollingCounter = cretStr; + int chance = 4; + int addedCrystals = 0; + if(mob.isUnique()){ // Uniques will drop 3x as many, and have special properties to enable dropping rare and possibly supreme versions as well. + rollingCounter *= 3; + }else if(Servers.localServer.PVPSERVER){ + rollingCounter *= 2; + } + while(rollingCounter > 0){ + // For every 50,000 creature strength, give a 1/8 chance at a chaos crystal + if(random.nextInt(chance+addedCrystals) == 0){ + // The crystal quality is the cube root of the rolling counter, capped at 100 of course + Item chaosCrystal = ItemFactory.createItem(ChaosCrystal.templateId, (float) (random.nextFloat()*Math.min(100, Math.cbrt(rollingCounter))), ""); + if(random.nextInt(40) == 0){ + chaosCrystal.setRarity((byte) 1); + }else if(mob.isUnique() && random.nextInt(5) == 0){ + if(random.nextInt(5) == 0){ + chaosCrystal.setRarity((byte) 2); + }else{ + chaosCrystal.setRarity((byte) 1); + } + } + corpse.insertItem(chaosCrystal); + addedCrystals++; + } + rollingCounter -= 5000; + } + if(addedCrystals > 0){ + hasCrystals = true; + }*/ + } + if(crystalStr > 10000){ // 1 silver + numCrystals += doRollingCrystalReward(mob, corpse, crystalStr, EnchantersCrystal.templateId, 5, 20000); + /*double rollingCounter = cretStr; + int chance = 5; + int addedCrystals = 0; + if(mob.isUnique()){ // Uniques will drop 3x as many, and have special properties to enable dropping rare and possibly supreme versions as well. + rollingCounter *= 3; + }else if(Servers.localServer.PVPSERVER){ + rollingCounter *= 2; + } + while(rollingCounter > 0){ + // For every 200,000 creature strength, give a 1/8 chance at a enchanters crystal + if(random.nextInt(chance+addedCrystals) == 0){ + // The crystal quality is the cube root of the rolling counter, capped at 100 of course + Item enchantersCrystal = ItemFactory.createItem(EnchantersCrystal.templateId, (float) (random.nextFloat()*Math.min(100, Math.cbrt(rollingCounter))), ""); + if(random.nextInt(40) == 0){ + enchantersCrystal.setRarity((byte) 1); + }else if(mob.isUnique() && random.nextInt(5) == 0){ + if(random.nextInt(5) == 0){ + enchantersCrystal.setRarity((byte) 2); + }else{ + enchantersCrystal.setRarity((byte) 1); + } + } + corpse.insertItem(enchantersCrystal); + addedCrystals++; + } + rollingCounter -= 20000; + } + if(addedCrystals > 0){ + hasCrystals = true; + }*/ + } + boolean sendLootHelp = false; + // Begin loot table drops + if(mob.getTemplate().getTemplateId() == Reaper.templateId){ + Server.getInstance().broadCastNormal("The "+mob.getName()+" has been slain."); + sendLootHelp = true; + }else if(mob.getTemplate().getTemplateId() == SpectralDrake.templateId){ + try{ + logger.info("Generating spectral hide for the corpse of the "+mob.getName()+"."); + for(int i = 0; i < 2; i++){ + Item spectralHide = ItemFactory.createItem(SpectralHide.templateId, 50+(50*random.nextFloat()), ""); + ItemTemplate itemTemplate = spectralHide.getTemplate(); + int weightGrams = itemTemplate.getWeightGrams(); + spectralHide.setWeight((int)((weightGrams*0.5f)+(weightGrams*0.5f*random.nextFloat())), true); + corpse.insertItem(spectralHide); + if(!mob.getStatus().isChampion()){ + break; + } + } + } catch (FailedException | NoSuchTemplateException e) { + e.printStackTrace(); + } + Server.getInstance().broadCastNormal("The "+mob.getName()+" has been slain."); + sendLootHelp = true; + }else if(Arena.isTitan(mob)){ + Server.getInstance().broadCastAlert("The Titan "+mob.getName()+" has been defeated!"); + MiscChanges.sendGlobalFreedomChat(mob, "The Titan "+mob.getName()+" has been defeated!", 255, 105, 180); + MiscChanges.sendServerTabMessage("The Titan "+mob.getName()+" has been defeated!", 255, 105, 180); + Arena.removeTitan(mob); + sendLootHelp = true; + } + if(mob.getTemplate().getTemplateId() == CreatureTemplateFactory.GOBLIN_CID){ + // Random lump of metal from goblins. + try{ + int[] lumpIds = { + //44, 45, 46, 47, 48, 49, 205, 221, 223, 220 + ItemList.adamantineBar, + ItemList.brassBar, + ItemList.bronzeBar, + ItemList.copperBar, + ItemList.glimmerSteelBar, + ItemList.goldBar, + ItemList.ironBar, + ItemList.leadBar, + ItemList.silverBar, + ItemList.steelBar, + ItemList.zincBar + }; + Item randomLump = ItemFactory.createItem(lumpIds[random.nextInt(lumpIds.length)], 20+(60*random.nextFloat()), ""); + corpse.insertItem(randomLump); + } catch (FailedException | NoSuchTemplateException e) { + e.printStackTrace(); + } + } + if(mob.isUnique()){ + // Spawn random addy/glimmer veins throughout the world + blessWorldWithMoonVeins(mob); + /*int i = 20; + while(i > 0){ + int x = random.nextInt(Server.surfaceMesh.getSize()); + int y = random.nextInt(Server.surfaceMesh.getSize()); + short height = Tiles.decodeHeight(Server.surfaceMesh.getTile(x, y)); + int type = Tiles.decodeType((int)Server.caveMesh.getTile(x, y)); + if(height >= 100 && (type == Tiles.Tile.TILE_CAVE_WALL.id || type == Tiles.Tile.TILE_CAVE.id)){ + Tiles.Tile tileType = random.nextBoolean() ? Tiles.Tile.TILE_CAVE_WALL_ORE_ADAMANTINE : Tiles.Tile.TILE_CAVE_WALL_ORE_GLIMMERSTEEL; + Server.caveMesh.setTile(x, y, Tiles.encode(Tiles.decodeHeight(Server.caveMesh.getTile(x, y)), tileType.id, Tiles.decodeData(Server.caveMesh.getTile(x, y)))); + Players.getInstance().sendChangedTile(x, y, false, true); + Server.setCaveResource(x, y, 400+random.nextInt(600)); + Village v = Villages.getVillage(x, y, true); + if (v == null) { + for (int vx = -50; vx < 50; vx += 5) { + for (int vy = -50; vy < 50 && (v = Villages.getVillage(x + vx, y + vy, true)) == null; vy += 5) { + } + } + } + if(v != null){ + HistoryManager.addHistory(mob.getTemplate().getName(), "blesses the world with a "+tileType.getName()+" near "+v.getName()+"!"); + } + logger.info("Placed a "+tileType.getName()+" at "+x+", "+y+" - "+height+" height"); + i--; + } + } + Server.getInstance().broadCastAlert("The death of the "+mob.getTemplate().getName()+" has blessed the world with valuable ores!");*/ + // Spawn 5-10 friyan tablets throughout the world. + spawnFriyanTablets(); + /*i = 5+random.nextInt(5); + while(i > 0){ + int x = random.nextInt(Server.surfaceMesh.getSize()); + int y = random.nextInt(Server.surfaceMesh.getSize()); + short height = Tiles.decodeHeight(Server.surfaceMesh.getTile(x, y)); + if(height > 0 && height < 1000 && Creature.getTileSteepness(x, y, true)[1] < 30){ + ItemFactory.createItem(FriyanTablet.templateId, 80f+random.nextInt(20), (float)x*4, (float)y*4, random.nextFloat()*360f, true, (byte)0, -10, "Friyanouce"); + logger.info("Created a Tablet of Friyan at "+x+", "+y+"."); + i--; + } + }*/ + + // Spawn Spectral Drake + if (mob.isDragon()) { // Spawn the spectral drake and add extra hide/scale + handleDragonLoot(mob, corpse); + /*int mTemplate = mob.getTemplate().getTemplateId(); + int lootTemplate = ItemList.drakeHide; + byte ctype = 0; + if(mTemplate == CreatureTemplateFactory.DRAGON_BLACK_CID || mTemplate == CreatureTemplateFactory.DRAGON_BLUE_CID || mTemplate == CreatureTemplateFactory.DRAGON_GREEN_CID + || mTemplate == CreatureTemplateFactory.DRAGON_RED_CID || mTemplate == CreatureTemplateFactory.DRAGON_WHITE_CID){ + //if(mTemplate == 16 || mTemplate == 89 || mTemplate == 91 || mTemplate == 90 || mTemplate == 92){ + ctype = 99; // Champion creature type + lootTemplate = ItemList.dragonScale; + //lootTemplate = 372; + }else{ + ctype = (byte)Math.max(0, Server.rand.nextInt(17) - 5); + } + + float x = mob.getPosX(); + float y = mob.getPosY(); + + // Spawn the spectral drake. + //logger.info("Spawning a spectral drake."); + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(SpectralDrake.templateId); // Spectral Drake ID: 2147483646 + Creature spectralDrake = Creature.doNew(template.getTemplateId(), true, x, y, random.nextFloat()*360.0f, mob.getLayer(), + template.getName(), (byte)0, mob.getKingdomId(), ctype, false, (byte)150); + Server.getInstance().broadCastAction("The spirit of the "+mob.getTemplate().getName()+" is released into the world!", mob, 20); + Server.getInstance().broadCastAlert(spectralDrake.getName()+" is released from the soul of the "+mob.getTemplate().getName()+", seeking vengeance for its physical form!"); + + // Insert extra hide / scale + + logger.info("Generating extra hide & scale to insert on the corpse of "+mob.getName()+"."); + ItemTemplate itemTemplate = ItemTemplateFactory.getInstance().getTemplate(lootTemplate); + for(int i = 0; i < 2; i++){ + Item loot = ItemFactory.createItem(lootTemplate, 80+(15*random.nextFloat()), ""); + String creatureName = mob.getTemplate().getName().toLowerCase(); + if (!loot.getName().contains(creatureName)){ + loot.setName(creatureName.toLowerCase() + " " + itemTemplate.getName()); + } + loot.setData2(mTemplate); + int weightGrams = itemTemplate.getWeightGrams() * (lootTemplate == 371 ? 3 : 1); + loot.setWeight((int)((weightGrams*0.1f)+(weightGrams*0.1f*random.nextFloat())), true); + corpse.insertItem(loot); + } + for(int i = 0; i < 4; i++){ + Item loot = ItemFactory.createItem(lootTemplate, 80+(15*random.nextFloat()), ""); + String creatureName = mob.getTemplate().getName().toLowerCase(); + if (!loot.getName().contains(creatureName)){ + loot.setName(creatureName.toLowerCase() + " " + itemTemplate.getName()); + } + loot.setData2(mTemplate); + int weightGrams = itemTemplate.getWeightGrams() * (lootTemplate == 371 ? 3 : 1); + loot.setWeight((int)((weightGrams*0.05f)+(weightGrams*0.05f*random.nextFloat())), true); + spectralDrake.getInventory().insertItem(loot); + }*/ + } else { // Spawn the reaper + try { + byte ctype = (byte)Math.max(0, Server.rand.nextInt(17) - 5); + CreatureTemplate template = CreatureTemplateFactory.getInstance().getTemplate(Reaper.templateId); // Reaper ID: 2147483647 + Creature reaper = Creature.doNew(template.getTemplateId(), true, mob.getPosX(), mob.getPosY(), random.nextFloat()*360.0f, mob.getLayer(), + template.getName(), (byte)0, mob.getKingdomId(), ctype, false, (byte)150); + Server.getInstance().broadCastAction("The death of the "+mob.getTemplate().getName()+" attracts a powerful being from below, seeking to claim it's soul.", mob, 20); + Server.getInstance().broadCastAlert(reaper.getName()+" is released from the underworld, seeking the soul of a powerful creature!"); + } catch (Exception e) { + e.printStackTrace(); + } + } + sendLootHelp = true; + } + if(mob.getStatus().isChampion()){ + // Champion mob loot + handleChampionLoot(corpse); + /*corpse.insertItem(ItemUtil.createRandomLootTool()); + if(random.nextInt(100) < 75){ + corpse.insertItem(ItemFactory.createItem((random.nextBoolean() ? 694 : 698), 30+(30*random.nextFloat()), "")); + } + if(random.nextInt(100) < 5){ + int[] maskTemplates = {973, 974, 975, 976, 977, 978, 1099}; + corpse.insertItem(ItemFactory.createItem(maskTemplates[random.nextInt(maskTemplates.length)], 90+(9*random.nextFloat()), "")); + } + if(random.nextInt(100) < 1){ + Item bone = ItemFactory.createItem(867, 90+(10*random.nextFloat()), ""); + bone.setRarity((byte)1); + if(random.nextInt(100) < 1){ + bone.setRarity((byte)2); + } + corpse.insertItem(bone); + }*/ + } + if(sendLootHelp){ + logger.info("Beginning loot assistance message generation..."); + displayLootAssistance(mob); + /*ArrayList atkNames = new ArrayList(); + Map attackers = Bounty.getAttackers(mob); + if(attackers != null){ + for(Long wid : attackers.keySet()){ + Creature cret = Creatures.getInstance().getCreatureOrNull(wid); + if(cret != null && cret.isPlayer()){ + atkNames.add(Players.getInstance().getPlayer(wid).getName()); + } + } + if(atkNames.size() > 0){ + String atkStrBuilder = "Loot Assistance ("+mob.getName()+"): "; + while(atkNames.size() > 0){ + int index = Server.rand.nextInt(atkNames.size()); + atkStrBuilder += atkNames.get(index); + atkNames.remove(index); + if(atkNames.size() > 0){ + atkStrBuilder += ", "; + } + } + MiscChanges.sendServerTabMessage(atkStrBuilder, 0, 128, 255); + logger.info("Broadcast loot assistance message success [Attackers]."); + }else{ + logger.warning("Powerful creature "+mob.getName()+" died, but no players were credited to its death [Attackers]."); + } + }else{ + logger.warning("Attackers was null for creature "+mob.getName()+" [Attackers]."); + }*/ + /*if(Bounty.dealtDamage.containsKey(mob.getWurmId())){ + logger.info("Found the damageDealt entry, parsing..."); + ArrayList names = new ArrayList(); + ArrayList damages = new ArrayList(); + for(long creatureId : Bounty.dealtDamage.get(mob.getWurmId()).keySet()){ + if(Players.getInstance().getPlayerOrNull(creatureId) != null){ + names.add(Players.getInstance().getPlayerOrNull(creatureId).getName()); + damages.add(Bounty.dealtDamage.get(mob.getWurmId()).get(creatureId)); + }else{ + if(Creatures.getInstance().getCreatureOrNull(creatureId) != null){ + logger.info("Skipping creature "+Creatures.getInstance().getCreatureOrNull(creatureId).getName()+" in loot assistance."); + } + } + } + logger.info("Names have been added: "+names); + String strBuilder = "Loot Assistance ("+mob.getName()+"): "; + DecimalFormat formatter = new DecimalFormat("#,###,###"); + while(names.size() > 0){ + int index = Server.rand.nextInt(names.size()); + strBuilder += names.get(index); + strBuilder += " ["+formatter.format(Math.round(damages.get(index)))+"]"; + names.remove(index); + damages.remove(index); + if(names.size() > 0){ + strBuilder += ", "; + } + } + MiscChanges.sendServerTabMessage(strBuilder, 0, 128, 255); + logger.info("Broadcast loot assistance message success [Damage]."); + }else{ + logger.warning("Powerful creature "+mob.getName()+" died, but no players were credited to its death [Damage]."); + }*/ + } + if(numCrystals > 0){ + Server.getInstance().broadCastAction(mob.getName()+" had something of interest...", mob, 5); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java new file mode 100644 index 0000000..d3babe4 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/bounty/PlayerBounty.java @@ -0,0 +1,221 @@ +package mod.sin.wyvern.bounty; + +import java.io.IOException; +import java.util.Map; +import java.util.Random; +import java.util.logging.Logger; + +import com.wurmonline.server.FailedException; +import com.wurmonline.server.Servers; +import com.wurmonline.server.creatures.Creature; +import com.wurmonline.server.economy.Economy; +import com.wurmonline.server.items.Item; +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.Title; +import com.wurmonline.server.skills.NoSuchSkillException; +import com.wurmonline.server.skills.SkillList; +import mod.sin.armour.SpectralHide; +import mod.sin.creatures.Reaper; +import mod.sin.creatures.SpectralDrake; +import mod.sin.items.AffinityOrb; +import mod.sin.wyvern.Bounty; +import mod.sin.wyvern.arena.Arena; +import mod.sin.wyvern.util.ItemUtil; + +public class PlayerBounty { + public static final Logger logger = Logger.getLogger(PlayerBounty.class.getName()); + protected static final Random random = new Random(); + + public static double getTypeBountyMod(Creature mob, String mobType){ + if(!mob.isUnique()){ + if (mobType.endsWith("fierce ")){ + return 1.5; + }else if (mobType.endsWith("angry ")){ + return 1.4; + }else if (mobType.endsWith("raging ")){ + return 1.6; + }else if (mobType.endsWith("slow ")){ + return 0.95; + }else if (mobType.endsWith("alert ")){ + return 1.2; + }else if (mobType.endsWith("greenish ")){ + return 1.7; + }else if (mobType.endsWith("lurking ")){ + return 1.1; + }else if (mobType.endsWith("sly ")){ + return 0.8; + }else if (mobType.endsWith("hardened ")){ + return 1.3; + }else if (mobType.endsWith("scared ")){ + return 0.85; + }else if (mobType.endsWith("diseased ")){ + return 0.9; + }else if (mobType.endsWith("champion ")){ + return 2.0; + } + } + return 1.0; + } + + public static void rewardPowerfulLoot(Player player, Creature mob){ + try{ + // Affinity Orb: + Item affinityOrb = ItemFactory.createItem(AffinityOrb.templateId, 99f+(1f*random.nextFloat()), ""); + player.getInventory().insertItem(affinityOrb); + // Enchant Orb: + float power; + if(mob.getStatus().isChampion()){ + power = 100f+(random.nextFloat()*20f); + }else{ + power = 90f+(random.nextFloat()*30f); + } + Item enchantOrb = ItemUtil.createEnchantOrb(power); + player.getInventory().insertItem(enchantOrb); + player.getCommunicator().sendSafeServerMessage("Libila takes the "+mob.getNameWithoutPrefixes()+"'s soul, but leaves something else behind..."); + }catch (NoSuchTemplateException | FailedException e) { + e.printStackTrace(); + } + } + + public static void rewardSpectralLoot(Player player){ + try{ + double fightskill = player.getFightingSkill().getKnowledge(); + Item spectralHide = ItemFactory.createItem(SpectralHide.templateId, 70+(30*random.nextFloat()), ""); // Spectral Hide ID: 22764 + ItemTemplate itemTemplate = spectralHide.getTemplate(); + int weightGrams = itemTemplate.getWeightGrams(); + spectralHide.setWeight((int)((weightGrams*0.25f)+(weightGrams*0.25f*fightskill/100f*random.nextFloat())), true); + player.getInventory().insertItem(spectralHide); + String fightStrength = "strong"; + if(fightskill >= 60){ + fightStrength = "great"; + } + if(fightskill >= 70){ + fightStrength = "powerful"; + } + if(fightskill >= 80){ + fightStrength = "master"; + } + if(fightskill >= 90){ + fightStrength = "legendary"; + } + player.getCommunicator().sendSafeServerMessage("The spirit recognizes you as a "+fightStrength+" warrior, and rewards you accordingly."); + player.addTitle(Title.getTitle(701)); + }catch (NoSuchTemplateException | FailedException e) { + e.printStackTrace(); + } + } + + public static void checkPlayerReward(Player player, Creature mob){ + try{ + int mobTemplateId = mob.getTemplate().getTemplateId(); + if(Bounty.dealtDamage.containsKey(mob.getWurmId()) && Bounty.dealtDamage.get(mob.getWurmId()).containsKey(player.getWurmId())){ + // -- Damage Dealt Rewards -- // + if(mob.isUnique()){ + // Treasure boxes awarded to players who deal damage: + Item treasureBox = ItemUtil.createTreasureBox(); + if(treasureBox != null){ + player.getInventory().insertItem(treasureBox); + }else{ + logger.warning("Error: Treasure box was not created properly!"); + } + } + if(Arena.isTitan(mob)){ + player.addTitle(Title.getTitle(700)); + } + double fightskill = player.getFightingSkill().getKnowledge(); + if((mobTemplateId == Reaper.templateId || mobTemplateId == SpectralDrake.templateId) && fightskill >= 50){ + rewardPowerfulLoot(player, mob); // Reward affinity orb and enchant orb: + if(mob.getTemplate().getTemplateId() == SpectralDrake.templateId){ + rewardSpectralLoot(player); // Reward spectral hide for spectral drakes + } + return; // If the player receives powerful loot, break the method completely and skip bounty. + } + // -- End Damage Dealt Rewards -- // + } + String mobName = mob.getTemplate().getName().toLowerCase(); + String mobType = mob.getPrefixes(); + long iron; + double cretStr = Bounty.getCreatureStrength(mob); + + if(Bounty.reward.containsKey(mobName)){ + iron = Bounty.reward.get(mobName); // Prioritize hardcoded values in the Bounty.reward list first + }else{ + iron = java.lang.Math.round(cretStr); // Calculate bounty from creature strength if they do not exist in the reward list. + } + if(Servers.localServer.PVPSERVER){ + if(!mob.isUnique() && mob.getTemplate().getTemplateId() != SpectralDrake.templateId && mob.getTemplate().getTemplateId() != Reaper.templateId){ + iron *= 2.5d; + } + try { + player.getSkills().getSkill(SkillList.MEDITATING).skillCheck(10, 0, false, 1); // Meditation skill gain + float faithMod = 1-(player.getFaith()/200f); + player.modifyFaith((((float)cretStr)*faithMod)/200000f); // Faith skill gain + } catch (NoSuchSkillException e) { + e.printStackTrace(); + } + } + + // Multiply bounty based on type + iron *= getTypeBountyMod(mob, mobType); + /*if(!mob.isUnique()){ + if (mobType.endsWith("fierce ")){ + iron *= 1.5; + }else if (mobType.endsWith("angry ")){ + iron *= 1.4; + }else if (mobType.endsWith("raging ")){ + iron *= 1.6; + }else if (mobType.endsWith("slow ")){ + iron *= 0.95; + }else if (mobType.endsWith("alert ")){ + iron *= 1.2; + }else if (mobType.endsWith("greenish ")){ + iron *= 1.7; + }else if (mobType.endsWith("lurking ")){ + iron *= 1.1; + }else if (mobType.endsWith("sly ")){ + iron *= 0.8; + }else if (mobType.endsWith("hardened ")){ + iron *= 1.3; + }else if (mobType.endsWith("scared ")){ + iron *= 0.85; + }else if (mobType.endsWith("diseased ")){ + iron *= 0.9; + }else if (mobType.endsWith("champion ")){ + iron *= 2.0; + } + }*/ + + player.addMoney(iron); + Item inventory = player.getInventory(); + String coinMessage = Economy.getEconomy().getChangeFor(iron).getChangeString(); + String strBuilder = "You are awarded " + coinMessage; + if((mob.isAggHuman() || mob.isMonster()) && !mob.isUnique() && !Servers.localServer.PVPSERVER){ + Item creatureToken = ItemFactory.createItem(22765, 1+(99*random.nextFloat()), ""); // Creature Token ID: 22765 + inventory.insertItem(creatureToken); + strBuilder += " and a "+creatureToken.getTemplate().getName(); + } + strBuilder += " for slaying the "+mob.getName()+"."; + player.getCommunicator().sendSafeServerMessage(strBuilder); + }catch (NoSuchTemplateException | FailedException | IOException e) { + e.printStackTrace(); + } + } // checkPlayerReward + + public static void checkPlayerBounty(Player player, Creature creature){ + try { + //Map attackers = ReflectionUtil.getPrivateField(creature, ReflectionUtil.getField(creature.getClass(), "attackers")); + Map attackers = Bounty.getAttackers(creature); + if(!Bounty.isCombatant(attackers, player.getWurmId()) || creature.isPlayer() || creature.isReborn()){ + return; + } + logger.info(player.getName()+" killed "+creature.getName()); + checkPlayerReward(player, creature); + } catch (IllegalArgumentException | ClassCastException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/invasion/Invasion.java b/src/main/java/mod/sin/wyvern/invasion/Invasion.java new file mode 100644 index 0000000..8894c1d --- /dev/null +++ b/src/main/java/mod/sin/wyvern/invasion/Invasion.java @@ -0,0 +1,48 @@ +package mod.sin.wyvern.invasion; + +import java.util.HashSet; +import java.util.Random; + +import com.wurmonline.server.Server; +import com.wurmonline.server.villages.Village; +import com.wurmonline.server.villages.Villages; + +public class Invasion { + public static boolean active = false; + public static long lastInvasionPoll = 0; + public static HashSet invasion = new HashSet<>(); + public static void pollInvasions(){ + long now = System.currentTimeMillis(); + if(now - lastInvasionPoll > 360000){ // 1 hour + Random rand = new Random(); + Village v = null; + int startx = 0; + int starty = 0; + while(v == null){ + startx = rand.nextInt(4000); + starty = rand.nextInt(4000); + v = Villages.getVillage(startx, starty, true); + if(v != null){ continue; } + for (int x = -50; x < 50; x += 5) { + for (int y = -50; y < 50 && (v = Villages.getVillage(startx + x, starty + y, true)) == null; y += 5) { + } + } + } + try { + int minion1Id = 555; + int minion2Id = 666; + int bossId = 777; + String villageName = v.getName(); + InvasionEvent event; + event = new InvasionEvent(startx, starty, villageName, bossId, minion1Id, minion2Id, rand.nextFloat()*100f); + invasion.add(event); + Server.getInstance().broadCastNormal("Whispers of a "+event.getPowerString()+" Necromancer circulate the area around "+villageName+"..."); + //HistoryManager.addHistory("A "+event.getPowerString()+" Necromancer", "invades the area surrounding "+villageName+"!"); + active = true; + lastInvasionPoll = now; + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/main/java/mod/sin/wyvern/invasion/InvasionEvent.java b/src/main/java/mod/sin/wyvern/invasion/InvasionEvent.java new file mode 100644 index 0000000..a2235c6 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/invasion/InvasionEvent.java @@ -0,0 +1,41 @@ +package mod.sin.wyvern.invasion; + +import java.util.HashSet; +import java.util.Random; + +import com.wurmonline.server.creatures.Creature; + +public class InvasionEvent{ + protected Random rand = new Random(); + protected String villageName; + protected float power; + protected Creature invasionBoss; + protected HashSet minions = new HashSet<>(); + + public InvasionEvent(int x, int y, String villageName, int bossId, int templateId1, int templateId2, float power) throws Exception{ + this.villageName = villageName; + this.power = power; + this.invasionBoss = Creature.doNew(bossId, x, y, rand.nextFloat()*360f, 0, "Necromancer", (rand.nextBoolean() ? (byte)0 : (byte)1)); + float halfPower = power / 2f; + int minionCount = (int) ((halfPower+(rand.nextFloat()*halfPower))/5f); + for(int i = 0; i < minionCount; i++){ + minions.add(Creature.doNew((rand.nextBoolean() ? templateId1 : templateId2), x, y, rand.nextFloat()*360f, 0, "Minion", (rand.nextBoolean() ? (byte)0 : (byte)1))); + } + } + + public String getPowerString(){ + if(power > 95){ + return "Legendary"; + }else if(power > 80){ + return "Powerful"; + }else if(power > 60){ + return "Strong"; + }else if(power > 40){ + return "Mediocre"; + }else if(power > 20){ + return "Weak"; + }else{ + return "Pathetic"; + } + } +} diff --git a/src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java b/src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java new file mode 100644 index 0000000..ab7eaa7 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/mastercraft/BytecodeTools.java @@ -0,0 +1,494 @@ +package mod.sin.wyvern.mastercraft; + +import javassist.bytecode.*; + +import java.io.FileNotFoundException; +import java.io.PrintWriter; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.IntStream; + + +public class BytecodeTools extends Bytecode { + + //private static final int EMPTY_INT = Integer.MAX_VALUE; + + BytecodeTools(ConstPool constPool){ + super(constPool); + } + + /** + * Look for a class in the constant pool. + * Throws NoMatchingConstPoolIndexException if the references isn't found. + * + * @param className String Object type. Full class name using periods. + * @return int primitive, index in constant pool table. + */ + int findClassIndex(String className){ + int classReferenceIndex = getClassReferenceIndex(className); + if (classReferenceIndex == -1) + throw new RuntimeException("No matching class found."); + this.add((classReferenceIndex >>> 8) & 0xFF, classReferenceIndex & 0xFF); + return classReferenceIndex; + } + + int addClassIndex(String className){ + int classReferenceIndex = getClassReferenceIndex(className); + if (classReferenceIndex == -1) + classReferenceIndex = this.getConstPool().addClassInfo(className); + this.add((classReferenceIndex >>> 8) & 0xFF, classReferenceIndex & 0xFF); + return classReferenceIndex; + } + + int findMethodIndex(int opcode, String name, String descriptor, String className){ + int methodReferenceIndex; + int classReferenceIndex = getClassReferenceIndex(className); + if (classReferenceIndex == -1) + throw new RuntimeException("No matching class found."); + + methodReferenceIndex = IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Methodref) + .filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null) + .filter(value -> Objects.equals(this.getConstPool().getMethodrefClass(value), classReferenceIndex)) + .findFirst() + .orElseThrow(() -> new RuntimeException("No matching method found.")); + this.addOpcode(opcode); + this.add((methodReferenceIndex >>> 8) & 0xFF, methodReferenceIndex & 0xFF); + + return methodReferenceIndex; + } + + int addMethodIndex(int opcode, String name, String methodDescriptor, String className){ + int classReferenceIndex = getClassReferenceIndex(className); + if (classReferenceIndex == -1) + classReferenceIndex = this.getConstPool().addClassInfo(className); + int indexReference = this.getConstPool().addMethodrefInfo(classReferenceIndex, name, methodDescriptor); + this.addOpcode(opcode); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + return indexReference; + } + + int findFieldIndex(int opcode, String name, String descriptor, String className){ + int fieldReferenceIndex; + int classReferenceIndex = getClassReferenceIndex(className); + if (classReferenceIndex == -1) + throw new RuntimeException("No matching class found."); + fieldReferenceIndex = IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Fieldref) + .filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null) + .filter(value -> this.getConstPool().getFieldrefClass(value) == classReferenceIndex) + .findFirst() + .orElseThrow(() -> new RuntimeException("No matching field found.")); + this.addOpcode(opcode); + this.add((fieldReferenceIndex >>> 8) & 0xFF, fieldReferenceIndex & 0xFF); + return fieldReferenceIndex; + } + + int addFieldIndex(int opcode, String name, String descriptor, String className){ + int classReferenceIndex = getClassReferenceIndex(className); + if (classReferenceIndex == -1) + classReferenceIndex = this.getConstPool().addClassInfo(className); + int fieldReferenceIndex = this.getConstPool().addFieldrefInfo(classReferenceIndex, name, descriptor); + this.addOpcode(opcode); + this.add((fieldReferenceIndex >>> 8) & 0xFF, fieldReferenceIndex & 0xFF); + return fieldReferenceIndex; + } + + void findStringIndex(String string){ + int indexReference = IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_String) + .filter(value -> Objects.equals(this.getConstPool().getStringInfo(value), string)) + .findFirst() + .orElseThrow(() -> new RuntimeException("No matching string found.")); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + + void addStringIndex(String string){ + int indexReference = this.getConstPool().addStringInfo(string); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + + void findLongIndex(long longValue){ + int indexReference = IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Long) + .filter(value -> this.getConstPool().getLongInfo(value) == longValue) + .findFirst() + .orElseThrow(() -> new RuntimeException("No matching long found.")); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + + void addLongIndex(long longValue){ + int indexReference = this.getConstPool().addLongInfo(longValue); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + + void findFloatIndex(float floatValue){ + int indexReference = IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Float) + .filter(value -> this.getConstPool().getFloatInfo(value) == floatValue) + .findFirst() + .orElseThrow(() -> new RuntimeException("No matching float found.")); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + + void addFloatIndex(float floatValue){ + int indexReference = this.getConstPool().addFloatInfo(floatValue); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + + /** + * a double value stored in the constant pool is always a LDC2_W. This is different then a local variable holding a double. + * + * @param doubleValue primitive double. + */ + void findDoubleIndex(double doubleValue){ + int indexReference = IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Double) + .filter(value -> this.getConstPool().getDoubleInfo(value) == doubleValue) + .findFirst() + .orElseThrow(() -> new RuntimeException("No matching double found.")); + this.addOpcode(Opcode.LDC2_W); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + + /** + * a double value stored in the constant pool is always a LDC2_W. This is different then a local variable holding a double. + * + * @param doubleValue primitive double. + */ + void addDoubleIndex(double doubleValue){ + int indexReference = this.getConstPool().addDoubleInfo(doubleValue); + this.addOpcode(Opcode.LDC2_W); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + + private boolean hasAClassDeclaringTag(int tag){ + return tag == ConstPool.CONST_Methodref || tag == ConstPool.CONST_Fieldref || tag == ConstPool.CONST_InterfaceMethodref; + } + + /** + * Often a class's name will appear twice in the constant pool. One of the occurrence is not used as a declaring class for anything. + * I have no idea why it's present but it can break looking up constant pool references if the unassociated one is picked. JA has a + * built in way of finding existent references but a underlying mechanic is that a hash map uses a string class name as a key + * in a hashMap. Two equal strings will overwrite each other in this case. This is part the the tools library to look for matches + * instead of relying on JA. + * + * 1. scan the constant pool and get the class references that match className. + * 2. scan again through the constant pool looking for class associations that use the references found in #1. One of the options + * will have no references and illuminate that one to return the one that should be used. + * + * @param className String type object, uses full class name and periods. + * @return int primitive, the address in constant pool for the class matching className. + */ + private int getClassReferenceIndex(String className){ + return IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Class) + .filter(value -> Objects.equals(Descriptor.toClassName(this.getConstPool().getClassInfoByDescriptor(value)), className)) + .filter( verifyIndex -> + IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> hasAClassDeclaringTag(this.getConstPool().getTag(value))) + .filter(value -> { + boolean result = false; + switch (this.getConstPool().getTag(value)) { + case ConstPool.CONST_Methodref: + result = this.getConstPool().getMethodrefClass(value) == verifyIndex; + break; + case ConstPool.CONST_Fieldref: + result = this.getConstPool().getFieldrefClass(value) == verifyIndex; + break; + case ConstPool.CONST_InterfaceMethodref: + result = this.getConstPool().getInterfaceMethodrefClass(value) == verifyIndex; + break; + } + return result;}) + .count() > 0 + ) + .findFirst() + .orElse(-1); + } + + void findInterfaceMethodIndex(String name, String descriptor){ + if(IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_InterfaceMethodref) + .filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null) + .count() != 1){ + throw new RuntimeException("No matching interface found."); + } + else { + int indexReference = IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_InterfaceMethodref) + .filter(value -> this.getConstPool().eqMember(name, descriptor, value) != null) + .findFirst() + .orElseThrow(() -> new RuntimeException("No matching interface found.")); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + } + + void addInterfaceMethodIndex(String name, String descriptor){ + int classIndexReference = IntStream.range(1, this.getConstPool().getSize()) + .filter(value -> this.getConstPool().getTag(value) == ConstPool.CONST_Class) + .filter(value -> Objects.equals(this.getConstPool().getClassInfoByDescriptor(value), Descriptor.toClassName(descriptor))) + .findFirst() + .orElseThrow(() -> new RuntimeException("No matching class found.")); + int indexReference = this.getConstPool().addInterfaceMethodrefInfo(classIndexReference, name, descriptor); + this.add((indexReference >>> 8) & 0xFF, indexReference & 0xFF); + } + + void codeBranching(int opcode, int branchCount){ + this.addOpcode(opcode); + this.add((branchCount >>> 8) & 0xFF, branchCount & 0xFF); + } + + void localVariableIndex(int opcode, int slot){ + this.addOpcode(opcode); + this.add(slot); + } + + void integerIndex(int opcode, int value){ + switch (opcode) { + case Opcode.BIPUSH : + this.addOpcode(Opcode.BIPUSH); + this.add((byte)value); + break; + case Opcode.SIPUSH : + this.addOpcode(Opcode.SIPUSH); + this.add((value >>> 8) & 0xFF, value & 0xFF); + } + } + + /** + * Encode the value for arg "integer" into the appropriate byteCode opCode + operand for the java-int. Add the + * encoded information to the byte code object "bytecode". + * + * @param integer int value. + */ + void addInteger(int integer) { + switch (integer) { + case -1: + this.add(Opcode.ICONST_M1); + break; + case 0: + this.add(Opcode.ICONST_0); + break; + case 1: + this.add(Opcode.ICONST_1); + break; + case 2: + this.add(Opcode.ICONST_2); + break; + case 3: + this.add(Opcode.ICONST_3); + break; + case 4: + this.add(Opcode.ICONST_4); + break; + case 5: + this.add(Opcode.ICONST_5); + break; + default: + if (integer >= Byte.MIN_VALUE && integer <= Byte.MAX_VALUE) { + this.add(Opcode.BIPUSH); + // integer bound to byte size. + this.add(integer); + } else if (integer >= Short.MIN_VALUE && integer <= Short.MAX_VALUE) { + this.add(Opcode.SIPUSH); + // Since byte code requires byte sized blocks, break up integer with bitmask and shift. + this.add((integer & 0xff00) >>> 8, integer & 0x00ff); + } else { + // Appends LDC or LDC_W depending on constant pool size. + this.addLdc(this.getConstPool().addIntegerInfo(integer)); + } + } + } + + /** + * Decode the byte code represented by a opCode + operand(s) at the position in arg "instructionIndex". Return + * decoded data as java-int. + * + * @param codeIterator JA CodeIterator object. + * @param instructionIndex int value, it is the codeIterator index of an opCode. + * @return int value. + */ + int getInteger(CodeIterator codeIterator, int instructionIndex) { + int opCode = codeIterator.byteAt(instructionIndex); + switch (opCode) { + case Opcode.ICONST_M1: + return -1; + case Opcode.ICONST_0: + return 0; + case Opcode.ICONST_1: + return 1; + case Opcode.ICONST_2: + return 2; + case Opcode.ICONST_3: + return 3; + case Opcode.ICONST_4: + return 4; + case Opcode.ICONST_5: + return 5; + case Opcode.BIPUSH: + return codeIterator.byteAt(instructionIndex + 1); + case Opcode.SIPUSH: + return codeIterator.s16bitAt(instructionIndex + 1); + case Opcode.LDC: + return this.getConstPool().getIntegerInfo(codeIterator.byteAt(instructionIndex + 1)); + case Opcode.LDC_W: + return this.getConstPool().getIntegerInfo(codeIterator.u16bitAt(instructionIndex + 1)); + default: + throw new RuntimeException(String.format("Failed to decode integer. Pos = %d, Bytecode = %d", instructionIndex, opCode)); + } + } + + static int findSlotInLocalVariableTable(CodeAttribute codeAttribute, String variableName){ + LocalVariableAttribute table = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); + int tableOrdinal; + tableOrdinal = IntStream.range(0,table.tableLength()).filter(value -> Objects.equals(table.variableName(value), variableName )).findFirst().orElse(-1); + if (tableOrdinal == -1){ + return -1; + } + return table.index(tableOrdinal); + } + + static int findLineNumberInLineNumberTable(CodeAttribute codeAttribute, String variableName){ + LocalVariableAttribute table = (LocalVariableAttribute) codeAttribute.getAttribute(LineNumberAttribute.tag); + int tableOrdinal; + tableOrdinal = IntStream.range(0,table.tableLength()).filter(value -> Objects.equals(table.variableName(value), variableName )).findFirst().orElse(-1); + if (tableOrdinal == -1){ + return -1; + } + return table.index(tableOrdinal); + } + + private static int[] getInstruction(int size, int index, CodeIterator codeIterator) { + int[] toReturn = null; + int bitLine; + int bitLine2; + switch (size) { + case 1: + bitLine = codeIterator.byteAt(index); + toReturn = new int[]{ + bitLine + }; + break; + case 2: + bitLine = codeIterator.s16bitAt(index); + toReturn = new int[]{ + (bitLine & 0xff00) >>> 8, + bitLine & 0x00ff + }; + break; + case 3: + bitLine = codeIterator.s32bitAt(index); + toReturn = new int[]{ + (bitLine & 0xff000000) >>> 24, + (bitLine & 0x00ff0000) >>> 16, + (bitLine & 0x0000ff00) >>> 8 + // not using the last byte + }; + break; + case 4: + bitLine = codeIterator.s32bitAt(index); + toReturn = new int[]{ + (bitLine & 0xff000000) >>> 24, + (bitLine & 0x00ff0000) >>> 16, + (bitLine & 0x0000ff00) >>> 8, + (bitLine & 0x000000ff) + }; + break; + case 5: + bitLine = codeIterator.s32bitAt(index); + bitLine2 = codeIterator.byteAt(index + 4); + toReturn = new int[]{ + (bitLine & 0xff000000) >>> 24, + (bitLine & 0x00ff0000) >>> 16, + (bitLine & 0x0000ff00) >>> 8, + (bitLine & 0x000000ff), + bitLine2 + }; + break; + case 6: + bitLine = codeIterator.s32bitAt(index); + bitLine2 = codeIterator.s16bitAt(index + 4); + toReturn = new int[]{ + (bitLine & 0xff000000) >>> 24, + (bitLine & 0x00ff0000) >>> 16, + (bitLine & 0x0000ff00) >>> 8, + (bitLine & 0x000000ff), + (bitLine2 & 0xff00) >>> 8, + (bitLine2 & 0x00ff) + }; + break; + case 7: + bitLine = codeIterator.s32bitAt(index); + bitLine2 = codeIterator.s32bitAt(index + 4); + toReturn = new int[]{ + (bitLine & 0xff000000) >>> 24, + (bitLine & 0x00ff0000) >>> 16, + (bitLine & 0x0000ff00) >>> 8, + (bitLine & 0x000000ff), + (bitLine2 & 0xff000000) >>> 24, + (bitLine2 & 0x00ff0000) >>> 16, + (bitLine2 & 0x0000ff00) >>> 8 + // not using the last byte + }; + break; + case 8: + bitLine = codeIterator.s32bitAt(index); + bitLine2 = codeIterator.s32bitAt(index + 4); + toReturn = new int[]{ + (bitLine & 0xff000000) >>> 24, + (bitLine & 0x00ff0000) >>> 16, + (bitLine & 0x0000ff00) >>> 8, + (bitLine & 0x000000ff), + (bitLine2 & 0xff000000) >>> 24, + (bitLine2 & 0x00ff0000) >>> 16, + (bitLine2 & 0x0000ff00) >>> 8, + (bitLine2 & 0x000000ff) + }; + break; + } + return toReturn; + } + + public static void byteCodePrint(String destinationPath, CodeIterator codeIterator) throws FileNotFoundException, BadBytecode { + Path printPath = Paths.get(destinationPath); + PrintWriter out = new PrintWriter(printPath.toFile()); + final String[] instructionOut = {""}; + codeIterator.begin(); + while (codeIterator.hasNext()) { + int index = codeIterator.next(); + int[] instruction = getInstruction(codeIterator.lookAhead() - index, index, codeIterator); + instructionOut[0] += Integer.toString(index); + instructionOut[0] += " "; + instructionOut[0] += Mnemonic.OPCODE[instruction[0]]; + if (instruction.length > 1) { + instructionOut[0] += " "; + IntStream.range(1, instruction.length) + .forEach(value -> { + instructionOut[0] += Integer.toString(instruction[value]); + instructionOut[0] += " "; + }); + } + out.println(instructionOut[0]); + instructionOut[0] = ""; + } + out.close(); + } + + static void printArrayToHex(Object[] obj, String name, Logger logger){ + int length = obj.length; + int[] c = new int[length]; + for (int i=0;i toExtendEntries = new ArrayList<>(); + private static ExtendTitleEnum singletonInstance; + + private ExtendTitleEnum(String className, int valuesSizerIndex, int populateVALUESIndex, ConstPool constPool) { + this.className = className; + this.valuesSizerIndex = valuesSizerIndex; + this.populateVALUESIndex = populateVALUESIndex; + this.constPool = constPool; + } + + /** + * Goes through the enum class's initiator to find bytecode index positions. + * + * @throws BadBytecode forwarded, Javassist stuff. + */ + static void builder(String className) throws BadBytecode, NotFoundException { + int valuesSizerIndex = -1; + //int indexANEWARRAY = -1; + int populateVALUESIndex = -1; + CtClass ctClassEnum = HookManager.getInstance().getClassPool().get(className); + ConstPool constPool = ctClassEnum.getClassFile().getConstPool(); + CodeIterator codeIterator = ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute().iterator(); + // Get the byte code instruction index for + // 1) size value for ANEWARRAY, + // 2) the VALUES array assignment or population. + BytecodeTools b = new BytecodeTools(constPool); + String valuesDescriptor = className.replace(".", "/"); + valuesDescriptor = "[L" + valuesDescriptor + ";"; + int constPoolValuesIndex = b.findFieldIndex(Opcode.PUTSTATIC, "$VALUES", + valuesDescriptor, className); + codeIterator.begin(); + int lastIndex = 0; + while (codeIterator.hasNext()){ + int instructionIndex = codeIterator.next(); + int opCode = codeIterator.byteAt(instructionIndex); + switch (opCode){ + case Opcode.ANEWARRAY : + valuesSizerIndex = lastIndex; + //indexANEWARRAY = instructionIndex; + break; + case Opcode.PUTSTATIC : + int cpAddress = codeIterator.u16bitAt(instructionIndex+1); + if (cpAddress == constPoolValuesIndex){ + populateVALUESIndex = instructionIndex; + } + break; + default: + break; + } + lastIndex = instructionIndex; + } + + synchronized (ExtendTitleEnum.class) { + singletonInstance = new ExtendTitleEnum(className, valuesSizerIndex, populateVALUESIndex, constPool); + } + } + + + static ExtendTitleEnum getSingletonInstance() { + return singletonInstance; + } + + /** + * A method to create data structures and add record a reference for that object. + * + * @param fieldName the name for the enum entry. + * @param titleId an ordinal for the Titles.Title enum. + * @param maleName in-game title name for male toons. + * @param femaleName in-game title name for femaleName toons. + * @param skillId A id number for the skill associated with the title, see {@link SkillList} + * @param titleTypes A string representation of entries in {@link com.wurmonline.server.players.Titles.TitleType}. In + * order to avoid premature class initialization for Javassist's bytecode stages we use a string + * instead of the WU object. The string must match one of the enum field names. + */ + synchronized void addExtendEntry(String fieldName, int titleId, String maleName, String femaleName, int skillId, String titleTypes) { + if (singletonInstance == null) { + throw new RuntimeException("ExtendTitleEnum instance is null, build it before addExtendEntry"); + } + EnumFields enumFields = new EnumFields(fieldName, titleId, maleName, femaleName, skillId, titleTypes); + toExtendEntries.add(enumFields); + } + + class EnumFields { + final String fieldName; + final int titleId; + final String maleName; + final String femaleName; + final int skillId; + final String titleTypes; + + /** + * @param fieldName the name for the enum entry. + * @param titleId an ordinal for the Titles.Title enum. + * @param maleName in-game title name for male toons. + * @param femaleName in-game title name for femaleName toons. + * @param skillId A id number for the skill associated with the title, see {@link SkillList} + * @param titleTypes A string representation of entries in {@link com.wurmonline.server.players.Titles.TitleType}. In + * order to avoid premature class initialization for Javassist's bytecode stages we use a string + * instead of the WU object. + **/ + EnumFields(String fieldName, int titleId, String maleName, String femaleName, + int skillId, String titleTypes){ + this.fieldName = fieldName; + this.titleId = titleId; + this.maleName = maleName; + this.femaleName = femaleName; + this.skillId = skillId; + this.titleTypes = titleTypes; + } + } + + /** + * Intended to be used in WurmServerMod-initiate section and it's for bytecode changes. This adds field objects to the enum class. + * + * @throws CannotCompileException forwarded, Javassist stuff. + */ + private synchronized void createFieldsInEnum() throws CannotCompileException, NotFoundException { + if (toExtendEntries.size() == 0){ + throw new RuntimeException("Can not extend an enum without values in toExtendEntries arrayList."); + } + + CtClass enumCtClass = HookManager.getInstance().getClassPool().get(this.className); + for (EnumFields enumData : toExtendEntries) { + CtField field = new CtField(enumCtClass, enumData.fieldName, enumCtClass); + field.setModifiers(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL | Modifier.ENUM); + enumCtClass.addField(field); + } + } + + /** + * This method uses JA bytecode to inject into the Enum's class initiator in order to expand the enum's $VALUES field. + * + * @throws BadBytecode forwarded, Javassist stuff. + */ + private void resizeEnumVALUES() throws BadBytecode, ClassNotFoundException, NotFoundException { + int expansion = toExtendEntries.size(); + CtClass ctClassEnum = HookManager.getInstance().getClassPool().get(this.className); + CodeIterator codeIterator = ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute().iterator(); + + BytecodeTools findBytecode = new BytecodeTools(this.constPool); + int currentSize = findBytecode.getInteger(codeIterator, this.valuesSizerIndex); + findBytecode.addInteger(currentSize); + findBytecode.addOpcode(Opcode.ANEWARRAY); + findBytecode.addClassIndex(this.className); + + BytecodeTools replaceBytecode = new BytecodeTools(this.constPool); + replaceBytecode.addInteger(currentSize + expansion); + replaceBytecode.addOpcode(Opcode.ANEWARRAY); + replaceBytecode.addClassIndex(this.className); + + CodeReplacer codeReplacer = new CodeReplacer(ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute()); + codeReplacer.replaceCode(findBytecode.get(), replaceBytecode.get()); + } + + /** + * This method builds bytecode to inject into the enum's initiator. The injected code initializes new enum entries and adds + * a reference of that new object to the $VALUES array. + * + * @throws BadBytecode forwarded, JA stuff. + * @throws ClassNotFoundException forwarded, JA stuff. + * @throws NotFoundException forwarded, JA stuff. + */ + synchronized void ExtendEnumEntries() throws BadBytecode, ClassNotFoundException, NotFoundException, CannotCompileException { + createFieldsInEnum(); + CtClass ctClassEnum = HookManager.getInstance().getClassPool().get(this.className); + CodeIterator initiatorCodeIterator = ctClassEnum.getClassInitializer().getMethodInfo().getCodeAttribute().iterator(); + + BytecodeTools enumInitiator = new BytecodeTools(ctClassEnum.getClassFile().getConstPool()); + BytecodeTools populateVALUES = new BytecodeTools(ctClassEnum.getClassFile().getConstPool()); + int extensionCounter = 0; + int valuesSize = enumInitiator.getInteger(initiatorCodeIterator, this.valuesSizerIndex); + // Construct the two bytecode objects to be inserted. The multiple enumData in toExtendEntries are combined into one + // long bytecode sequence and inserted at the proper point. + for (EnumFields enumData : toExtendEntries) { + enumInitiator.addOpcode(Opcode.NEW); + enumInitiator.findClassIndex(this.className); + enumInitiator.addOpcode(Opcode.DUP); + enumInitiator.addLdc(enumData.fieldName); + enumInitiator.addInteger(valuesSize + extensionCounter); + enumInitiator.addInteger(enumData.titleId); + enumInitiator.addLdc(enumData.maleName); + enumInitiator.addLdc(enumData.femaleName); + enumInitiator.addInteger(enumData.skillId); + enumInitiator.addFieldIndex(Opcode.GETSTATIC, enumData.titleTypes, + "Lcom/wurmonline/server/players/Titles$TitleType;", + "com/wurmonline/server/players/Titles$TitleType"); + enumInitiator.addMethodIndex(Opcode.INVOKESPECIAL, "", + "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;ILcom/wurmonline/server/players/Titles$TitleType;)V", + this.className); + enumInitiator.addFieldIndex(Opcode.PUTSTATIC, enumData.fieldName, "Lcom/wurmonline/server/players/Titles$Title;", + this.className); + + populateVALUES.addOpcode(Opcode.DUP); + populateVALUES.addInteger(valuesSize + extensionCounter); + extensionCounter++; + populateVALUES.findFieldIndex(Opcode.GETSTATIC, enumData.fieldName, "Lcom/wurmonline/server/players/Titles$Title;", + this.className); + populateVALUES.addOpcode(Opcode.AASTORE); + } + // Do bytecode changes from the bottom up so bytecode indexes don't change after every insert. + initiatorCodeIterator.insert(populateVALUESIndex, populateVALUES.get()); + resizeEnumVALUES(); + initiatorCodeIterator.insert(valuesSizerIndex, enumInitiator.get()); + } +} \ No newline at end of file diff --git a/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java new file mode 100644 index 0000000..e406ce9 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/mastercraft/Mastercraft.java @@ -0,0 +1,242 @@ +package mod.sin.wyvern.mastercraft; + +import java.util.Objects; +import java.util.logging.Logger; + +import org.gotti.wurmunlimited.modloader.ReflectionUtil; +import org.gotti.wurmunlimited.modloader.classhooks.HookManager; + +import com.wurmonline.server.Server; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.players.Titles; +import com.wurmonline.server.skills.Skill; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; +import javassist.NotFoundException; +import javassist.bytecode.BadBytecode; +import javassist.expr.ExprEditor; +import javassist.expr.MethodCall; +import mod.sin.lib.Util; + +public class Mastercraft { + private static Logger logger = Logger.getLogger(Mastercraft.class.getName()); + public static double getNewDifficulty(Skill skill, double diff, Item item){ + if(skill.affinity > 0){ + diff -= skill.affinity; + } + if(skill.getKnowledge() > 99.0d){ + diff -= 2d-((100d-skill.getKnowledge())*2d); + } + if(skill.getKnowledge() > 90.0d){ + diff -= 2d-((100d-skill.getKnowledge())*0.2d); + } + if(item != null){ + if(item.getRarity() > 0){ + diff -= item.getRarity(); + } + if(item.getCurrentQualityLevel() > 99.0f){ + diff -= 1d-((100d-item.getCurrentQualityLevel())*1d); + } + if(item.getCurrentQualityLevel() > 90.0f){ + diff -= 1d-((100d-item.getCurrentQualityLevel())*0.1d); + } + } + return diff; + } + public static float getCastPowerIncrease(Skill skill){ + double addedPower = 0; + if(skill.affinity > 0){ + addedPower += 2*skill.affinity; + } + if(skill.getKnowledge() > 0){ + float lowFloat1 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat()); + float lowFloat2 = Math.min(Server.rand.nextFloat(), Server.rand.nextFloat()); + addedPower += Math.min(skill.getKnowledge()*lowFloat1, skill.getKnowledge()*lowFloat2); + }else{ + logger.warning("Error: Some player just tried casting with no channeling skill!"); + } + return (float) addedPower; + } + public static float getFavorCostMultiplier(Skill skill){ + float mult = 1f; + if(skill.affinity > 0){ + mult -= skill.affinity*0.02f; //2% reduction per affinity + } + if(skill.getKnowledge() > 90d){ + mult -= 0.1d-((100d-skill.getKnowledge())*0.01d); + } + if(skill.getKnowledge() > 99d){ + mult -= 0.1d-((100-skill.getKnowledge())*0.1d); + } + return mult; + } + public static void addNewTitles(){ + try { + ExtendTitleEnum.builder("com.wurmonline.server.players.Titles$Title"); + // GM/Developer Titles + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Game_Master", 500, "Game Master", "Game Master", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Developer", 501, "Developer", "Developer", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Pet_Me", 502, "Pet Me", "Pet Me", -1, "NORMAL"); + + // Troll Titles + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Macro_King", 550, "Macro King", "Macro King", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Drama_Queen", 551, "Drama Queen", "Drama Queen", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Zergling", 552, "Zergling", "Zergling", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Special_Title", 553, "Special Guy", "Special Girl", -1, "NORMAL"); + + // Contest Titles + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Home_Decorator", 600, "Home Decorator", "Home Decorator", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Arena_Champion", 601, "Champion of the Arena", "Champion of the Arena", -1, "NORMAL"); + + // Special Event Titles + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Titan_Slayer", 700, "Titanslayer", "Titanslayer", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Spectral_Slayer", 701, "Spectral Warrior", "Spectral Warrior", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Holdstrong_Architect", 701, "Holdstrong Architect", "Holdstrong Architect", -1, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Stronghold_Architect", 701, "Stronghold Architect", "Stronghold Architect", -1, "NORMAL"); + + // Characteristic Titles + ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Normal", 1000, "Logical", "Logical", 100, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Minor", 1001, "Intelligent", "Intelligent", 100, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Master", 1002, "Brilliant", "Brilliant", 100, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindLogic_Legendary", 1003, "Mentalist", "Mentalist", 100, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindSpeed_Normal", 1004, "Keen", "Keen", 101, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindSpeed_Minor", 1005, "Thinker", "Thinker", 101, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindSpeed_Master", 1006, "Clever", "Clever", 101, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("MindSpeed_Legendary", 1007, "Mind Over Matter", "Mind Over Matter", 101, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStrength_Normal", 1008, "Strong", "Strong", 102, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStrength_Minor", 1009, "Fortified", "Fortified", 102, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStrength_Master", 1010, "Unyielding", "Unyielding", 102, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStrength_Legendary", 1011, "Force of Nature", "Force of Nature", 102, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStamina_Normal", 1012, "Enduring", "Enduring", 103, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStamina_Minor", 1013, "Resilient", "Resilient", 103, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStamina_Master", 1014, "Vigorous", "Vigorous", 103, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyStamina_Legendary", 1015, "Unstoppable", "Unstoppable", 103, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyControl_Normal", 1016, "Nimble", "Nimble", 104, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyControl_Minor", 1017, "Deft", "Deft", 104, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyControl_Master", 1018, "Skillful", "Skillful", 104, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("BodyControl_Legendary", 1019, "Manipulator", "Manipulator", 104, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulStrength_Normal", 1020, "Spirited", "Spirited", 105, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulStrength_Minor", 1021, "Diviner", "Diviner", 105, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulStrength_Master", 1022, "Anima", "Anima", 105, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulStrength_Legendary", 1023, "Prophet", "Prophet", 105, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulDepth_Normal", 1024, "Sensible", "Sensible", 106, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulDepth_Minor", 1025, "Medium", "Medium", 106, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulDepth_Master", 1026, "Spiritual", "Spiritual", 106, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("SoulDepth_Legendary", 1027, "Planewalker", "Planewalker", 106, "LEGENDARY"); + + // Skill Titles (Full) + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Staff_Normal", 1100, "Acolyte", "Acolyte", 10090, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Staff_Minor", 1101, "Disciple", "Disciple", 10090, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Staff_Master", 1102, "Monk", "Monk", 10090, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Staff_Legendary", 1103, "Sensei", "Sensei", 10090, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Scythe_Normal", 1104, "Mower", "Mower", 10047, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Scythe_Minor", 1105, "Harvester", "Harvester", 10047, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Scythe_Master", 1106, "Scythian", "Scythian", 10047, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Scythe_Legendary", 1107, "Reaper", "Reaper", 10047, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Defensive_Normal", 1108, "Resistant", "Resistant", 10054, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Defensive_Minor", 1109, "Guardian", "Guardian", 10054, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Defensive_Master", 1110, "Bulwark", "Bulwark", 10054, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Defensive_Legendary", 1111, "Unbreakable", "Unbreakable", 10054, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Aggressive_Normal", 1112, "Angry", "Angry", 10053, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Aggressive_Minor", 1113, "Violent", "Violent", 10053, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Aggressive_Master", 1114, "Battleborn", "Battleborn", 10053, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Aggressive_Legendary", 1115, "Warmonger", "Warmonger", 10053, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Normal_Normal", 1116, "Infantry", "Infantry", 10055, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Normal_Minor", 1117, "Marauder", "Marauder", 10055, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Normal_Master", 1118, "Gladiator", "Gladiator", 10055, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Normal_Legendary", 1119, "Templar", "Templar", 10055, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Weaponless_Normal", 1120, "Scrapper", "Scrapper", 10052, "NORMAL"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Weaponless_Minor", 1121, "Brawler", "Brawler", 10052, "MINOR"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Weaponless_Master", 1122, "Boxer", "Boxer", 10052, "MASTER"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Weaponless_Legendary", 1123, "Martial Artist", "Martial Artist", 10052, "LEGENDARY"); + + // Skill Titles (100) + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Archery_Legendary", 1500, "Legendary Marksman", "Legendary Marksman", 1030, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Body_Legendary", 1501, "Hercules", "Hercules", 1, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Axes_Legendary", 1502, "Viking", "Viking", 1003, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Baking_Legendary", 1503, "Patissier", "Patissier", 10039, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Archaeology_Legendary", 1504, "Curator", "Curator", 10069, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("CarvingKnife_Legendary", 1505, "Woodsculptor", "Woodsculptor", 10007, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Taming_Legendary", 1506, "King of the Jungle", "Queen of the Jungle", 10078, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Climbing_Legendary", 1507, "Moonwalker", "Moonwalker", 10073, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Tracking_Legendary", 1508, "Bloodhound", "Bloodhound", 10018, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Clubs_Legendary", 1509, "Bam Bam", "Bam Bam", 1025, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Catapults_Legendary", 1510, "Castle Crasher", "Castle Crasher", 10077, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Firemaking_Legendary", 1511, "Incendiary", "Incendiary", 1010, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Gardening_Legendary", 1512, "Earthbound", "Earthbound", 10045, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Hammers_Legendary", 1513, "Doomhammer", "Doomhammer", 1027, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Locksmithing_Legendary", 1514, "Vault Smith", "Vault Smith", 10034, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Religion_Legendary", 1515, "Chosen", "Chosen", 1026, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Yoyo_Legendary", 1516, "String Theorist", "String Theorist", 10050, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Nature_Legendary", 1517, "Naturalist", "Naturalist", 1019, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Mind_Legendary", 1518, "Enlightened", "Enlightened", 2, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Mauls_Legendary", 1519, "Breaker", "Breaker", 1004, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Shipbuilding_Legendary", 1520, "Naval Engineer", "Naval Engineer", 10082, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("NaturalSubstances_Legendary", 1521, "Biochemist", "Biochemist", 10042, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("WarMachines_Legendary", 1522, "Eradicator", "Eradicator", 1029, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Thievery_Legendary", 1523, "Shadow", "Shadow", 1028, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Swords_Legendary", 1524, "Samurai", "Samurai", 1000, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().addExtendEntry("Forestry_Legendary", 1525, "Silvanus", "Mother Nature", 10048, "LEGENDARY"); + ExtendTitleEnum.getSingletonInstance().ExtendEnumEntries(); + + } catch (BadBytecode | ClassNotFoundException | NotFoundException | CannotCompileException e) { + logger.warning(e.getMessage()); + } + } + public static void changeExistingTitles(){ + for (Titles.Title title : Titles.Title.values()) { + if (Objects.equals("Pumpkin King", title.getFemaleName())){ + try { + ReflectionUtil.setPrivateField(title, ReflectionUtil.getField(title.getClass(), "femaleName"), "Pumpkin Queen"); + } catch (IllegalArgumentException | IllegalAccessException | ClassCastException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + } + } + public static void preInit(){ + try { + ClassPool classPool = HookManager.getInstance().getClassPool(); + Class thisClass = Mastercraft.class; + + // - Reduce skill check difficulty with high skills or tools - // + CtClass ctSkill = classPool.get("com.wurmonline.server.skills.Skill"); + + /*ctSkill.getDeclaredMethod("checkAdvance").insertBefore("" + + "$1 = "+Mastercraft.class.getName()+".getNewDifficulty(this, $1, $2);");*/ + Util.insertBeforeDeclared(thisClass, ctSkill, "checkAdvance", "$1 = "+Mastercraft.class.getName()+".getNewDifficulty(this, $1, $2);"); + + // - Increase spellcasting power for skilled channelers - // + CtClass ctSpell = classPool.get("com.wurmonline.server.spells.Spell"); + CtMethod[] ctRuns = ctSpell.getDeclaredMethods("run"); + for(CtMethod method : ctRuns){ + method.instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("doEffect")) { + m.replace("$2 += "+Mastercraft.class.getName()+".getCastPowerIncrease(castSkill);" + + "$_ = $proceed($$);"); + logger.info("Instrumented doEffect in run()"); + return; + } + } + }); + method.instrument(new ExprEditor(){ + public void edit(MethodCall m) throws CannotCompileException { + if (m.getMethodName().equals("depleteFavor")) { + m.replace("$1 *= "+Mastercraft.class.getName()+".getFavorCostMultiplier(castSkill);" + + "$_ = $proceed($$);"); + logger.info("Instrumented depleteFavor in run()"); + return; + } + } + }); + } + + } catch (CannotCompileException | NotFoundException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/mod/sin/wyvern/util/ItemUtil.java b/src/main/java/mod/sin/wyvern/util/ItemUtil.java new file mode 100644 index 0000000..5379305 --- /dev/null +++ b/src/main/java/mod/sin/wyvern/util/ItemUtil.java @@ -0,0 +1,123 @@ +package mod.sin.wyvern.util; + +import java.util.Random; +import java.util.logging.Logger; + +import com.wurmonline.server.FailedException; +import com.wurmonline.server.Server; +import com.wurmonline.server.items.Item; +import com.wurmonline.server.items.ItemFactory; +import com.wurmonline.server.items.ItemList; +import com.wurmonline.server.items.ItemSpellEffects; +import com.wurmonline.server.items.NoSuchTemplateException; +import com.wurmonline.server.spells.SpellEffect; +import com.wurmonline.shared.constants.Enchants; + +import mod.sin.items.EnchantOrb; +import mod.sin.items.TreasureBox; + +public class ItemUtil { + public static final Logger logger = Logger.getLogger(ItemUtil.class.getName()); + protected static final Random random = new Random(); + public static int[] sorceryIds = { + ItemList.bloodAngels, + ItemList.smokeSol, + ItemList.slimeUttacha, + ItemList.tomeMagicRed, + ItemList.scrollBinding, + ItemList.cherryWhite, + ItemList.cherryRed, + ItemList.cherryGreen, + ItemList.giantWalnut, + ItemList.tomeEruption, + ItemList.wandOfTheSeas, + ItemList.libramNight, + ItemList.tomeMagicGreen, + ItemList.tomeMagicBlack, + ItemList.tomeMagicBlue, + ItemList.tomeMagicWhite + }; + public static Item createEnchantOrb(float power){ + byte[] enchantOrbEnchants = { + Enchants.BUFF_CIRCLE_CUNNING, + Enchants.BUFF_FLAMING_AURA, + Enchants.BUFF_SHARED_PAIN, + Enchants.BUFF_ROTTING_TOUCH, + Enchants.BUFF_LIFETRANSFER, Enchants.BUFF_LIFETRANSFER, // 2 rolls for LT + Enchants.BUFF_NIMBLENESS, + Enchants.BUFF_FROSTBRAND, + Enchants.BUFF_WEBARMOUR, + Enchants.BUFF_BLESSINGDARK, Enchants.BUFF_BLESSINGDARK, // 2 rolls for BotD + Enchants.BUFF_VENOM, + Enchants.BUFF_WIND_OF_AGES + }; + try { + Item enchantOrb = ItemFactory.createItem(EnchantOrb.templateId, 99+(1*Server.rand.nextFloat()), ""); + ItemSpellEffects effs = enchantOrb.getSpellEffects(); + if(effs == null){ + effs = new ItemSpellEffects(enchantOrb.getWurmId()); + } + byte enchant = enchantOrbEnchants[Server.rand.nextInt(enchantOrbEnchants.length)]; + SpellEffect eff = new SpellEffect(enchantOrb.getWurmId(), enchant, power, 20000000); + effs.addSpellEffect(eff); + enchantOrb.setDescription(eff.getName()+" "+Math.round(power)); + return enchantOrb; + } catch (FailedException | NoSuchTemplateException e) { + e.printStackTrace(); + } + return null; + } + public static Item createRandomLootTool(){ + try{ + int[] templates = {7, 8, 20, 24, 25, 27, 62, 93, 97}; + int template = templates[random.nextInt(templates.length)]; + float quality = 100; + for(int i = 0; i < 3; i++){ + quality = java.lang.Math.min(quality, java.lang.Math.max((float)10, 90*random.nextFloat())); + } + byte[] materials = {7, 8, 9, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, 30, 30, 31, 31, 34, 34, 56, 57, 67}; + byte material = materials[random.nextInt(materials.length)]; + byte rarity = 0; + if(random.nextInt(50) <= 2){ + rarity = 1; + }else if(random.nextInt(200) <= 2){ + rarity = 2; + } + byte[] enchants = {13, 13, 16, 16, 47}; + byte enchant = enchants[random.nextInt(enchants.length)]; + float power = 130; + for(int i = 0; i < 2; i++){ + power = java.lang.Math.min(power, 30+(100*random.nextFloat())); + } + Item tool = ItemFactory.createItem(template, quality, material, rarity, ""); + ItemSpellEffects effs = tool.getSpellEffects(); + if(effs == null){ + effs = new ItemSpellEffects(tool.getWurmId()); + } + SpellEffect eff = new SpellEffect(tool.getWurmId(), enchant, power, 20000000); + effs.addSpellEffect(eff); + tool.setDescription(eff.getName()+" "+String.valueOf((byte)power)); + return tool; + } catch (FailedException | NoSuchTemplateException e) { + e.printStackTrace(); + } + return null; + } + public static Item createTreasureBox(){ + try { + Item treasureBox = ItemFactory.createItem(TreasureBox.templateId, 10f+(90f*random.nextFloat()), ""); + if(Server.rand.nextInt(20) == 0){ + treasureBox.setRarity((byte) 3); + }else if(Server.rand.nextInt(5) == 0){ + treasureBox.setRarity((byte) 2); + }else if(Server.rand.nextBoolean()){ + treasureBox.setRarity((byte) 1); + } + return treasureBox; + } catch (FailedException | NoSuchTemplateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } +}