├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── data └── autobots │ ├── armorsets.xml │ ├── buffs.xml │ ├── config.xml │ ├── equipment.xml │ ├── symbols.xml │ └── teleports.xml ├── logo.png ├── patch.diff ├── sql ├── autobots.sql └── characters_autofarm.sql └── src └── main ├── kotlin └── dev │ └── l2j │ └── autobots │ ├── Autobot.kt │ ├── AutobotClient.kt │ ├── AutobotData.kt │ ├── AutobotScheduler.kt │ ├── AutobotsManager.kt │ ├── AutobotsNameManager.kt │ ├── CoScopes.kt │ ├── admincommands │ └── AdminAutobots.kt │ ├── autofarm │ ├── AutofarmCommandHandler.kt │ └── AutofarmManager.kt │ ├── behaviors │ ├── CombatBehavior.kt │ ├── SocialBehavior.kt │ ├── attributes │ │ ├── ConsumableUser.kt │ │ ├── Healer.kt │ │ ├── Kiter.kt │ │ ├── PetOwner.kt │ │ ├── RequiresMiscItem.kt │ │ ├── Reser.kt │ │ └── SecretManaRegen.kt │ ├── classes │ │ ├── AdventurerBehavior.kt │ │ ├── ArchmageBehavior.kt │ │ ├── CardinalBehavior.kt │ │ ├── DominatorBehavior.kt │ │ ├── DreadnoughtBehavior.kt │ │ ├── DuelistBehavior.kt │ │ ├── EvasTemplarBehavior.kt │ │ ├── FortuneSeekerBehavior.kt │ │ ├── GhostHunterBehavior.kt │ │ ├── GhostSentinelBehavior.kt │ │ ├── GrandKhavatariBehavior.kt │ │ ├── HellKnightBehavior.kt │ │ ├── MaestroBehavior.kt │ │ ├── MoonlightSentinelBehavior.kt │ │ ├── MysticMuseBehavior.kt │ │ ├── PhoenixKnightBehavior.kt │ │ ├── SagittariusBehavior.kt │ │ ├── ShillienTemplarBehavior.kt │ │ ├── SoultakerBehavior.kt │ │ ├── SpectralDancerBehavior.kt │ │ ├── StormScreamerBehavior.kt │ │ ├── SwordMuseBehavior.kt │ │ ├── TitanBehavior.kt │ │ ├── WindRiderBehavior.kt │ │ └── pre │ │ │ ├── DarkElvenWizardBehavior.kt │ │ │ ├── ElvenWizardBehavior.kt │ │ │ ├── FighterBehavior.kt │ │ │ ├── HumanWizardBehavior.kt │ │ │ ├── KnightBehavior.kt │ │ │ ├── MonkBehavior.kt │ │ │ ├── MysticBehavior.kt │ │ │ ├── OrcFighterBehavior.kt │ │ │ ├── OrcMysticBehavior.kt │ │ │ ├── OrcRaiderBehavior.kt │ │ │ ├── RogueBehavior.kt │ │ │ └── WarriorBehavior.kt │ ├── preferences │ │ ├── ActivityPreferences.kt │ │ ├── AttackPlayerType.kt │ │ ├── CombatPreferences.kt │ │ ├── SkillPreferences.kt │ │ ├── SkillUsageCondition.kt │ │ ├── SocialPreferences.kt │ │ ├── TargetingPreference.kt │ │ └── skills │ │ │ └── DefaultSkillPreferences.kt │ └── sequences │ │ ├── EquipGearRealisticallySequence.kt │ │ ├── ReturnToDeathLocationSequence.kt │ │ ├── Sequence.kt │ │ ├── TeleportToLocationSequence.kt │ │ └── TradingSequence.kt │ ├── config │ ├── AutobotBuffs.kt │ ├── AutobotEquipment.kt │ ├── AutobotLocation.kt │ ├── AutobotSettings.kt │ └── AutobotSymbol.kt │ ├── dao │ └── AutobotsDao.kt │ ├── extensions │ ├── AutobotExtensions.kt │ └── PlayerExtensions.kt │ ├── models │ ├── AutobotInfo.kt │ ├── AutobotLoc.kt │ ├── BotChat.kt │ ├── BotDebugAction.kt │ ├── ChatType.kt │ ├── CreateBotDetails.kt │ └── RespawnAction.kt │ ├── skills │ └── BotSkill.kt │ ├── ui │ ├── AdminActions.kt │ ├── AdminUiActions.kt │ ├── AutobotsUi.kt │ ├── AutofarmUi.kt │ ├── UiComponents.kt │ ├── html │ │ └── HtmlAlignment.kt │ ├── states │ │ ├── BotDetailsViewState.kt │ │ ├── CreateBotViewState.kt │ │ ├── IndexViewState.kt │ │ ├── SettingsViewState.kt │ │ ├── ViewState.kt │ │ └── ViewStates.kt │ └── tabs │ │ ├── BotDetailsTab.kt │ │ └── IndexTab.kt │ └── utils │ ├── AutobotHelpers.kt │ ├── AutobotItems.kt │ ├── AutobotSkills.kt │ ├── BotZoneService.kt │ ├── CancellationToken.kt │ ├── CrestService.kt │ ├── DDSConverter.kt │ ├── IconsTable.kt │ ├── ImageHelper.kt │ ├── Klock.kt │ └── packets │ ├── GMViewBuffs.kt │ └── ServerSideImage.kt └── resources ├── components ├── checkbox.htc ├── combobox_withsave.htc └── textbox_withsave.htc ├── fakenamewordlist.txt ├── views ├── autofarm_main.htv ├── autofarm_skills.htv ├── bot_details.htv ├── create_bot.htv ├── index.htv ├── partialviews │ ├── botdetails │ │ ├── botdetails_offline.ptv │ │ ├── botdetails_online.ptv │ │ ├── botdetails_tabs.ptv │ │ ├── chat │ │ │ ├── botdetails_chat.ptv │ │ │ └── botdetails_chat_tabs.ptv │ │ ├── combat │ │ │ └── botdetails_combat.ptv │ │ ├── info │ │ │ ├── botdetails_activity.ptv │ │ │ ├── botdetails_activity_none.ptv │ │ │ ├── botdetails_activity_schedule.ptv │ │ │ ├── botdetails_activity_uptime.ptv │ │ │ └── botdetails_info.ptv │ │ ├── skills │ │ │ ├── botdetails_skills.ptv │ │ │ ├── botdetails_skills_addcondition.ptv │ │ │ ├── botdetails_skills_condition.ptv │ │ │ ├── botdetails_skills_condition_edit.ptv │ │ │ └── botdetails_skills_condition_toggle.ptv │ │ └── social │ │ │ ├── botdetails_social.ptv │ │ │ ├── botdetails_social_create_craft.ptv │ │ │ ├── botdetails_social_create_craft_item.ptv │ │ │ ├── botdetails_social_create_store.ptv │ │ │ └── botdetails_social_create_store_item.ptv │ ├── index_checkbox.ptv │ ├── index_filter.ptv │ ├── index_tab_table_clan.ptv │ ├── index_tab_table_general.ptv │ ├── index_tabs.ptv │ ├── listbotsrow.ptv │ ├── listbotsrow_checked.ptv │ ├── listbotsrow_offline.ptv │ ├── listbotsrow_online.ptv │ ├── listbotsrow_unchecked.ptv │ ├── selected_options.ptv │ ├── selected_options_offline.ptv │ └── selected_options_online.ptv └── settings.htv └── xml └── icons.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 2 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 3 | 4 | # User-specific stuff 5 | .idea/**/workspace.xml 6 | .idea/**/tasks.xml 7 | .idea/**/usage.statistics.xml 8 | .idea/**/dictionaries 9 | .idea/**/shelf 10 | 11 | # Generated files 12 | .idea/**/contentModel.xml 13 | 14 | # Sensitive or high-churn files 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.local.xml 18 | .idea/**/sqlDataSources.xml 19 | .idea/**/dynamic.xml 20 | .idea/**/uiDesigner.xml 21 | .idea/**/dbnavigator.xml 22 | 23 | # Gradle 24 | .idea/**/gradle.xml 25 | .idea/**/libraries 26 | 27 | # Gradle and Maven with auto-import 28 | # When using Gradle or Maven with auto-import, you should exclude module files, 29 | # since they will be recreated, and may cause churn. Uncomment if using 30 | # auto-import. 31 | .idea/artifacts 32 | .idea/compiler.xml 33 | .idea/jarRepositories.xml 34 | .idea/modules.xml 35 | .idea/*.iml 36 | .idea/modules 37 | *.iml 38 | *.ipr 39 | 40 | # CMake 41 | cmake-build-*/ 42 | 43 | # Mongo Explorer plugin 44 | .idea/**/mongoSettings.xml 45 | 46 | # File-based project format 47 | *.iws 48 | 49 | # IntelliJ 50 | out/ 51 | 52 | # mpeltonen/sbt-idea plugin 53 | .idea_modules/ 54 | 55 | # JIRA plugin 56 | atlassian-ide-plugin.xml 57 | 58 | # Cursive Clojure plugin 59 | .idea/replstate.xml 60 | 61 | # Crashlytics plugin (for Android Studio and IntelliJ) 62 | com_crashlytics_export_strings.xml 63 | crashlytics.properties 64 | crashlytics-build.properties 65 | fabric.properties 66 | 67 | # Editor-based Rest Client 68 | .idea/httpRequests 69 | 70 | # Android studio 3.1+ serialized cache file 71 | .idea/caches/build_file_checksums.ser 72 | 73 | # Compiled class file 74 | *.class 75 | 76 | # Log file 77 | *.log 78 | 79 | # BlueJ files 80 | *.ctxt 81 | 82 | # Mobile Tools for Java (J2ME) 83 | .mtj.tmp/ 84 | 85 | # Package Files # 86 | *.jar 87 | *.war 88 | *.nar 89 | *.ear 90 | *.zip 91 | *.tar.gz 92 | *.rar 93 | 94 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 95 | hs_err_pid* 96 | 97 | data/geodata/ 98 | config/hexid.txt 99 | # Project exclude paths 100 | /.gradle/ 101 | 102 | build/ 103 | log/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # L2Autobots 2 | 3 | [![](https://vistr.dev/badge?repo=elfocrash.l2autobots&corners=square)](https://github.com/Elfocrash/l2autobots) 4 | 5 | ![](logo.png) 6 | 7 | ## Installation stuff 8 | 9 | This repo contains just the Autobots codebase and a patch that you need to run. It is also fully written in Kotlin. 10 | It is coded on aCis 382. 11 | 12 | ## Features 13 | 14 | - Full autobot control through an in game dashboard with amazing UX 15 | - Spawn/Despawn/Delete 16 | - Inspect a bot's inventory, status, skills and buffs 17 | - Customise the bot's combat and social preferences in game 18 | - Target radius 19 | - PvP aggression and preferences 20 | - Self sustain with potions that can be configured in game 21 | - Infinite buff replenishing 22 | - Infinite consumable replenishing 23 | - Ingame bot filtering 24 | - Persistent bots that are saved in the database and can be logged in where they logged out 25 | - Unique behaviour on each bot based on its class 26 | - Archers will kite 27 | - Spoilers will spoil and sweeper 28 | - Pet owners will have pets following or assisting them 29 | - Create an autobot in game 30 | - Name 31 | - Level 32 | - Class 33 | - Appearance 34 | - Create random Autobot 35 | - Bot chat control 36 | - You can see what the bot sees in the chat and you can do things like talk in general chat or shout chat and also use PMs 37 | - Bot clan control 38 | - Create a bot clan in game and change the members of the clan from the dashboard, including clan crests for remote locations 39 | - Full ingame bot control (movement, attack, skills, chat) 40 | - Automatic return to death area using gatekeepers 41 | 42 | ## Usage 43 | 44 | Just type `//a b` and everything is managable from the dashboard 45 | 46 | ## Showcase 47 | 48 | ![](https://i.imgur.com/wNV2KO6.gif) 49 | 50 | ![](https://i.imgur.com/aTKWULr.gif) 51 | 52 | ![](https://i.imgur.com/QZl20wL.gif) 53 | 54 | ## Videos (Click them) 55 | 56 | ### Demo 57 | [![](https://img.youtube.com/vi/K5STEUv1M7Y/maxresdefault.jpg)](https://www.youtube.com/watch?v=K5STEUv1M7Y) 58 | 59 | ### Skill configuration 60 | [![](https://img.youtube.com/vi/kp4zyFL7_Tw/maxresdefault.jpg)](https://www.youtube.com/watch?v=kp4zyFL7_Tw) 61 | 62 | ### onDeath return 63 | [![](https://img.youtube.com/vi/KU9Jy2EOSy8/maxresdefault.jpg)](https://www.youtube.com/watch?v=KU9Jy2EOSy8) 64 | 65 | ### Autofarm 66 | [![](https://img.youtube.com/vi/4ikdhc_Tq5Q/maxresdefault.jpg)](https://www.youtube.com/watch?v=4ikdhc_Tq5Q) 67 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | } 5 | dependencies { 6 | classpath 'net.sf.proguard:proguard-gradle:6.2.2' 7 | } 8 | } 9 | 10 | plugins { 11 | id 'com.github.johnrengelman.shadow' version '5.2.0' 12 | id 'java' 13 | id 'org.jetbrains.kotlin.jvm' version '1.3.70' 14 | } 15 | 16 | wrapper { gradleVersion = '6.0' } 17 | 18 | group 'dev.l2j.autobots' 19 | version '1.0-SNAPSHOT' 20 | 21 | sourceCompatibility = 13 22 | 23 | repositories { 24 | jcenter() 25 | mavenCentral() 26 | } 27 | 28 | dependencies { 29 | compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.10.+" 30 | compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.10.+" 31 | compile group: 'com.mchange', name: 'c3p0', version: '0.9.5' 32 | compile group: 'com.mchange', name: 'mchange-commons-java', version: '0.2.6.2' 33 | compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.15' 34 | compile group: 'org.mindrot', name: 'jbcrypt', version: '0.4' 35 | compile group: 'org.reflections', name: 'reflections', version: '0.9.12' 36 | compile group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-jdk8', version: '1.3.5' 37 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" 38 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5' 39 | } 40 | 41 | compileKotlin { 42 | kotlinOptions { 43 | jvmTarget = "1.8" 44 | } 45 | } 46 | compileTestKotlin { 47 | kotlinOptions { 48 | jvmTarget = "1.8" 49 | } 50 | } -------------------------------------------------------------------------------- /data/autobots/armorsets.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /data/autobots/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 350 4 | Welcome to L2 5 | 2000 6 | None 7 | Random 8 | true 9 | true 10 | true 11 | true 12 | 13 | -------------------------------------------------------------------------------- /data/autobots/symbols.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /data/autobots/teleports.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elfocrash/L2Autobots/f990c61df25e94c08ea6c36c5e230928a36ce0fc/logo.png -------------------------------------------------------------------------------- /sql/autobots.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS autobots ( 2 | `obj_Id` INT UNSIGNED NOT NULL DEFAULT 0, 3 | `char_name` VARCHAR(35) NOT NULL, 4 | `level` TINYINT UNSIGNED DEFAULT NULL, 5 | `maxHp` MEDIUMINT UNSIGNED DEFAULT NULL, 6 | `curHp` MEDIUMINT UNSIGNED DEFAULT NULL, 7 | `maxCp` MEDIUMINT UNSIGNED DEFAULT NULL, 8 | `curCp` MEDIUMINT UNSIGNED DEFAULT NULL, 9 | `maxMp` MEDIUMINT UNSIGNED DEFAULT NULL, 10 | `curMp` MEDIUMINT UNSIGNED DEFAULT NULL, 11 | `face` TINYINT UNSIGNED DEFAULT NULL, 12 | `hairStyle` TINYINT UNSIGNED DEFAULT NULL, 13 | `hairColor` TINYINT UNSIGNED DEFAULT NULL, 14 | `sex` TINYINT UNSIGNED DEFAULT NULL, 15 | `heading` MEDIUMINT DEFAULT NULL, 16 | `x` MEDIUMINT DEFAULT NULL, 17 | `y` MEDIUMINT DEFAULT NULL, 18 | `z` MEDIUMINT DEFAULT NULL, 19 | `exp` BIGINT UNSIGNED DEFAULT 0, 20 | `expBeforeDeath` BIGINT UNSIGNED DEFAULT 0, 21 | `sp` INT UNSIGNED NOT NULL DEFAULT 0, 22 | `karma` INT UNSIGNED DEFAULT NULL, 23 | `pvpkills` SMALLINT UNSIGNED DEFAULT NULL, 24 | `pkkills` SMALLINT UNSIGNED DEFAULT NULL, 25 | `clanid` INT UNSIGNED DEFAULT NULL, 26 | `race` TINYINT UNSIGNED DEFAULT NULL, 27 | `classid` TINYINT UNSIGNED DEFAULT NULL, 28 | `base_class` TINYINT UNSIGNED NOT NULL DEFAULT 0, 29 | `deletetime` BIGINT DEFAULT NULL, 30 | `cancraft` TINYINT UNSIGNED DEFAULT NULL, 31 | `title` VARCHAR(16) DEFAULT NULL, 32 | `rec_have` TINYINT UNSIGNED NOT NULL DEFAULT 0, 33 | `rec_left` TINYINT UNSIGNED NOT NULL DEFAULT 0, 34 | `accesslevel` MEDIUMINT DEFAULT 0, 35 | `online` TINYINT UNSIGNED DEFAULT NULL, 36 | `onlinetime` INT DEFAULT NULL, 37 | `lastAccess` BIGINT UNSIGNED DEFAULT NULL, 38 | `clan_privs` MEDIUMINT UNSIGNED DEFAULT 0, 39 | `wantspeace` TINYINT UNSIGNED DEFAULT 0, 40 | `isin7sdungeon` TINYINT UNSIGNED NOT NULL DEFAULT 0, 41 | `punish_level` TINYINT UNSIGNED NOT NULL DEFAULT 0, 42 | `punish_timer` BIGINT UNSIGNED NOT NULL DEFAULT 0, 43 | `power_grade` TINYINT UNSIGNED DEFAULT NULL, 44 | `nobless` TINYINT UNSIGNED NOT NULL DEFAULT 0, 45 | `hero` TINYINT UNSIGNED NOT NULL DEFAULT 0, 46 | `subpledge` SMALLINT NOT NULL DEFAULT 0, 47 | `lvl_joined_academy` TINYINT UNSIGNED NOT NULL DEFAULT 0, 48 | `apprentice` INT UNSIGNED NOT NULL DEFAULT 0, 49 | `sponsor` INT UNSIGNED NOT NULL DEFAULT 0, 50 | `varka_ketra_ally` TINYINT NOT NULL DEFAULT 0, 51 | `clan_join_expiry_time` BIGINT UNSIGNED NOT NULL DEFAULT 0, 52 | `clan_create_expiry_time` BIGINT UNSIGNED NOT NULL DEFAULT 0, 53 | `death_penalty_level` SMALLINT UNSIGNED NOT NULL DEFAULT 0, 54 | `creationDate` BIGINT UNSIGNED DEFAULT NULL, 55 | `modificationDate` BIGINT UNSIGNED DEFAULT NULL, 56 | `combat_prefs` LONGTEXT NULL DEFAULT NULL CHECK (json_valid(`combat_prefs`)), 57 | `activity_prefs` LONGTEXT NULL DEFAULT NULL CHECK (json_valid(`activity_prefs`)), 58 | `skill_prefs` LONGTEXT NULL DEFAULT NULL CHECK (json_valid(`skill_prefs`)), 59 | `social_prefs` LONGTEXT NULL DEFAULT NULL CHECK (json_valid(`social_prefs`)), 60 | PRIMARY KEY (obj_Id), 61 | KEY `clanid` (`clanid`) 62 | ); 63 | 64 | COLLATE='utf8_general_ci' 65 | ENGINE=InnoDB 66 | ; 67 | 68 | 69 | -------------------------------------------------------------------------------- /sql/characters_autofarm.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS character_autofarm ( 2 | `obj_Id` INT UNSIGNED NOT NULL DEFAULT 0, 3 | `classId` INT UNSIGNED NOT NULL DEFAULT 0, 4 | `combat_prefs` LONGTEXT NULL DEFAULT NULL CHECK (json_valid(`combat_prefs`)), 5 | `skill_prefs` LONGTEXT NULL DEFAULT NULL CHECK (json_valid(`skill_prefs`)), 6 | PRIMARY KEY (obj_Id, classId) 7 | ); -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/AutobotClient.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots 2 | 3 | import net.sf.l2j.commons.mmocore.ReceivablePacket 4 | import net.sf.l2j.gameserver.model.actor.Player 5 | import net.sf.l2j.gameserver.network.GameClient 6 | import net.sf.l2j.gameserver.network.serverpackets.L2GameServerPacket 7 | import java.nio.ByteBuffer 8 | 9 | internal class AutobotClient(val autobot: Autobot) : GameClient(null) { 10 | 11 | override fun toString(): String { 12 | return "Bot Client toString()" 13 | } 14 | 15 | override fun decrypt(buf: ByteBuffer?, size: Int): Boolean { 16 | return true 17 | } 18 | 19 | override fun encrypt(buf: ByteBuffer?, size: Int): Boolean { 20 | return true 21 | } 22 | 23 | override fun enableCrypt(): ByteArray { 24 | return byteArrayOf() 25 | } 26 | 27 | override fun setState(pState: GameClientState?) { 28 | 29 | } 30 | 31 | override fun sendPacket(gsp: L2GameServerPacket?) { 32 | 33 | } 34 | 35 | override fun markToDeleteChar(slot: Int): Byte { 36 | return 0 37 | } 38 | 39 | override fun markRestoredChar(slot: Int) { 40 | 41 | } 42 | 43 | override fun loadCharFromDisk(slot: Int): Player { 44 | return autobot 45 | } 46 | 47 | override fun close(gsp: L2GameServerPacket?) { 48 | 49 | } 50 | 51 | override fun closeNow() { 52 | 53 | } 54 | 55 | override fun cleanMe(fast: Boolean) { 56 | 57 | } 58 | 59 | override fun dropPacket(): Boolean { 60 | return false 61 | } 62 | 63 | override fun onBufferUnderflow() { 64 | 65 | } 66 | 67 | override fun onUnknownPacket() { 68 | 69 | } 70 | 71 | override fun execute(packet: ReceivablePacket?) { 72 | 73 | } 74 | 75 | override fun isDetached(): Boolean { 76 | return false 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/AutobotData.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots 2 | 3 | import com.fasterxml.jackson.databind.DeserializationFeature 4 | import com.fasterxml.jackson.databind.MapperFeature 5 | import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule 6 | import com.fasterxml.jackson.dataformat.xml.XmlMapper 7 | import com.fasterxml.jackson.module.kotlin.readValue 8 | import com.fasterxml.jackson.module.kotlin.registerKotlinModule 9 | import dev.l2j.autobots.config.* 10 | import net.sf.l2j.gameserver.enums.actors.ClassId 11 | import java.io.File 12 | 13 | internal object AutobotData { 14 | private val mapper = XmlMapper(JacksonXmlModule().apply { 15 | setDefaultUseWrapper(false)}).registerKotlinModule().configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true) 16 | .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 17 | 18 | var equipment = listOf() 19 | var buffs = mapOf>() 20 | var symbols = listOf() 21 | var teleportLocations = listOf() 22 | var settings: AutobotSettings 23 | 24 | init { 25 | settings = mapper.readValue(File("./data/autobots/config.xml")) 26 | 27 | equipment = mapper.readValue(File("./data/autobots/equipment.xml")) 28 | buffs = mapper.readValue>(File("./data/autobots/buffs.xml")).map { it.classId to it.buffsContent}.toMap() 29 | teleportLocations = mapper.readValue(File("./data/autobots/teleports.xml")) 30 | symbols = mapper.readValue(File("./data/autobots/symbols.xml")) 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/AutobotScheduler.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots 2 | 3 | import dev.l2j.autobots.behaviors.preferences.ActivityType 4 | import dev.l2j.autobots.dao.AutobotsDao 5 | import dev.l2j.autobots.models.ScheduledSpawnInfo 6 | import dev.l2j.autobots.utils.Klock 7 | import kotlinx.coroutines.CoroutineScope 8 | import kotlinx.coroutines.Dispatchers 9 | import kotlinx.coroutines.launch 10 | import java.time.Clock 11 | import java.time.LocalDateTime 12 | import java.time.format.DateTimeFormatter 13 | import java.util.concurrent.ConcurrentSkipListMap 14 | 15 | internal object AutobotScheduler { 16 | private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default) 17 | 18 | private val scheduledBots = AutobotsDao.loadScheduledSpawns().map { it.botName to it }.toMap(ConcurrentSkipListMap(String.CASE_INSENSITIVE_ORDER)) 19 | val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm") 20 | 21 | init { 22 | Klock.start("scheduledBots", 1000, 30000, CoScopes.generalScope, action = { 23 | val dateTimeNow = LocalDateTime.now(Clock.systemUTC()) 24 | scheduledBots.values.forEach { 25 | handleScheduledBotSpawn(dateTimeNow, it) 26 | } 27 | }) 28 | } 29 | 30 | private fun handleScheduledBotSpawn(dateTimeNow: LocalDateTime, it: ScheduledSpawnInfo) { 31 | val loginDateTime = LocalDateTime.parse("${dateTimeNow.year}-${if (dateTimeNow.monthValue < 10) "0${dateTimeNow.monthValue}" else dateTimeNow.monthValue}-${if (dateTimeNow.dayOfMonth < 10) "0${dateTimeNow.dayOfMonth}" else dateTimeNow.dayOfMonth} ${it.loginTime}", formatter) 32 | val logoutDateTime = LocalDateTime.parse("${dateTimeNow.year}-${if (dateTimeNow.monthValue < 10) "0${dateTimeNow.monthValue}" else dateTimeNow.monthValue}-${if (dateTimeNow.dayOfMonth < 10) "0${dateTimeNow.dayOfMonth}" else dateTimeNow.dayOfMonth} ${it.logoutTime}", formatter) 33 | 34 | if (dateTimeNow >= loginDateTime && dateTimeNow < logoutDateTime && !AutobotsManager.activeBots.containsKey(it.botName)) { 35 | scope.launch { 36 | val autobot = AutobotsDao.loadByName(it.botName) ?: return@launch 37 | AutobotsManager.spawnAutobot(autobot) 38 | } 39 | } 40 | 41 | if (dateTimeNow >= logoutDateTime && AutobotsManager.activeBots.containsKey(it.botName)) { 42 | scope.launch { AutobotsManager.activeBots[it.botName]!!.despawn() } 43 | } 44 | } 45 | 46 | internal fun addBot(autobot: Autobot){ 47 | if(autobot.combatBehavior.activityPreferences.activityType == ActivityType.Schedule) { 48 | val spawnInfo = ScheduledSpawnInfo(autobot.name, autobot.combatBehavior.activityPreferences.loginTime, autobot.combatBehavior.activityPreferences.logoutTime) 49 | scheduledBots[autobot.name] = ScheduledSpawnInfo(autobot.name, autobot.combatBehavior.activityPreferences.loginTime, autobot.combatBehavior.activityPreferences.logoutTime) 50 | val dateTimeNow = LocalDateTime.now(Clock.systemUTC()) 51 | handleScheduledBotSpawn(dateTimeNow, spawnInfo) 52 | } 53 | } 54 | 55 | internal fun removeBot(autobot: Autobot){ 56 | scheduledBots.remove(autobot.name) 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/AutobotsNameManager.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots 2 | 3 | import net.sf.l2j.commons.lang.StringUtil 4 | import net.sf.l2j.commons.random.Rnd 5 | import net.sf.l2j.gameserver.data.sql.PlayerInfoTable 6 | import net.sf.l2j.gameserver.data.xml.NpcData 7 | import java.io.BufferedReader 8 | import java.io.LineNumberReader 9 | import java.io.StringReader 10 | import java.util.logging.Level 11 | import java.util.logging.Logger 12 | 13 | object AutobotsNameService { 14 | 15 | private val logger = Logger.getLogger(AutobotsNameService::class.java.name) 16 | private lateinit var fakePlayerNames: List 17 | 18 | init { 19 | loadWordlist() 20 | } 21 | 22 | fun getRandomAvailableName(): String { 23 | var name = getRandomNameFromWordlist() 24 | 25 | while (!nameIsValid(name)) { 26 | name = getRandomNameFromWordlist() 27 | } 28 | 29 | return name 30 | } 31 | 32 | private fun getRandomNameFromWordlist(): String { 33 | return fakePlayerNames[Rnd.get(0, fakePlayerNames.size - 1)] 34 | } 35 | 36 | private fun loadWordlist() { 37 | try { 38 | LineNumberReader(BufferedReader(StringReader(javaClass.getResource("/fakenamewordlist.txt").readText()))).use { lnr -> 39 | val playersList = ArrayList() 40 | lnr.readLines().forEach { line -> 41 | run { 42 | if (line.trim { it <= ' ' }.isNotEmpty() && !line.startsWith("#")) { 43 | playersList.add(line) 44 | } 45 | } 46 | } 47 | fakePlayerNames = playersList 48 | logger.log(Level.INFO, "Loaded ${fakePlayerNames.size} fake player names.") 49 | } 50 | } catch (e: Exception) { 51 | e.printStackTrace() 52 | } 53 | } 54 | 55 | private fun nameAlreadyExists(name: String): Boolean { 56 | return PlayerInfoTable.getInstance().getPlayerObjectId(name) > 0 57 | } 58 | 59 | fun nameIsValid(name: String) : Boolean{ 60 | if (!StringUtil.isValidString(name, "^[A-Za-z0-9]{3,16}$")) { 61 | return false 62 | } 63 | 64 | if (NpcData.getInstance().getTemplateByName(name) != null) { 65 | return false 66 | } 67 | 68 | if(nameAlreadyExists(name)) { 69 | return false 70 | } 71 | 72 | return true 73 | 74 | } 75 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/CoScopes.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots 2 | 3 | import kotlinx.coroutines.CoroutineScope 4 | import kotlinx.coroutines.Dispatchers 5 | 6 | //Needs to be reworked 7 | internal object CoScopes { 8 | internal val generalScope: CoroutineScope = CoroutineScope(Dispatchers.Default) 9 | 10 | internal val sequenceScope: CoroutineScope = CoroutineScope(Dispatchers.Default) 11 | internal val massSpawnerScope: CoroutineScope = CoroutineScope(Dispatchers.Default) 12 | internal val massDespawnerScope: CoroutineScope = CoroutineScope(Dispatchers.Default) 13 | 14 | internal val onUpdateScope: CoroutineScope = CoroutineScope(Dispatchers.IO) 15 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/autofarm/AutofarmCommandHandler.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.autofarm 2 | 3 | import dev.l2j.autobots.ui.AutofarmUi 4 | import net.sf.l2j.gameserver.model.actor.Player 5 | 6 | internal object AutofarmCommandHandler { 7 | 8 | fun onBypass(player: Player, command: String) { 9 | if(!command.startsWith("autofarm")) { 10 | return 11 | } 12 | 13 | if(command == "autofarm") { 14 | AutofarmUi.index(player) 15 | return 16 | } 17 | 18 | val splitCommand = command.removePrefix("autofarm ").split(" ") 19 | 20 | when(splitCommand[0]){ 21 | "start" -> { 22 | AutofarmManager.startFarm(player) 23 | AutofarmUi.index(player) 24 | } 25 | "stop" -> { 26 | AutofarmManager.stopFarm(player) 27 | AutofarmUi.index(player) 28 | } 29 | "close" -> { 30 | AutofarmUi.closeWindow(player) 31 | } 32 | "todo" -> { 33 | player.sendMessage("Not implemented yet") 34 | } 35 | } 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/SocialBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors 2 | 3 | import dev.l2j.autobots.Autobot 4 | import dev.l2j.autobots.AutobotData 5 | import dev.l2j.autobots.behaviors.preferences.SocialPreferences 6 | import dev.l2j.autobots.behaviors.preferences.TownAction 7 | import dev.l2j.autobots.behaviors.sequences.ReturnToDeathLocationSequence 8 | import dev.l2j.autobots.behaviors.sequences.TeleportToLocationSequence 9 | import dev.l2j.autobots.behaviors.sequences.TradingSequence 10 | import dev.l2j.autobots.extensions.getActiveSequence 11 | import dev.l2j.autobots.extensions.getSocialBehavior 12 | import dev.l2j.autobots.models.RespawnAction 13 | import kotlinx.coroutines.delay 14 | import net.sf.l2j.commons.random.Rnd 15 | import net.sf.l2j.gameserver.model.actor.Player 16 | 17 | internal open class SocialBehavior(val bot: Player, var socialPreferences: SocialPreferences) { 18 | 19 | internal suspend fun onUpdate() { 20 | 21 | if(bot.getActiveSequence() != null) 22 | return 23 | 24 | if(bot is Autobot) { 25 | if(bot.hasActiveTradeRequest() && bot.activeTradeList == null) { 26 | delay(2000) 27 | bot.answerTradeRequest(true) 28 | TradingSequence(bot).also { it.execute() } 29 | return 30 | } 31 | } 32 | 33 | 34 | if(bot.getSocialBehavior().socialPreferences.townAction == TownAction.TeleToRandomLocation && Rnd.get(2500) == 0) { 35 | TeleportToLocationSequence(bot, AutobotData.teleportLocations.random().location).execute() 36 | } 37 | } 38 | 39 | internal suspend fun onRespawn() { 40 | if(bot is Autobot) { 41 | when(bot.respawnAction){ 42 | RespawnAction.None -> {} 43 | RespawnAction.ReturnToDeathLocation -> { 44 | ReturnToDeathLocationSequence(bot).execute() 45 | } 46 | RespawnAction.Logout -> { 47 | delay(Rnd.get(10000, 60000).toLong()) 48 | bot.despawn() 49 | } 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/attributes/ConsumableUser.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.attributes 2 | 3 | import dev.l2j.autobots.Autobot 4 | import dev.l2j.autobots.extensions.useItem 5 | import net.sf.l2j.gameserver.model.actor.Player 6 | 7 | internal interface ConsumableUser { 8 | val consumables: List 9 | 10 | fun handleConsumables(player: Player){ 11 | if(consumables.isEmpty()) return 12 | 13 | consumables.forEach { 14 | 15 | if(!it.condition(player)) return@forEach 16 | 17 | val items = player.inventory.getItemsByItemId(it.consumableId) 18 | 19 | if(items.isEmpty() && player is Autobot) { 20 | player.addItem("AubotoItem", it.consumableId, 200, player, false) 21 | } 22 | 23 | player.useItem(it.consumableId) 24 | } 25 | } 26 | } 27 | internal data class Consumable(val consumableId: Int, val condition: (Player) -> Boolean = { true }) -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/attributes/Healer.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.attributes 2 | 3 | import dev.l2j.autobots.utils.getHealthPercentage 4 | import dev.l2j.autobots.utils.isFullHealth 5 | import net.sf.l2j.gameserver.model.actor.Player 6 | 7 | internal interface Healer { 8 | fun tryTargetingLowestHpTargetInRadius(player: Player, radius: Int) { 9 | val finalTargets = mutableListOf() 10 | 11 | val targets = player.getKnownTypeInRadius(Player::class.java, radius).filter { (it.isInParty && player.isInParty && player.party == it.party) || (it.clan != null && player.clan != null && player.clanId == it.clanId) }.toMutableList() 12 | finalTargets.add(player) 13 | 14 | val partyMembers = targets.filter { it.isInParty && player.isInParty && it.party == player.party && it.getHealthPercentage() < 80 } 15 | 16 | if(partyMembers.isEmpty()) { 17 | val clanMembers = targets.filter { it.clan != null && player.clan != null && player.clanId == it.clanId && it.getHealthPercentage() < 80 } 18 | 19 | if(clanMembers.isNotEmpty()) { 20 | finalTargets.addAll(clanMembers) 21 | } 22 | } else { 23 | finalTargets.addAll(partyMembers) 24 | } 25 | 26 | val target = finalTargets.filter { !it!!.isDead }.minBy { it!!.getHealthPercentage() } ?: return 27 | 28 | //TODO fix this broken shit 29 | 30 | if(!target.isFullHealth() && target.getHealthPercentage() < 80) { 31 | player.target = target 32 | return 33 | } 34 | 35 | if(target.isDead) { 36 | player.target = null 37 | return 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/attributes/Kiter.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.attributes 2 | 3 | import dev.l2j.autobots.behaviors.preferences.ArcherCombatPreferences 4 | import dev.l2j.autobots.extensions.getCombatBehavior 5 | import dev.l2j.autobots.utils.distance 6 | import kotlinx.coroutines.delay 7 | import net.sf.l2j.gameserver.enums.IntentionType 8 | import net.sf.l2j.gameserver.geoengine.GeoEngine 9 | import net.sf.l2j.gameserver.model.actor.Creature 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | import net.sf.l2j.gameserver.model.location.Location 12 | 13 | internal interface Kiter { 14 | 15 | suspend fun kite(bot: Player){ 16 | if(bot.target == null) 17 | return 18 | 19 | if (bot.getCombatBehavior().combatPreferences !is ArcherCombatPreferences) return 20 | 21 | val prefs = (bot.getCombatBehavior().combatPreferences as ArcherCombatPreferences) 22 | if(!prefs.isKiting) { 23 | return 24 | } 25 | 26 | val kiteRange = prefs.kiteRadius 27 | val distance = distance(bot, bot.target as Creature) 28 | if (distance >= kiteRange) return 29 | 30 | val posX: Int = bot.x + if (bot.target.x < bot.x) kiteRange else -kiteRange 31 | val posY: Int = bot.y + if (bot.target.y < bot.y) kiteRange else -kiteRange 32 | val posZ: Int = bot.z + 50 33 | 34 | if (GeoEngine.getInstance().canMoveToTarget(bot.x, bot.y, bot.z, posX, posY, posZ)) 35 | { 36 | bot.ai.setIntention(IntentionType.MOVE_TO, Location(posX, posY, posZ)) 37 | delay(prefs.kitingDelay) 38 | return 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/attributes/PetOwner.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.attributes 2 | 3 | import dev.l2j.autobots.behaviors.preferences.PetOwnerPreferences 4 | import dev.l2j.autobots.extensions.getCombatBehavior 5 | import dev.l2j.autobots.extensions.useMagicSkill 6 | import dev.l2j.autobots.skills.BotSkill 7 | import net.sf.l2j.gameserver.enums.IntentionType 8 | import net.sf.l2j.gameserver.geoengine.GeoEngine 9 | import net.sf.l2j.gameserver.model.actor.Creature 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | import net.sf.l2j.gameserver.model.actor.instance.Servitor 12 | import net.sf.l2j.gameserver.model.item.instance.ItemInstance 13 | import net.sf.l2j.gameserver.network.serverpackets.ActionFailed 14 | 15 | internal interface PetOwner { 16 | 17 | val summonInfo: Pair 18 | 19 | val petBuffs: Array 20 | 21 | fun summonPet(bot: Player){ 22 | if(bot.hasServitor()) { 23 | return 24 | } 25 | 26 | val skill = bot.getSkill(summonInfo.first.skillId) ?: return 27 | 28 | if(summonInfo.second != null) { 29 | if (bot.inventory.getItemByItemId(summonInfo.second!!.miscItemId(bot)) != null) { 30 | if (bot.inventory.getItemByItemId(summonInfo.second!!.miscItemId(bot)).count <= summonInfo.second!!.minimumAmountBeforeGive) { 31 | bot.inventory.addItem("", summonInfo.second!!.miscItemId(bot), summonInfo.second!!.countToGive, bot, null) 32 | } 33 | } else { 34 | bot.inventory.addItem("", summonInfo.second!!.miscItemId(bot), summonInfo.second!!.countToGive, bot, null) 35 | val consumable: ItemInstance = bot.inventory.getItemByItemId(summonInfo.second!!.miscItemId(bot)) 36 | if (consumable.isEquipable) bot.inventory.equipItem(consumable) 37 | } 38 | } 39 | 40 | if(summonInfo.first.condition(bot, skill, bot.target as Creature?)) { 41 | bot.useMagicSkill(skill) 42 | } 43 | } 44 | 45 | fun petAssist(bot: Player) { 46 | if (bot.getCombatBehavior().combatPreferences is PetOwnerPreferences) { 47 | if (bot.hasServitor()) { 48 | val prefs = bot.getCombatBehavior().combatPreferences as PetOwnerPreferences 49 | if (prefs.petAssists) { 50 | if(!bot.hasServitor()) 51 | return 52 | 53 | if(bot.target == null) 54 | return 55 | 56 | val servitor = bot.summon as Servitor 57 | servitor.target = bot.target 58 | 59 | if(servitor.target == null) return 60 | if (servitor.target.isAutoAttackable(servitor)) { 61 | if (servitor.target is Player && ((servitor.target as Player).isCursedWeaponEquipped && servitor.level < 21 || bot.isCursedWeaponEquipped && bot.level < 21)) { 62 | bot.sendPacket(ActionFailed.STATIC_PACKET) 63 | return 64 | } 65 | if (servitor.target != null && GeoEngine.getInstance().canSeeTarget(servitor, servitor.target)) { 66 | 67 | if(prefs.petUsesShots) { 68 | if (bot.inventory.getItemByItemId(prefs.petShotId) != null) { 69 | if (bot.inventory.getItemByItemId(prefs.petShotId).count <= 5) { 70 | bot.inventory.addItem("", prefs.petShotId, 100, bot, null) 71 | } 72 | } else { 73 | bot.inventory.addItem("", prefs.petShotId, 100, bot, null) 74 | } 75 | 76 | if(!bot.autoSoulShot.contains(prefs.petShotId)) { 77 | bot.addAutoSoulShot(prefs.petShotId) 78 | bot.rechargeShots(true, true) 79 | } 80 | }else { 81 | if(bot.autoSoulShot.contains(prefs.petShotId)) { 82 | bot.removeAutoSoulShot(prefs.petShotId) 83 | } 84 | } 85 | servitor.ai.setIntention(IntentionType.ATTACK, servitor.target) 86 | } 87 | } else { 88 | if (servitor.target != null && !GeoEngine.getInstance().canSeeTarget(servitor, servitor.target)) servitor.ai.setIntention(IntentionType.FOLLOW, this) 89 | } 90 | } else { 91 | val servitor = bot.summon as Servitor 92 | if (!servitor.followStatus) { 93 | servitor.followOwner() 94 | } 95 | } 96 | } 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/attributes/RequiresMiscItem.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.attributes 2 | 3 | import dev.l2j.autobots.Autobot 4 | import net.sf.l2j.gameserver.model.actor.Player 5 | import net.sf.l2j.gameserver.model.item.instance.ItemInstance 6 | 7 | internal interface RequiresMiscItem { 8 | 9 | val miscItems: List 10 | 11 | fun handleMiscItems(fakePlayer: Player) { 12 | 13 | miscItems.forEach { 14 | if (fakePlayer.inventory.getItemByItemId(it.miscItemId(fakePlayer)) != null && fakePlayer is Autobot) { 15 | if (fakePlayer.inventory.getItemByItemId(it.miscItemId(fakePlayer)).count <= it.minimumAmountBeforeGive) { 16 | fakePlayer.inventory.addItem("", it.miscItemId(fakePlayer), it.countToGive, fakePlayer, null) 17 | } 18 | } else { 19 | if(fakePlayer is Autobot) { 20 | fakePlayer.inventory.addItem("", it.miscItemId(fakePlayer), it.countToGive, fakePlayer, null) 21 | } 22 | 23 | val consumable: ItemInstance? = fakePlayer.inventory.getItemByItemId(it.miscItemId(fakePlayer)) ?: return@forEach 24 | if (consumable!!.isEquipable) fakePlayer.inventory.equipItem(consumable) 25 | } 26 | } 27 | } 28 | } 29 | 30 | internal data class MiscItem(val miscItemId: (Player) -> Int, val countToGive: Int = 500, val minimumAmountBeforeGive: Int = 20) -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/attributes/Reser.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.attributes 2 | 3 | interface Reser { 4 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/attributes/SecretManaRegen.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.attributes 2 | 3 | import dev.l2j.autobots.Autobot 4 | import dev.l2j.autobots.utils.getManaPercentage 5 | import net.sf.l2j.gameserver.model.actor.Player 6 | 7 | interface SecretManaRegen { 8 | fun regenMana(autobot: Player){ 9 | if(autobot.getManaPercentage() < 20 && autobot is Autobot) { 10 | autobot.currentMp = autobot.maxMp.toDouble() 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/AdventurerBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.behaviors.preferences.skills.AdventurerSkillPreferences 7 | import dev.l2j.autobots.extensions.getCombatBehavior 8 | import dev.l2j.autobots.skills.BotSkill 9 | import dev.l2j.autobots.utils.* 10 | import net.sf.l2j.gameserver.enums.items.ShotType 11 | import net.sf.l2j.gameserver.model.actor.Player 12 | 13 | 14 | internal class AdventurerBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 15 | 16 | override var skillPreferences: SkillPreferences = AdventurerSkillPreferences() 17 | 18 | override fun getShotType(): ShotType { 19 | return ShotType.SOULSHOT 20 | } 21 | 22 | override val getOffensiveSkills: List = listOf( 23 | BotSkill(bluff) { _, _, target -> target is Player && (target.pvpFlag > 0 || target.karma > 0) }, 24 | BotSkill(trick) { player, _, target -> target is Player && (target.pvpFlag > 0 || target.karma > 0) && player.getCombatBehavior().skillPreferences.togglableSkills[trick]!! }, 25 | BotSkill(switch) { player, _, target -> target is Player && (target.pvpFlag > 0 || target.karma > 0) && player.getCombatBehavior().skillPreferences.togglableSkills[switch]!! }, 26 | BotSkill(backstab) { player, _, _ -> player.isBehindTarget }, 27 | BotSkill(lethalBlow), 28 | BotSkill(deadlyBlow), 29 | BotSkill(criticalBlow, isConditionalSkill = false, isTogglableSkill = false, useWhenEffectIsNotPresent = true)) 30 | 31 | override val getSelfSupportSkills: List = listOf( 32 | BotSkill(dash, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = true), 33 | BotSkill(ultimateEvasion, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 34 | BotSkill(mirage, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = true), 35 | BotSkill(viciousStance, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 36 | BotSkill(focusPower, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 37 | BotSkill(focusSkillMastery, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true) 38 | ) 39 | 40 | override val conditionalSkills: List = listOf(dash, ultimateEvasion, mirage) 41 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/ArchmageBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.behaviors.preferences.skills.ArchmageSkillPreferences 7 | import dev.l2j.autobots.extensions.getCombatBehavior 8 | import dev.l2j.autobots.skills.BotSkill 9 | import dev.l2j.autobots.utils.* 10 | import net.sf.l2j.gameserver.enums.items.ShotType 11 | import net.sf.l2j.gameserver.model.actor.Player 12 | import net.sf.l2j.gameserver.model.actor.instance.Monster 13 | 14 | 15 | internal class ArchmageBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 16 | 17 | override var skillPreferences: SkillPreferences = ArchmageSkillPreferences() 18 | 19 | override fun getShotType(): ShotType { 20 | return ShotType.BLESSED_SPIRITSHOT 21 | } 22 | 23 | override val getOffensiveSkills: List = listOf( 24 | BotSkill(surrenderToFire) {_, _, target -> skillPreferences.togglableSkills[surrenderToFire]!! && ((target is Monster) || (target is Player && (target.pvpFlag > 0 || target.karma > 0))) && !target.hasEffect(surrenderToFire) }, 25 | BotSkill(cancellation) {_, _, target -> skillPreferences.togglableSkills[cancellation]!! && target is Player && (target.pvpFlag > 0 || target.karma > 0) && target.allEffects.size > 5 }, 26 | BotSkill(fireVortex), 27 | BotSkill(slow) { player, skill, target -> target != null && !target.hasEffect(slow) && player.getCombatBehavior().validateConditionalSkill(skill)}, 28 | BotSkill(prominence) 29 | ) 30 | 31 | override val getSelfSupportSkills: List = 32 | listOf(BotSkill(arcanePower, { player, _, _ -> player.getCombatBehavior().skillPreferences.togglableSkills[arcanePower]!! && !player.hasEffect(arcanePower) && player.isInCombat }, true)) 33 | 34 | override val conditionalSkills: List = listOf(slow) 35 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/CardinalBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.Healer 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.extensions.getClosestEntityInRadius 8 | import dev.l2j.autobots.extensions.useMagicSkill 9 | import dev.l2j.autobots.skills.BotSkill 10 | import dev.l2j.autobots.utils.getHealthPercentage 11 | import net.sf.l2j.gameserver.enums.IntentionType 12 | import net.sf.l2j.gameserver.enums.items.ShotType 13 | import net.sf.l2j.gameserver.model.L2Skill 14 | import net.sf.l2j.gameserver.model.actor.Creature 15 | import net.sf.l2j.gameserver.model.actor.Player 16 | 17 | 18 | internal class CardinalBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), Healer { 19 | 20 | override var skillPreferences: SkillPreferences = SkillPreferences(true) 21 | 22 | override val conditionalSkills: List = emptyList() 23 | 24 | override fun getShotType(): ShotType { 25 | return ShotType.BLESSED_SPIRITSHOT 26 | } 27 | 28 | override suspend fun afterAttack() { 29 | super.afterAttack() 30 | 31 | if(player.target == player && player.getHealthPercentage() > 80) { 32 | player.target = null 33 | } 34 | 35 | if(player.target == null) { 36 | if(player.isInParty) { 37 | player.target = player.party.leader 38 | player.ai.setIntention(IntentionType.FOLLOW, player.target) 39 | return 40 | } 41 | 42 | if(player.clan != null) { 43 | val closestClanMember = player.getClosestEntityInRadius(2000) { it is Player && it.clan != null && it.clanId == player.clanId} 44 | player.target = closestClanMember 45 | player.ai.setIntention(IntentionType.FOLLOW, player.target) 46 | } 47 | } 48 | } 49 | 50 | override suspend fun beforeAttack() { 51 | super.beforeAttack() 52 | if(player.target == null) { 53 | 54 | } 55 | } 56 | 57 | override suspend fun attack() { 58 | heal() 59 | } 60 | 61 | override suspend fun targetAppropriateTarget() { 62 | tryTargetingLowestHpTargetInRadius(player, 2000) 63 | } 64 | 65 | private fun heal() { 66 | val skill = getNextAvailableHealingSkill() 67 | val target = player.target 68 | 69 | if(target != null && skill != null) { 70 | player.useMagicSkill(skill) 71 | } 72 | } 73 | 74 | override val getOffensiveSkills: List = emptyList() 75 | 76 | val healingSkills: List = listOf( 77 | BotSkill(1218) { player, _, target -> target != null && target is Player && (player.getHealthPercentage()) < 70 }, 78 | BotSkill(1217) { player, _, target -> target != null && target is Player && (player.getHealthPercentage()) < 80 }) 79 | 80 | fun getNextAvailableHealingSkill(): L2Skill? { 81 | 82 | if(healingSkills.isEmpty()) return null 83 | 84 | var skillToUse: L2Skill? = null 85 | for(botSkill in healingSkills) { 86 | val skill = player.getSkill(botSkill.skillId) 87 | if(!player.checkDoCastConditions(skill)) 88 | continue 89 | 90 | if(botSkill.condition(player, skill, player.target as Creature?) && skill.checkCondition(player, player.target, false)) { 91 | skillToUse = skill 92 | break 93 | } 94 | } 95 | 96 | if(skillToUse == null) return null 97 | 98 | return skillToUse 99 | } 100 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/DominatorBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.skills.BotSkill 7 | import net.sf.l2j.gameserver.enums.items.ShotType 8 | import net.sf.l2j.gameserver.model.actor.Player 9 | 10 | 11 | internal class DominatorBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 12 | 13 | override var skillPreferences: SkillPreferences = SkillPreferences(true) 14 | 15 | override fun getShotType(): ShotType { 16 | return ShotType.BLESSED_SPIRITSHOT 17 | } 18 | 19 | override val getOffensiveSkills: List = listOf(BotSkill(1245)) 20 | 21 | override val conditionalSkills: List = emptyList() 22 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/DreadnoughtBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.behaviors.preferences.skills.DreadnoughtSkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import dev.l2j.autobots.utils.* 9 | import net.sf.l2j.gameserver.enums.items.ShotType 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | 12 | 13 | internal class DreadnoughtBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 14 | 15 | override var skillPreferences: SkillPreferences = DreadnoughtSkillPreferences() 16 | 17 | override fun getShotType(): ShotType { 18 | return ShotType.SOULSHOT 19 | } 20 | 21 | override val getOffensiveSkills: List = listOf( 22 | BotSkill(361), 23 | BotSkill(347){player, _, target -> target != null && !target.isDead && distance(player, target) < 100 }, 24 | BotSkill(48){player, _, target -> target != null && !target.isDead && distance(player, target) < 100 }, 25 | BotSkill(452){player, _, target -> target != null && !target.isDead && distance(player, target) < 100 }, 26 | BotSkill(36){player, _, target -> target != null && !target.isDead && distance(player, target) < 100 }) 27 | 28 | override val getSelfSupportSkills: List = listOf( 29 | BotSkill(braveheart, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 30 | BotSkill(revival, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 31 | BotSkill(battleroar, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 32 | BotSkill(fellSwoop, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 33 | BotSkill(viciousStance, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 34 | BotSkill(warFrenzy, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 35 | BotSkill(thrillFight, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true) 36 | 37 | ) 38 | 39 | override val conditionalSkills: List = listOf(braveheart,revival,battleroar) 40 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/DuelistBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.DuelistCombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.behaviors.preferences.skills.DuelistSkillPreferences 7 | import dev.l2j.autobots.extensions.getCombatBehavior 8 | import dev.l2j.autobots.skills.BotSkill 9 | import dev.l2j.autobots.utils.* 10 | import net.sf.l2j.gameserver.enums.items.ShotType 11 | import net.sf.l2j.gameserver.model.actor.Creature 12 | import net.sf.l2j.gameserver.model.actor.Player 13 | import net.sf.l2j.gameserver.model.actor.instance.Monster 14 | 15 | 16 | internal class DuelistBehavior(player: Player, combatPreferences: DuelistCombatPreferences) : CombatBehavior(player, combatPreferences) { 17 | 18 | override var skillPreferences: SkillPreferences = DuelistSkillPreferences(false) 19 | 20 | override fun getShotType(): ShotType { 21 | return ShotType.SOULSHOT 22 | } 23 | 24 | override val getOffensiveSkills: List = listOf( 25 | BotSkill(sonicRage) {player, _, target -> shouldUseSkillOnTarget(target, player.getCombatBehavior().typedSkillPreferences()) && player.charges < 7 }, 26 | BotSkill(tripleSonicSlash) {player, _, target -> shouldUseSkillOnTarget(target, player.getCombatBehavior().typedSkillPreferences())}, 27 | BotSkill(doubleSonicSlash){player, _, target -> shouldUseSkillOnTarget(target, player.getCombatBehavior().typedSkillPreferences())}, 28 | BotSkill(sonicBlaster){player, _, target -> shouldUseSkillOnTarget(target, player.getCombatBehavior().typedSkillPreferences())}, 29 | BotSkill(tripleSlash){player, _, target -> shouldUseSkillOnTarget(target, player.getCombatBehavior().typedSkillPreferences())}) 30 | 31 | private fun shouldUseSkillOnTarget(target: Creature?, skillPreferences: DuelistSkillPreferences) = 32 | ((target is Monster && skillPreferences.useSkillsOnMobs) || target !is Monster) 33 | 34 | override val getSelfSupportSkills: List = listOf( 35 | BotSkill(sonicFocus){player, skill, _ -> player.getSkill(345) == null && player.charges < skill.maxCharges }, 36 | BotSkill(duelistSpirit, isConditionalSkill = false, isTogglableSkill = false, useWhenEffectIsNotPresent = true), 37 | BotSkill(braveheart, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 38 | BotSkill(battleroar, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 39 | BotSkill(sonicBarrier, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 40 | BotSkill(sonicMove, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = true) 41 | ) 42 | 43 | override val conditionalSkills: List = listOf( 44 | braveheart, 45 | battleroar, 46 | sonicBarrier, 47 | sonicMove 48 | ) 49 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/EvasTemplarBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.MiscItem 5 | import dev.l2j.autobots.behaviors.attributes.RequiresMiscItem 6 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 7 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 8 | import dev.l2j.autobots.behaviors.preferences.skills.EvasTemplarSkillPreferences 9 | import dev.l2j.autobots.extensions.getCombatBehavior 10 | import dev.l2j.autobots.skills.BotSkill 11 | import dev.l2j.autobots.utils.* 12 | import net.sf.l2j.gameserver.enums.items.ShotType 13 | import net.sf.l2j.gameserver.model.actor.Player 14 | 15 | 16 | internal class EvasTemplarBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), RequiresMiscItem { 17 | 18 | override var skillPreferences: SkillPreferences = EvasTemplarSkillPreferences() 19 | 20 | override fun getShotType(): ShotType { 21 | return ShotType.SOULSHOT 22 | } 23 | 24 | override val miscItems = listOf(MiscItem({1458}, 100, 50)) 25 | 26 | override val getOffensiveSkills: List = listOf( 27 | BotSkill(tribunal), 28 | BotSkill(shieldBash) { _, _, target -> target is Player && target.target == player }, 29 | BotSkill(arrest) { player, skill, target -> (target !is Player || ((target.pvpFlag > 0 || target.karma > 0) )) && !target!!.isRooted && player.getCombatBehavior().validateConditionalSkill(skill) }, 30 | BotSkill(songOfSilence) { player, skill, target -> (target !is Player || ((target.pvpFlag > 0 || target.karma > 0) )) && !target!!.isRooted && player.getCombatBehavior().validateConditionalSkill(skill) } 31 | ) 32 | 33 | override val getSelfSupportSkills: List = listOf( 34 | BotSkill(summonStormCubic) { player, _, _ -> player.getCombatBehavior().skillPreferences.togglableSkills[summonStormCubic]!! && !player.isInCombat && player.getCubic(summonStormCubicNpcId) == null }, 35 | //BotSkill(summonLifeCubic) { player, _, _ -> !player.isInCombat && player.getCubic(summonLifeCubicNpcId) == null }, 36 | BotSkill(summonAttractiveCubic) { player, _, _ -> player.getCombatBehavior().skillPreferences.togglableSkills[summonAttractiveCubic]!! && !player.isInCombat && player.getCubic(summonAttractiveCubicNpcId) == null }, 37 | BotSkill(touchOfLife, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false, forceTargetSelf = true), 38 | BotSkill(magicalMirror, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = true), 39 | BotSkill(ultimateDefense, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 40 | BotSkill(vengeance, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 41 | BotSkill(shieldFortress, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 42 | BotSkill(fortitude, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 43 | BotSkill(deflectArrow, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 44 | BotSkill(guardStance, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 45 | BotSkill(holyArmor, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true) 46 | ) 47 | 48 | override val conditionalSkills: List = listOf(arrest, ultimateDefense, touchOfLife, magicalMirror, vengeance) 49 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/FortuneSeekerBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.extensions.getClosestEntityInRadius 7 | import dev.l2j.autobots.extensions.useMagicSkill 8 | import dev.l2j.autobots.skills.BotSkill 9 | import dev.l2j.autobots.utils.* 10 | import kotlinx.coroutines.delay 11 | import net.sf.l2j.gameserver.enums.items.ShotType 12 | import net.sf.l2j.gameserver.model.actor.Player 13 | import net.sf.l2j.gameserver.model.actor.instance.Monster 14 | 15 | 16 | internal class FortuneSeekerBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 17 | 18 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 19 | 20 | override fun getShotType(): ShotType { 21 | return ShotType.SOULSHOT 22 | } 23 | 24 | override val getOffensiveSkills: List = listOf( 25 | BotSkill(spoilCrush){ player, _, target -> target is Monster && target.spoilerId != player.objectId && target.spoilerId == 0}, 26 | BotSkill(spoil){ player, _, target -> target is Monster && target.spoilerId != player.objectId && target.spoilerId == 0}, 27 | BotSkill(hammerCrush){_, _, target -> target is Player && !target.isStunned}, 28 | BotSkill(stunAttack){_, _, target -> target is Player && !target.isStunned}, 29 | BotSkill(armorCrush) 30 | ) 31 | 32 | override suspend fun afterAttack() { 33 | if(player.target == null || player.target !is Monster) 34 | return 35 | 36 | val sweeperSkill = player.getSkill(42) ?: return 37 | 38 | val mob = (player.target as Monster) 39 | if(mob.getHealthPercentage() < 10 && mob.spoilerId == player.objectId) 40 | delay(2000) 41 | 42 | if(mob.isDead && mob.spoilerId == player.objectId) { 43 | player.useMagicSkill(sweeperSkill) 44 | delay(1000) 45 | } 46 | 47 | val sweepable = player.getClosestEntityInRadius(300) { it is Monster && it.isDead && it.spoilerId == player.objectId} 48 | 49 | if(sweepable != null) { 50 | val previousTarget = player.target 51 | player.target = sweepable 52 | player.useMagicSkill(sweeperSkill) 53 | delay(1500) 54 | player.target = previousTarget 55 | } 56 | } 57 | 58 | override val conditionalSkills: List = emptyList() 59 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/GhostHunterBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.skills.BotSkill 7 | import dev.l2j.autobots.utils.* 8 | import net.sf.l2j.gameserver.enums.items.ShotType 9 | import net.sf.l2j.gameserver.model.actor.Player 10 | 11 | 12 | internal class GhostHunterBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 13 | 14 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 15 | 16 | override fun getShotType(): ShotType { 17 | return ShotType.SOULSHOT 18 | } 19 | 20 | override val getOffensiveSkills: List = listOf( 21 | BotSkill(bluff) { _, _, target -> target !is Player || (target.pvpFlag > 0 || target.karma > 0) }, 22 | BotSkill(backstab) { player, _, _ -> player.isBehindTarget }, 23 | BotSkill(lethalBlow), 24 | BotSkill(deadlyBlow), 25 | BotSkill(mortalStrike), 26 | BotSkill(blindingBlow)) 27 | 28 | override val conditionalSkills: List = emptyList() 29 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/GhostSentinelBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.Kiter 5 | import dev.l2j.autobots.behaviors.attributes.MiscItem 6 | import dev.l2j.autobots.behaviors.attributes.RequiresMiscItem 7 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 8 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 9 | import dev.l2j.autobots.skills.BotSkill 10 | import dev.l2j.autobots.utils.getArrowId 11 | import net.sf.l2j.gameserver.enums.items.ShotType 12 | import net.sf.l2j.gameserver.model.actor.Player 13 | 14 | 15 | internal class GhostSentinelBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), RequiresMiscItem, Kiter { 16 | 17 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 18 | 19 | override fun getShotType(): ShotType { 20 | return ShotType.SOULSHOT 21 | } 22 | 23 | override val miscItems = listOf(MiscItem({b -> getArrowId(b)})) 24 | 25 | override val getOffensiveSkills: List = listOf( 26 | BotSkill(101){_, _, target -> target is Player && target.pvpFlag > 0 }, 27 | BotSkill(343){_, _, target -> target is Player }, 28 | BotSkill(354){_, _, target -> target is Player }, 29 | BotSkill(369){_, _, target -> target is Player }) 30 | 31 | override val conditionalSkills: List = emptyList() 32 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/GrandKhavatariBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.skills.BotSkill 7 | import net.sf.l2j.gameserver.enums.items.ShotType 8 | import net.sf.l2j.gameserver.model.actor.Player 9 | 10 | 11 | internal class GrandKhavatariBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 12 | 13 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 14 | 15 | override fun getShotType(): ShotType { 16 | return ShotType.SOULSHOT 17 | } 18 | 19 | override val getOffensiveSkills: List = listOf( 20 | BotSkill(284), 21 | BotSkill(281), 22 | BotSkill(280), 23 | BotSkill(54), 24 | BotSkill(346)) 25 | 26 | override val conditionalSkills: List = emptyList() 27 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/HellKnightBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.MiscItem 5 | import dev.l2j.autobots.behaviors.attributes.PetOwner 6 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 7 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 8 | import dev.l2j.autobots.behaviors.preferences.skills.HellKnightSkillPreferences 9 | import dev.l2j.autobots.extensions.getCombatBehavior 10 | import dev.l2j.autobots.skills.BotSkill 11 | import dev.l2j.autobots.utils.* 12 | import net.sf.l2j.gameserver.enums.items.ShotType 13 | import net.sf.l2j.gameserver.model.actor.Player 14 | 15 | 16 | internal class HellKnightBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), PetOwner { 17 | 18 | override var skillPreferences: SkillPreferences = HellKnightSkillPreferences() 19 | 20 | override fun getShotType(): ShotType { 21 | return ShotType.SOULSHOT 22 | } 23 | 24 | override val getOffensiveSkills: List = listOf( 25 | BotSkill(shieldStun) { _, _, target -> target is Player && !target.isStunned }, 26 | BotSkill(shieldSlam) { _, _, target -> target is Player && !target.isMuted }, 27 | BotSkill(touchOfDeath) { player, skill, target -> target is Player && player.getCombatBehavior().validateConditionalSkill(skill) }, 28 | BotSkill(shackle) { player, skill, target -> (target !is Player || ((target.pvpFlag > 0 || target.karma > 0) )) && !target!!.isRooted && player.getCombatBehavior().validateConditionalSkill(skill) }, 29 | BotSkill(judgement) 30 | 31 | ) 32 | 33 | override val getSelfSupportSkills: List = listOf( 34 | BotSkill(ultimateDefense, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 35 | BotSkill(physicalMirror, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 36 | BotSkill(vengeance, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 37 | BotSkill(shieldFortress, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 38 | BotSkill(fortitude, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 39 | BotSkill(deflectArrow, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true) 40 | ) 41 | 42 | override val summonInfo: Pair = Pair(BotSkill(summonDarkPanther) { player, _, _ -> !player.isInCombat }, MiscItem({ 1459 }, 50, 10)) 43 | 44 | override val petBuffs: Array = getDefaultFighterBuffs() 45 | 46 | override val conditionalSkills: List = listOf(shackle, ultimateDefense, touchOfDeath, physicalMirror, vengeance, shieldOfRevenge) 47 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/MaestroBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.MiscItem 5 | import dev.l2j.autobots.behaviors.attributes.PetOwner 6 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 7 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 8 | import dev.l2j.autobots.skills.BotSkill 9 | import dev.l2j.autobots.utils.* 10 | import net.sf.l2j.gameserver.enums.items.ShotType 11 | import net.sf.l2j.gameserver.model.actor.Player 12 | import net.sf.l2j.gameserver.model.actor.instance.Servitor 13 | 14 | 15 | internal class MaestroBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), PetOwner { 16 | 17 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 18 | 19 | override fun getShotType(): ShotType { 20 | return ShotType.SOULSHOT 21 | } 22 | 23 | override suspend fun beforeAttack() { 24 | super.beforeAttack() 25 | 26 | if(player.hasServitor()) { 27 | val servitor = player.summon as Servitor 28 | servitor.applyBuffs(*getDefaultFighterBuffs()) 29 | } 30 | } 31 | 32 | override val getOffensiveSkills: List = listOf( 33 | BotSkill(hammerCrush){_, _, target -> target is Player && !target.isStunned}, 34 | BotSkill(stunAttack){_, _, target -> target is Player && !target.isStunned}, 35 | BotSkill(armorCrush) 36 | ) 37 | 38 | override val summonInfo: Pair = Pair(BotSkill(25) { player, _, _ -> !player.isInCombat }, MiscItem({ 1459 }, 50, 10)) 39 | 40 | override val petBuffs: Array = getDefaultFighterBuffs() 41 | 42 | override val conditionalSkills: List = emptyList() 43 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/MoonlightSentinelBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.Kiter 5 | import dev.l2j.autobots.behaviors.attributes.MiscItem 6 | import dev.l2j.autobots.behaviors.attributes.RequiresMiscItem 7 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 8 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 9 | import dev.l2j.autobots.skills.BotSkill 10 | import dev.l2j.autobots.utils.getArrowId 11 | import net.sf.l2j.gameserver.enums.items.ShotType 12 | import net.sf.l2j.gameserver.model.actor.Player 13 | 14 | 15 | internal class MoonlightSentinelBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), RequiresMiscItem, Kiter { 16 | 17 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 18 | 19 | override fun getShotType(): ShotType { 20 | return ShotType.SOULSHOT 21 | } 22 | 23 | override val miscItems = listOf(MiscItem({b -> getArrowId(b)})) 24 | 25 | override val getOffensiveSkills: List = listOf( 26 | BotSkill(101){_, _, target -> target is Player && target.pvpFlag > 0 }, 27 | BotSkill(343){_, _, target -> target is Player }, 28 | BotSkill(354){_, _, target -> target is Player }, 29 | BotSkill(369){_, _, target -> target is Player }) 30 | 31 | override val conditionalSkills: List = emptyList() 32 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/MysticMuseBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.skills.BotSkill 7 | import net.sf.l2j.gameserver.enums.items.ShotType 8 | import net.sf.l2j.gameserver.model.actor.Player 9 | 10 | 11 | internal class MysticMuseBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 12 | 13 | override var skillPreferences: SkillPreferences = SkillPreferences(true) 14 | 15 | override fun getShotType(): ShotType { 16 | return ShotType.BLESSED_SPIRITSHOT 17 | } 18 | 19 | override val getOffensiveSkills: List = listOf( 20 | BotSkill(1265), 21 | BotSkill(1342), 22 | BotSkill(1340), 23 | BotSkill(1235)) 24 | 25 | override val conditionalSkills: List = emptyList() 26 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/PhoenixKnightBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.MiscItem 5 | import dev.l2j.autobots.behaviors.attributes.RequiresMiscItem 6 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 7 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 8 | import dev.l2j.autobots.behaviors.preferences.skills.PhoenixKnightSkillPreferences 9 | import dev.l2j.autobots.extensions.getCombatBehavior 10 | import dev.l2j.autobots.skills.BotSkill 11 | import dev.l2j.autobots.utils.* 12 | import net.sf.l2j.gameserver.enums.items.ShotType 13 | import net.sf.l2j.gameserver.model.actor.Player 14 | 15 | 16 | internal class PhoenixKnightBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), RequiresMiscItem { 17 | 18 | override var skillPreferences: SkillPreferences = PhoenixKnightSkillPreferences() 19 | 20 | override fun getShotType(): ShotType { 21 | return ShotType.SOULSHOT 22 | } 23 | 24 | override val miscItems = listOf(MiscItem({ 1459 }, 50, 10)) 25 | 26 | override val getOffensiveSkills: List = listOf( 27 | BotSkill(shieldSlam) { _, _, target -> target is Player && !target.isMuted }, 28 | BotSkill(shieldStun) { _, _, target -> target is Player && !target.isStunned }, 29 | BotSkill(shackle) { player, skill, target -> (target !is Player || ((target.pvpFlag > 0 || target.karma > 0) )) && !target!!.isRooted && player.getCombatBehavior().validateConditionalSkill(skill) }, 30 | BotSkill(tribunal) 31 | ) 32 | 33 | override val getSelfSupportSkills: List = listOf( 34 | BotSkill(angelicIcon, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 35 | BotSkill(touchOfLife, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 36 | BotSkill(ultimateDefense, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 37 | BotSkill(holyBlessing, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 38 | BotSkill(deflectArrow, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 39 | BotSkill(aegisStance, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 40 | BotSkill(shieldFortress, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 41 | BotSkill(fortitude, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 42 | BotSkill(holyBlade, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 43 | BotSkill(holyArmor, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 44 | BotSkill(physicalMirror, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 45 | BotSkill(vengeance, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false) 46 | ) 47 | 48 | override val conditionalSkills: List = listOf(shackle, ultimateDefense, holyBlessing, physicalMirror, vengeance, touchOfLife, angelicIcon) 49 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/SagittariusBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.Kiter 5 | import dev.l2j.autobots.behaviors.attributes.MiscItem 6 | import dev.l2j.autobots.behaviors.attributes.RequiresMiscItem 7 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 8 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 9 | import dev.l2j.autobots.behaviors.preferences.skills.SagittariusSkillPreferences 10 | import dev.l2j.autobots.skills.BotSkill 11 | import dev.l2j.autobots.utils.* 12 | import net.sf.l2j.gameserver.enums.items.ShotType 13 | import net.sf.l2j.gameserver.model.actor.Player 14 | 15 | 16 | internal class SagittariusBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), RequiresMiscItem, Kiter { 17 | 18 | override var skillPreferences: SkillPreferences = SagittariusSkillPreferences() 19 | 20 | override fun getShotType(): ShotType { 21 | return ShotType.SOULSHOT 22 | } 23 | 24 | override val getOffensiveSkills: List = listOf( 25 | BotSkill(stunningShot){_, _, target -> target is Player && (target.pvpFlag > 0 || target.karma > 0) && !target.isStunned}, 26 | BotSkill(lethalShot){_, _, target -> target is Player }, 27 | BotSkill(hamstringShot){_, _, target -> target is Player && !target.hasEffect(hamstringShot) }) 28 | 29 | override val getSelfSupportSkills: List = listOf( 30 | BotSkill(rapidShot, isConditionalSkill = false, isTogglableSkill = false, useWhenEffectIsNotPresent = true), 31 | BotSkill(dash, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = true), 32 | BotSkill(ultimateEvasion, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 33 | BotSkill(hawkEye, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 34 | BotSkill(viciousStance, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 35 | BotSkill(accuracy, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true) 36 | ) 37 | 38 | override val miscItems = listOf(MiscItem({ b -> getArrowId(b)})) 39 | 40 | override val conditionalSkills: List = listOf(dash, ultimateEvasion) 41 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/ShillienTemplarBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.MiscItem 5 | import dev.l2j.autobots.behaviors.attributes.RequiresMiscItem 6 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 7 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 8 | import dev.l2j.autobots.skills.BotSkill 9 | import dev.l2j.autobots.utils.* 10 | import net.sf.l2j.gameserver.enums.items.ShotType 11 | import net.sf.l2j.gameserver.model.actor.Player 12 | 13 | 14 | internal class ShillienTemplarBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), RequiresMiscItem { 15 | 16 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 17 | 18 | override fun getShotType(): ShotType { 19 | return ShotType.SOULSHOT 20 | } 21 | 22 | override val miscItems = listOf(MiscItem({ 1458 }, 100, 50)) 23 | 24 | override val getOffensiveSkills: List = listOf( 25 | BotSkill(shieldBash) { _, _, target -> target is Player && target.target == player }, 26 | BotSkill(arrest) { player, _, target -> target is Player && !target.isRooted && distance(player, target) > 300 }, 27 | BotSkill(touchOfDeath) { _, _, target -> target is Player && player.getHealthPercentage() < 75 }, 28 | BotSkill(judgement) 29 | //TODO hex 30 | ) 31 | 32 | override val getSelfSupportSkills: List = listOf( 33 | BotSkill(summonVampiricCubic) { player, _, _ -> !player.isInCombat && player.getCubic(summonVampiricCubicNpcId) == null }, 34 | BotSkill(summonPhantomCubic) { player, _, _ -> !player.isInCombat && player.getCubic(summonPhantomCubicNpcId) == null }, 35 | BotSkill(summonViperCubic) { player, _, _ -> !player.isInCombat && player.getCubic(summonViperCubicNpcId) == null }, 36 | BotSkill(magicalMirror) { player, _, _ -> player.getHealthPercentage() < 60 }, 37 | BotSkill(ultimateDefense) { player, _, _ -> player.getHealthPercentage() < 20 } 38 | ) 39 | 40 | override val conditionalSkills: List = emptyList() 41 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/SoultakerBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.MiscItem 5 | import dev.l2j.autobots.behaviors.attributes.PetOwner 6 | import dev.l2j.autobots.behaviors.attributes.RequiresMiscItem 7 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 8 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 9 | import dev.l2j.autobots.behaviors.preferences.skills.SoultakerSkillPreferences 10 | import dev.l2j.autobots.extensions.getCombatBehavior 11 | import dev.l2j.autobots.skills.BotSkill 12 | import dev.l2j.autobots.utils.* 13 | import net.sf.l2j.gameserver.enums.items.ShotType 14 | import net.sf.l2j.gameserver.model.actor.Player 15 | 16 | 17 | internal class SoultakerBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), RequiresMiscItem, PetOwner { 18 | 19 | override var skillPreferences: SkillPreferences = SoultakerSkillPreferences() 20 | 21 | override fun getShotType(): ShotType { 22 | return ShotType.BLESSED_SPIRITSHOT 23 | } 24 | 25 | override val miscItems = listOf(MiscItem({ 2508 })) 26 | 27 | override val getOffensiveSkills: List = listOf( 28 | BotSkill(curseGloom){ player, _, target -> player.getCombatBehavior().skillPreferences.togglableSkills[curseGloom]!! && (/*(target is Monster) || */(target is Player && (target.pvpFlag > 0 || target.karma > 0)) && !target.hasEffect(curseGloom))}, 29 | BotSkill(anchor){ player, _, target -> player.getCombatBehavior().skillPreferences.togglableSkills[anchor]!! && target is Player && (target.pvpFlag > 0 || target.karma > 0) && !target.hasEffect(anchor)}, 30 | BotSkill(curseOfAbyss){ player, _, target -> player.getCombatBehavior().skillPreferences.togglableSkills[curseOfAbyss]!! && target is Player && (target.pvpFlag > 0 || target.karma > 0) && !target.hasEffect(curseOfAbyss)}, 31 | BotSkill(curseOfDoom){ player, _, target -> player.getCombatBehavior().skillPreferences.togglableSkills[curseOfDoom]!! && target is Player && (target.pvpFlag > 0 || target.karma > 0) && !target.hasEffect(curseOfDoom)}, 32 | BotSkill(silence){ player, _, target -> player.getCombatBehavior().skillPreferences.togglableSkills[silence]!! && target is Player && (target.pvpFlag > 0 || target.karma > 0) && !target.hasEffect(silence)}, 33 | BotSkill(slow) { player, skill, target -> target != null && !target.hasEffect(slow) && player.getCombatBehavior().validateConditionalSkill(skill)}, 34 | BotSkill(darkVortex), 35 | BotSkill(vampiricClaw){ player, skill, _ -> player.getCombatBehavior().validateConditionalSkill(skill)}, 36 | BotSkill(deathSpike)) 37 | 38 | override val summonInfo: Pair = Pair(BotSkill(1129) { _, _, target -> target != null && target.isDead }, MiscItem({ 1459 }, 50, 10)) 39 | 40 | override val petBuffs: Array = emptyArray() 41 | 42 | override val getSelfSupportSkills: List = 43 | listOf( 44 | BotSkill(arcanePower, { player, _, _ -> player.getCombatBehavior().skillPreferences.togglableSkills[arcanePower]!! && !player.hasEffect(arcanePower) && player.isInCombat }, true), 45 | BotSkill(transferPain, { player, _, _ -> player.getCombatBehavior().skillPreferences.togglableSkills[transferPain]!! && !player.hasEffect(transferPain) && player.hasServitor() }, true) 46 | ) 47 | 48 | override val conditionalSkills: List = listOf(slow, vampiricClaw) 49 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/SpectralDancerBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.skills.BotSkill 7 | import dev.l2j.autobots.utils.* 8 | import net.sf.l2j.commons.random.Rnd 9 | import net.sf.l2j.gameserver.enums.items.ShotType 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | 12 | 13 | internal class SpectralDancerBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 14 | 15 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 16 | 17 | override fun getShotType(): ShotType { 18 | return ShotType.SOULSHOT 19 | } 20 | 21 | override val getOffensiveSkills: List = listOf( 22 | BotSkill(arrest) { _, _, target -> target is Player && !target.isRooted }, 23 | BotSkill(judgement), 24 | BotSkill(demonicBladeDance){ player, _, target -> target is Player && distance(player, target) < 100 && Rnd.get(1, 10) < 4 } 25 | 26 | ) 27 | 28 | override val getSelfSupportSkills: List = listOf( 29 | BotSkill(ultimateDefense) { player, _, _ -> player.getHealthPercentage() < 20 } 30 | ) 31 | 32 | override val conditionalSkills: List = emptyList() 33 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/StormScreamerBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.skills.BotSkill 7 | import net.sf.l2j.gameserver.enums.items.ShotType 8 | import net.sf.l2j.gameserver.model.actor.Player 9 | 10 | 11 | internal class StormScreamerBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 12 | 13 | override var skillPreferences: SkillPreferences = SkillPreferences(true) 14 | 15 | override fun getShotType(): ShotType { 16 | return ShotType.BLESSED_SPIRITSHOT 17 | } 18 | 19 | override val getOffensiveSkills: List = listOf( 20 | BotSkill(1341), 21 | BotSkill(1343), 22 | BotSkill(1234), 23 | BotSkill(1239)) 24 | 25 | override val conditionalSkills: List = emptyList() 26 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/SwordMuseBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.behaviors.preferences.skills.SwordMuseSkillPreferences 7 | import dev.l2j.autobots.extensions.getCombatBehavior 8 | import dev.l2j.autobots.skills.BotSkill 9 | import dev.l2j.autobots.utils.* 10 | import net.sf.l2j.gameserver.enums.items.ShotType 11 | import net.sf.l2j.gameserver.model.actor.Player 12 | 13 | 14 | internal class SwordMuseBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 15 | 16 | override var skillPreferences: SkillPreferences = SwordMuseSkillPreferences() 17 | 18 | override fun getShotType(): ShotType { 19 | return ShotType.SOULSHOT 20 | } 21 | 22 | override val getOffensiveSkills: List = listOf( 23 | BotSkill(arrest) { player, skill, target -> (target !is Player || ((target.pvpFlag > 0 || target.karma > 0) )) && !target!!.isRooted && player.getCombatBehavior().validateConditionalSkill(skill) }, 24 | BotSkill(songOfSilence){player, skill, target -> (target !is Player || ((target.pvpFlag > 0 || target.karma > 0) )) && player.getCombatBehavior().validateConditionalSkill(skill) && target != null && !target.hasEffect(songOfSilence) } 25 | ) 26 | 27 | override val getSelfSupportSkills: List = listOf( 28 | BotSkill(ultimateDefense, isConditionalSkill = true, isTogglableSkill = false, useWhenEffectIsNotPresent = false), 29 | BotSkill(deflectArrow, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true), 30 | BotSkill(holyBlade, isConditionalSkill = false, isTogglableSkill = true, useWhenEffectIsNotPresent = true) 31 | ) 32 | 33 | override val conditionalSkills: List = listOf(ultimateDefense, songOfSilence) 34 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/TitanBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.skills.BotSkill 7 | import dev.l2j.autobots.utils.getHealthPercentage 8 | import net.sf.l2j.commons.random.Rnd 9 | import net.sf.l2j.gameserver.enums.items.ShotType 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | 12 | 13 | internal class TitanBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 14 | 15 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 16 | 17 | override fun getShotType(): ShotType { 18 | return ShotType.SOULSHOT 19 | } 20 | 21 | override val getOffensiveSkills: List = listOf( 22 | BotSkill(362), 23 | BotSkill(315) { _, _, _ -> Rnd.nextDouble() < 0.8 }, 24 | BotSkill(190) { _, _, _ -> Rnd.nextDouble() < 0.2 } ) 25 | 26 | override val getSelfSupportSkills: List = listOf( 27 | BotSkill(139) { player, _, _ -> player.getHealthPercentage() < 30 }, 28 | BotSkill(176) { player, _, _ -> player.getHealthPercentage() < 15 } 29 | ) 30 | 31 | override val conditionalSkills: List = emptyList() 32 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/WindRiderBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 5 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 6 | import dev.l2j.autobots.skills.BotSkill 7 | import dev.l2j.autobots.utils.* 8 | import net.sf.l2j.gameserver.enums.items.ShotType 9 | import net.sf.l2j.gameserver.model.actor.Player 10 | 11 | 12 | internal class WindRiderBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences) { 13 | 14 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 15 | 16 | override fun getShotType(): ShotType { 17 | return ShotType.SOULSHOT 18 | } 19 | 20 | override val getOffensiveSkills: List = listOf( 21 | BotSkill(bluff) { _, _, target -> target !is Player || (target.pvpFlag > 0 || target.karma > 0) }, 22 | BotSkill(backstab) { player, _, _ -> player.isBehindTarget }, 23 | BotSkill(lethalBlow), 24 | BotSkill(deadlyBlow), 25 | BotSkill(mortalStrike), 26 | BotSkill(blindingBlow)) 27 | 28 | override val conditionalSkills: List = emptyList() 29 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/DarkElvenWizardBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import dev.l2j.autobots.utils.distance 9 | import net.sf.l2j.gameserver.enums.items.ShotType 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | 12 | 13 | internal class DarkElvenWizardBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 14 | 15 | override var skillPreferences: SkillPreferences = SkillPreferences(true) 16 | 17 | override fun getShotType(): ShotType { 18 | return ShotType.BLESSED_SPIRITSHOT 19 | } 20 | 21 | override val getOffensiveSkills: List = listOf( 22 | BotSkill(1266), 23 | BotSkill(1172){player, _, target -> target != null && distance(player, target) < 200 }, 24 | BotSkill(1178), 25 | BotSkill(1175)) 26 | 27 | override val conditionalSkills: List = emptyList() 28 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/ElvenWizardBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import dev.l2j.autobots.utils.distance 9 | import net.sf.l2j.gameserver.enums.items.ShotType 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | 12 | 13 | internal class ElvenWizardBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 14 | 15 | override var skillPreferences: SkillPreferences = SkillPreferences(true) 16 | 17 | override fun getShotType(): ShotType { 18 | return ShotType.BLESSED_SPIRITSHOT 19 | } 20 | 21 | override val getOffensiveSkills: List = listOf( 22 | BotSkill(1264), 23 | BotSkill(1172){player, _, target -> target != null && distance(player, target) < 200 }, 24 | BotSkill(1175), 25 | BotSkill(1274), 26 | BotSkill(1181)) 27 | 28 | override val conditionalSkills: List = emptyList() 29 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/FighterBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import net.sf.l2j.gameserver.enums.items.ShotType 9 | import net.sf.l2j.gameserver.model.actor.Player 10 | 11 | 12 | internal class FighterBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 13 | 14 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 15 | 16 | override fun getShotType(): ShotType { 17 | return ShotType.SOULSHOT 18 | } 19 | 20 | override val getOffensiveSkills: List = listOf( 21 | BotSkill(3), 22 | BotSkill(16), 23 | BotSkill(56)) 24 | 25 | override val conditionalSkills: List = emptyList() 26 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/HumanWizardBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import dev.l2j.autobots.utils.distance 9 | import net.sf.l2j.gameserver.enums.items.ShotType 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | 12 | 13 | internal class HumanWizardBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 14 | 15 | override var skillPreferences: SkillPreferences = SkillPreferences(true) 16 | 17 | override fun getShotType(): ShotType { 18 | return ShotType.BLESSED_SPIRITSHOT 19 | } 20 | 21 | override val getOffensiveSkills: List = listOf( 22 | BotSkill(1172){player, _, target -> target != null && distance(player, target) < 200 }, 23 | BotSkill(1220), 24 | BotSkill(1274), 25 | BotSkill(1181)) 26 | 27 | override val conditionalSkills: List = emptyList() 28 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/KnightBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import dev.l2j.autobots.utils.getHealthPercentage 9 | import dev.l2j.autobots.utils.shieldStun 10 | import dev.l2j.autobots.utils.ultimateDefense 11 | import net.sf.l2j.gameserver.enums.items.ShotType 12 | import net.sf.l2j.gameserver.model.actor.Player 13 | 14 | 15 | internal class KnightBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 16 | 17 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 18 | 19 | override fun getShotType(): ShotType { 20 | return ShotType.SOULSHOT 21 | } 22 | 23 | override val getOffensiveSkills: List = listOf( 24 | BotSkill(shieldStun) { _, _, target -> target is Player && !target.isStunned }) 25 | 26 | override val getSelfSupportSkills: List = listOf( 27 | BotSkill(ultimateDefense) { player, _, _ -> player.getHealthPercentage() < 40 } 28 | ) 29 | 30 | override val conditionalSkills: List = emptyList() 31 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/MonkBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import net.sf.l2j.gameserver.enums.items.ShotType 9 | import net.sf.l2j.gameserver.model.actor.Player 10 | 11 | 12 | internal class MonkBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 13 | 14 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 15 | 16 | override fun getShotType(): ShotType { 17 | return ShotType.SOULSHOT 18 | } 19 | 20 | override val getOffensiveSkills: List = listOf( 21 | BotSkill(120){ _, _, target -> target is Player && !target.isStunned}, 22 | BotSkill(54){ player, skill, _ -> player.charges < skill.maxCharges}, 23 | BotSkill(284){ player, skill, _ -> player.charges < skill.maxCharges}) 24 | 25 | override val getSelfSupportSkills: List = listOf( 26 | BotSkill(50){player, skill, _ -> player.charges < skill.maxCharges } 27 | ) 28 | 29 | override val conditionalSkills: List = emptyList() 30 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/MysticBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import net.sf.l2j.gameserver.enums.items.ShotType 9 | import net.sf.l2j.gameserver.model.actor.Player 10 | 11 | 12 | internal class MysticBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 13 | 14 | override var skillPreferences: SkillPreferences = SkillPreferences(true) 15 | 16 | override fun getShotType(): ShotType { 17 | return ShotType.BLESSED_SPIRITSHOT 18 | } 19 | 20 | override val getOffensiveSkills: List = listOf( 21 | BotSkill(1147), 22 | BotSkill(1184), 23 | BotSkill(1177)) 24 | 25 | override val conditionalSkills: List = emptyList() 26 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/OrcFighterBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.Autobot 4 | import dev.l2j.autobots.behaviors.CombatBehavior 5 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 6 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 7 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 8 | import dev.l2j.autobots.skills.BotSkill 9 | import net.sf.l2j.gameserver.enums.items.ShotType 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | 12 | 13 | internal class OrcFighterBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 14 | 15 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 16 | 17 | override fun getShotType(): ShotType { 18 | return ShotType.SOULSHOT 19 | } 20 | 21 | override val getOffensiveSkills: List = listOf( 22 | BotSkill(3), 23 | BotSkill(29)) 24 | 25 | override val conditionalSkills: List = emptyList() 26 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/OrcMysticBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import net.sf.l2j.gameserver.enums.items.ShotType 9 | import net.sf.l2j.gameserver.model.actor.Player 10 | 11 | 12 | internal class OrcMysticBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 13 | override var skillPreferences: SkillPreferences = SkillPreferences(player.level >= 7) 14 | 15 | override fun getShotType(): ShotType { 16 | return ShotType.BLESSED_SPIRITSHOT 17 | } 18 | 19 | override val getOffensiveSkills: List = listOf( 20 | BotSkill(1090)) 21 | 22 | override fun onLevelUp(oldLevel: Int, newLevel: Int) { 23 | if(player.level >= 7) { 24 | skillPreferences.isSkillsOnly = true 25 | } 26 | } 27 | 28 | override val conditionalSkills: List = emptyList() 29 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/OrcRaiderBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import dev.l2j.autobots.utils.stunAttack 9 | import net.sf.l2j.gameserver.enums.items.ShotType 10 | import net.sf.l2j.gameserver.model.actor.Player 11 | 12 | 13 | internal class OrcRaiderBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 14 | 15 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 16 | 17 | override fun getShotType(): ShotType { 18 | return ShotType.SOULSHOT 19 | } 20 | 21 | override val getOffensiveSkills: List = listOf( 22 | BotSkill(stunAttack){ _, _, target -> target is Player && !target.isStunned}, 23 | BotSkill(255)) 24 | 25 | override val conditionalSkills: List = emptyList() 26 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/RogueBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.MiscItem 5 | import dev.l2j.autobots.behaviors.attributes.RequiresMiscItem 6 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 7 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 8 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 9 | import dev.l2j.autobots.skills.BotSkill 10 | import dev.l2j.autobots.utils.getArrowId 11 | import dev.l2j.autobots.utils.getHealthPercentage 12 | import dev.l2j.autobots.utils.hasEffect 13 | import dev.l2j.autobots.utils.rapidShot 14 | import net.sf.l2j.gameserver.enums.items.ShotType 15 | import net.sf.l2j.gameserver.model.actor.Player 16 | 17 | 18 | internal class RogueBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), RequiresMiscItem, SecretManaRegen { 19 | 20 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 21 | 22 | override fun getShotType(): ShotType { 23 | return ShotType.SOULSHOT 24 | } 25 | 26 | override val getOffensiveSkills: List = listOf( 27 | BotSkill(16), 28 | BotSkill(96){_, _, target -> target?.getFirstEffect(96) != null}, 29 | BotSkill(101){_, _, target -> target is Player && target.pvpFlag > 0 && !target.isStunned}) 30 | 31 | override val getSelfSupportSkills: List = listOf( 32 | BotSkill(rapidShot) { player, _, _ -> !player.hasEffect(rapidShot)}, 33 | BotSkill(111) { player, _, _ -> player.getHealthPercentage() < 40} 34 | ) 35 | 36 | override val miscItems = listOf(MiscItem({ b -> getArrowId(b) })) 37 | 38 | override val conditionalSkills: List = emptyList() 39 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/classes/pre/WarriorBehavior.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.classes.pre 2 | 3 | import dev.l2j.autobots.behaviors.CombatBehavior 4 | import dev.l2j.autobots.behaviors.attributes.SecretManaRegen 5 | import dev.l2j.autobots.behaviors.preferences.CombatPreferences 6 | import dev.l2j.autobots.behaviors.preferences.SkillPreferences 7 | import dev.l2j.autobots.skills.BotSkill 8 | import net.sf.l2j.gameserver.enums.items.ShotType 9 | import net.sf.l2j.gameserver.model.actor.Player 10 | 11 | 12 | internal class WarriorBehavior(player: Player, combatPreferences: CombatPreferences) : CombatBehavior(player, combatPreferences), SecretManaRegen { 13 | 14 | override var skillPreferences: SkillPreferences = SkillPreferences(false) 15 | 16 | override fun getShotType(): ShotType { 17 | return ShotType.SOULSHOT 18 | } 19 | 20 | override val getOffensiveSkills: List = listOf( 21 | BotSkill(255), 22 | BotSkill(3)) 23 | 24 | override val conditionalSkills: List = emptyList() 25 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/preferences/ActivityPreferences.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.preferences 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty 4 | import dev.l2j.autobots.AutobotScheduler 5 | import java.time.Clock 6 | import java.time.LocalDateTime 7 | 8 | internal data class ActivityPreferences(@JsonProperty("activityType")var activityType: ActivityType = ActivityType.None, 9 | @JsonProperty("uptimeMinutes")var uptimeMinutes: Int = 60, 10 | @JsonProperty("loginTime")var loginTime: String = "09:00", 11 | @JsonProperty("logoutTime")var logoutTime: String = "20:00"){ 12 | fun logoutTimeIsInThePast() : Boolean{ 13 | val dateTimeNow = LocalDateTime.now(Clock.systemUTC()) 14 | val logoutTime = LocalDateTime.parse("${dateTimeNow.year}-${if (dateTimeNow.monthValue < 10) "0${dateTimeNow.monthValue}" else dateTimeNow.monthValue}-${if (dateTimeNow.dayOfMonth < 10) "0${dateTimeNow.dayOfMonth}" else dateTimeNow.dayOfMonth} $logoutTime", AutobotScheduler.formatter) 15 | return dateTimeNow > logoutTime 16 | } 17 | } 18 | 19 | enum class ActivityType { 20 | None, 21 | Uptime, 22 | Schedule 23 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/preferences/AttackPlayerType.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.preferences 2 | 3 | internal enum class AttackPlayerType { 4 | None, 5 | Flagged, 6 | Innocent 7 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/preferences/CombatPreferences.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.preferences 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty 4 | import dev.l2j.autobots.AutobotData 5 | 6 | internal open class DefaultCombatPreferences( 7 | @JsonProperty("targetingRadius")override var targetingRadius: Int = AutobotData.settings.targetingRange, 8 | @JsonProperty("attackPlayerType")override var attackPlayerType: AttackPlayerType = AutobotData.settings.attackPlayerType, 9 | @JsonProperty("buffs") override var buffs: Array = emptyArray(), 10 | @JsonProperty("targetingPreference")override var targetingPreference: TargetingPreference = AutobotData.settings.targetingPreference, 11 | @JsonProperty("useManaPots")override var useManaPots: Boolean = AutobotData.settings.useManaPots, 12 | @JsonProperty("useQuickHealingPots")override var useQuickHealingPots: Boolean = AutobotData.settings.useQuickHealingPots, 13 | @JsonProperty("useGreaterHealingPots")override var useGreaterHealingPots: Boolean = AutobotData.settings.useGreaterHealingPots, 14 | @JsonProperty("useGreaterCpPots")override var useGreaterCpPots: Boolean = AutobotData.settings.useGreaterCpPots 15 | ) : CombatPreferences 16 | 17 | internal open class ArcherCombatPreferences( 18 | @JsonProperty("kiteRadius")var kiteRadius: Int = 500, 19 | @JsonProperty("isKiting")var isKiting: Boolean = true, 20 | @JsonProperty("kitingDelay")var kitingDelay: Long = 700, 21 | @JsonProperty("targetingRadius")override var targetingRadius: Int = AutobotData.settings.targetingRange, 22 | @JsonProperty("attackPlayerType")override var attackPlayerType: AttackPlayerType = AutobotData.settings.attackPlayerType, 23 | @JsonProperty("buffs")override var buffs: Array = emptyArray(), 24 | @JsonProperty("targetingPreference")override var targetingPreference: TargetingPreference = AutobotData.settings.targetingPreference, 25 | @JsonProperty("useManaPots")override var useManaPots: Boolean = AutobotData.settings.useManaPots, 26 | @JsonProperty("useQuickHealingPots")override var useQuickHealingPots: Boolean = AutobotData.settings.useQuickHealingPots, 27 | @JsonProperty("useGreaterHealingPots")override var useGreaterHealingPots: Boolean = AutobotData.settings.useGreaterHealingPots, 28 | @JsonProperty("useGreaterCpPots")override var useGreaterCpPots: Boolean = AutobotData.settings.useGreaterCpPots) : CombatPreferences 29 | 30 | internal open class PetOwnerCombatPreferences( 31 | @JsonProperty("petAssists")override var petAssists: Boolean = true, 32 | @JsonProperty("summonPet")override var summonPet: Boolean = true, 33 | @JsonProperty("petUsesShots")override var petUsesShots: Boolean = false, 34 | @JsonProperty("petShotId")override var petShotId: Int, 35 | @JsonProperty("petHasBuffs")override var petHasBuffs: Boolean = true, 36 | @JsonProperty("targetingRadius")override var targetingRadius: Int = AutobotData.settings.targetingRange, 37 | @JsonProperty("attackPlayerType")override var attackPlayerType: AttackPlayerType = AutobotData.settings.attackPlayerType, 38 | @JsonProperty("buffs")override var buffs: Array = emptyArray(), 39 | @JsonProperty("targetingPreference")override var targetingPreference: TargetingPreference = AutobotData.settings.targetingPreference, 40 | @JsonProperty("useManaPots")override var useManaPots: Boolean = AutobotData.settings.useManaPots, 41 | @JsonProperty("useQuickHealingPots")override var useQuickHealingPots: Boolean = AutobotData.settings.useQuickHealingPots, 42 | @JsonProperty("useGreaterHealingPots")override var useGreaterHealingPots: Boolean = AutobotData.settings.useGreaterHealingPots, 43 | @JsonProperty("useGreaterCpPots")override var useGreaterCpPots: Boolean = AutobotData.settings.useGreaterCpPots) : CombatPreferences, PetOwnerPreferences 44 | 45 | internal open class DuelistCombatPreferences( 46 | @JsonProperty("targetingRadius")override var targetingRadius: Int = AutobotData.settings.targetingRange, 47 | @JsonProperty("attackPlayerType")override var attackPlayerType: AttackPlayerType = AutobotData.settings.attackPlayerType, 48 | @JsonProperty("buffs")override var buffs: Array = emptyArray(), 49 | @JsonProperty("targetingPreference")override var targetingPreference: TargetingPreference = AutobotData.settings.targetingPreference, 50 | @JsonProperty("useManaPots")override var useManaPots: Boolean = AutobotData.settings.useManaPots, 51 | @JsonProperty("useQuickHealingPots")override var useQuickHealingPots: Boolean = AutobotData.settings.useQuickHealingPots, 52 | @JsonProperty("useGreaterHealingPots")override var useGreaterHealingPots: Boolean = AutobotData.settings.useGreaterHealingPots, 53 | @JsonProperty("useGreaterCpPots")override var useGreaterCpPots: Boolean = AutobotData.settings.useGreaterCpPots) : CombatPreferences 54 | 55 | internal interface CombatPreferences{ 56 | var targetingRadius: Int 57 | var attackPlayerType: AttackPlayerType 58 | var buffs: Array 59 | var targetingPreference: TargetingPreference 60 | var useManaPots: Boolean 61 | var useQuickHealingPots: Boolean 62 | var useGreaterHealingPots: Boolean 63 | var useGreaterCpPots: Boolean 64 | } 65 | 66 | internal interface PetOwnerPreferences { 67 | var petAssists: Boolean 68 | var summonPet: Boolean 69 | var petUsesShots: Boolean 70 | var petShotId: Int 71 | var petHasBuffs: Boolean 72 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/preferences/SkillPreferences.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.preferences 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty 4 | 5 | internal open class SkillPreferences( 6 | @JsonProperty("isSkillsOnly")var isSkillsOnly: Boolean, 7 | @JsonProperty("skillUsageConditions")open val skillUsageConditions : MutableList = mutableListOf(), 8 | @JsonProperty("togglableSkills")open val togglableSkills: MutableMap = mutableMapOf() 9 | ) -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/preferences/SocialPreferences.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.preferences 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty 4 | 5 | internal open class SocialPreferences( 6 | @JsonProperty("townAction")var townAction: TownAction = TownAction.None, 7 | @JsonProperty("tradingAction")var tradingAction: TradingAction? = null 8 | ) 9 | 10 | internal enum class TownAction { 11 | None, 12 | TeleToRandomLocation, 13 | TeleToSpecificLocation, 14 | Trade 15 | } 16 | 17 | internal data class TradingAction( 18 | @JsonProperty("looksFor")var looksForItems: MutableList, 19 | @JsonProperty("offers")var offersItems: MutableList 20 | ) 21 | 22 | internal data class TradingItem( 23 | @JsonProperty("itemId")var itemId: Int, 24 | @JsonProperty("itemCount")var itemCount: Int 25 | ) -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/preferences/TargetingPreference.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.preferences 2 | 3 | enum class TargetingPreference { 4 | Random, 5 | Closest 6 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/sequences/EquipGearRealisticallySequence.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.sequences 2 | 3 | import dev.l2j.autobots.utils.CancellationToken 4 | import dev.l2j.autobots.utils.giveItemsByClassAndLevel 5 | import net.sf.l2j.gameserver.model.actor.Player 6 | 7 | internal class EquipGearRealisticallySequence(override val bot: Player) : Sequence { 8 | 9 | override var cancellationToken: CancellationToken? = null 10 | 11 | override suspend fun definition() { 12 | giveItemsByClassAndLevel(bot, addRealistically = true) 13 | } 14 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/sequences/ReturnToDeathLocationSequence.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.sequences 2 | 3 | import dev.l2j.autobots.extensions.findClosestGatekeeper 4 | import dev.l2j.autobots.extensions.getSocialBehavior 5 | import dev.l2j.autobots.extensions.location 6 | import dev.l2j.autobots.extensions.moveTo 7 | import dev.l2j.autobots.utils.CancellationToken 8 | import dev.l2j.autobots.utils.distance 9 | import kotlinx.coroutines.delay 10 | import net.sf.l2j.commons.random.Rnd 11 | import net.sf.l2j.gameserver.data.xml.TeleportLocationData 12 | import net.sf.l2j.gameserver.enums.ZoneId 13 | import net.sf.l2j.gameserver.model.actor.Player 14 | import net.sf.l2j.gameserver.model.location.Location 15 | 16 | internal class ReturnToDeathLocationSequence(override val bot: Player) : Sequence { 17 | 18 | override var cancellationToken: CancellationToken? = null 19 | 20 | override suspend fun definition() { 21 | 22 | if (bot.lastDeathLocation == null) { 23 | return 24 | } 25 | 26 | delay(Rnd.get(5000, 8000).toLong()) 27 | 28 | val closestGatekeeper = bot.findClosestGatekeeper() ?: return 29 | bot.target = closestGatekeeper 30 | bot.moveTo(closestGatekeeper.x, closestGatekeeper.y, closestGatekeeper.z) 31 | while (distance(bot, closestGatekeeper) >= 110) { 32 | 33 | if (bot.isDead) { 34 | return 35 | } 36 | 37 | if (distance(bot, closestGatekeeper) <= 1000) { 38 | closestGatekeeper.onAction(bot) 39 | } 40 | 41 | if (!bot.isMoving) { 42 | 43 | } 44 | delay(Rnd.get(4000, 6000).toLong()) 45 | } 46 | delay(Rnd.get(2000, 4000).toLong()) 47 | 48 | val closestTeleportLocation = TeleportLocationData.getInstance().allTeleportLocations 49 | .filter { !it.isNoble } 50 | .minBy { distance(bot.lastDeathLocation!!, Location(it.x, it.y, it.z)) } 51 | 52 | bot.teleportTo(closestTeleportLocation, 20) 53 | 54 | delay(Rnd.get(5000, 8000).toLong()) 55 | if (bot.isInsideZone(ZoneId.TOWN)) { 56 | return bot.getSocialBehavior().onRespawn() 57 | } 58 | 59 | val deathLoc = bot.lastDeathLocation!! 60 | bot.moveTo(deathLoc.x, deathLoc.y, deathLoc.z) 61 | bot.lastDeathLocation = null 62 | while (distance(bot.location(), deathLoc) >= 1500) { 63 | 64 | if (bot.isDead) { 65 | return 66 | } 67 | 68 | if (bot.isInCombat) { 69 | return 70 | } 71 | 72 | if (!bot.isMoving) { 73 | if(!bot.isMoving) { 74 | bot.moveTo(deathLoc.x, deathLoc.y, deathLoc.z) 75 | } 76 | } 77 | 78 | delay(Rnd.get(2000, 4000).toLong()) 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/sequences/Sequence.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.sequences 2 | 3 | import dev.l2j.autobots.CoScopes 4 | import dev.l2j.autobots.extensions.getActiveSequence 5 | import dev.l2j.autobots.extensions.setActiveSequence 6 | import dev.l2j.autobots.utils.CancellationToken 7 | import kotlinx.coroutines.async 8 | import net.sf.l2j.gameserver.model.actor.Player 9 | 10 | internal interface Sequence { 11 | val bot: Player 12 | 13 | var cancellationToken: CancellationToken? 14 | 15 | suspend fun definition() 16 | 17 | suspend fun execute(){ 18 | if(bot.getActiveSequence() != null) { 19 | bot.getActiveSequence()?.cancellationToken?.cancelLambda?.invoke() 20 | bot.setActiveSequence(null) 21 | } 22 | 23 | val job = CoScopes.sequenceScope.async { definition() } 24 | cancellationToken = CancellationToken({ job.cancel() }) 25 | job.invokeOnCompletion { 26 | bot.setActiveSequence(null) 27 | } 28 | bot.setActiveSequence(this) 29 | job.await() 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/behaviors/sequences/TeleportToLocationSequence.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.behaviors.sequences 2 | 3 | import dev.l2j.autobots.extensions.findClosestGatekeeper 4 | import dev.l2j.autobots.extensions.location 5 | import dev.l2j.autobots.extensions.moveTo 6 | import dev.l2j.autobots.utils.CancellationToken 7 | import dev.l2j.autobots.utils.distance 8 | import kotlinx.coroutines.delay 9 | import net.sf.l2j.commons.random.Rnd 10 | import net.sf.l2j.gameserver.data.xml.TeleportLocationData 11 | import net.sf.l2j.gameserver.enums.ZoneId 12 | import net.sf.l2j.gameserver.model.actor.Player 13 | import net.sf.l2j.gameserver.model.location.Location 14 | 15 | internal class TeleportToLocationSequence(override val bot: Player, private val targetLocation: Location) : Sequence { 16 | 17 | override var cancellationToken: CancellationToken? = null 18 | 19 | override suspend fun definition() { 20 | 21 | if (!bot.isInsideZone(ZoneId.TOWN)) { 22 | return 23 | } 24 | 25 | delay(Rnd.get(5000, 8000).toLong()) 26 | 27 | val closestGatekeeper = bot.findClosestGatekeeper() ?: return 28 | bot.target = closestGatekeeper 29 | bot.moveTo(closestGatekeeper.x, closestGatekeeper.y, closestGatekeeper.z) 30 | while (distance(bot, closestGatekeeper) >= 110) { 31 | 32 | if (bot.isDead) { 33 | return 34 | } 35 | 36 | if (distance(bot, closestGatekeeper) <= 1000) { 37 | closestGatekeeper.onAction(bot) 38 | } 39 | 40 | if (!bot.isMoving) { 41 | 42 | } 43 | delay(Rnd.get(4000, 6000).toLong()) 44 | } 45 | delay(Rnd.get(2000, 4000).toLong()) 46 | 47 | val closestTeleportLocation = TeleportLocationData.getInstance().allTeleportLocations 48 | .filter { !it.isNoble } 49 | .minBy { distance(targetLocation, Location(it.x, it.y, it.z)) } 50 | 51 | bot.teleportTo(closestTeleportLocation, 20) 52 | 53 | delay(Rnd.get(5000, 8000).toLong()) 54 | if (bot.isInsideZone(ZoneId.TOWN)) { 55 | return definition() 56 | } 57 | 58 | bot.moveTo(targetLocation.x, targetLocation.y, targetLocation.z) 59 | while (distance(bot.location(), targetLocation) >= 1500) { 60 | 61 | if (bot.isDead) { 62 | return 63 | } 64 | 65 | if (bot.isInCombat) { 66 | return 67 | } 68 | 69 | if (!bot.isMoving) { 70 | if(!bot.isMoving) { 71 | bot.moveTo(targetLocation.x, targetLocation.y, targetLocation.z) 72 | } 73 | } 74 | 75 | delay(Rnd.get(2000, 4000).toLong()) 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/config/AutobotBuffs.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.config 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty 4 | import net.sf.l2j.gameserver.enums.actors.ClassId 5 | 6 | data class AutobotBuffs(@JsonProperty("classid") val classId: ClassId, @JsonProperty("buffs")val buffsAsString: String){ 7 | val buffsContent : Array = buffsAsString.split(";").map { intArrayOf(it.split(",")[0].toInt(), it.split(",")[1].toInt()) }.toTypedArray() 8 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/config/AutobotEquipment.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.config 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty 4 | import net.sf.l2j.gameserver.enums.actors.ClassId 5 | 6 | data class AutobotEquipment( 7 | @JsonProperty("classid") val classId: ClassId, 8 | @JsonProperty("minLevel") val minLevel: Int, 9 | @JsonProperty("maxLevel") val maxLevel: Int, 10 | @JsonProperty("rhand") val rightHand: Int, 11 | @JsonProperty("lhand") val leftHand: Int, 12 | @JsonProperty("head") val head: Int, 13 | @JsonProperty("chest") val chest: Int, 14 | @JsonProperty("legs") val legs: Int, 15 | @JsonProperty("hands") val hands: Int, 16 | @JsonProperty("feet") val feet: Int, 17 | @JsonProperty("neck") val neck: Int, 18 | @JsonProperty("lear") val leftEar: Int, 19 | @JsonProperty("rear") val rightEar: Int, 20 | @JsonProperty("lring") val leftRing: Int, 21 | @JsonProperty("rring") val rightRing: Int) 22 | -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/config/AutobotLocation.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.config 2 | 3 | import net.sf.l2j.gameserver.model.location.Location 4 | 5 | data class AutobotLocation(val x: Int, val y: Int, val z: Int, val location: Location = Location(x, y, z)) -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/config/AutobotSettings.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.config 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore 4 | import com.fasterxml.jackson.annotation.JsonProperty 5 | import com.fasterxml.jackson.databind.DeserializationFeature 6 | import com.fasterxml.jackson.databind.MapperFeature 7 | import com.fasterxml.jackson.databind.SerializationFeature 8 | import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule 9 | import com.fasterxml.jackson.dataformat.xml.XmlMapper 10 | import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement 11 | import com.fasterxml.jackson.module.kotlin.registerKotlinModule 12 | import dev.l2j.autobots.behaviors.preferences.AttackPlayerType 13 | import dev.l2j.autobots.behaviors.preferences.TargetingPreference 14 | import java.io.File 15 | import java.nio.charset.Charset 16 | 17 | @JacksonXmlRootElement(namespace = "", localName = "settings") 18 | internal data class AutobotSettings( 19 | @JsonProperty("thinkIteration") var iterationDelay: Long, 20 | @JsonProperty("defaultTitle") var defaultTitle: String = "", 21 | @JsonProperty("defaultTargetingRange") var targetingRange: Int, 22 | @JsonProperty("defaultAttackPlayerType") var attackPlayerType: AttackPlayerType, 23 | @JsonProperty("defaultTargetingPreference") var targetingPreference: TargetingPreference, 24 | @JsonProperty("useManaPots") var useManaPots: Boolean = true, 25 | @JsonProperty("useQuickHealingPots") var useQuickHealingPots: Boolean = false, 26 | @JsonProperty("useGreaterHealingPots") var useGreaterHealingPots: Boolean = true, 27 | @JsonProperty("useGreaterCpPots") var useGreaterCpPots: Boolean = true 28 | ){ 29 | @JsonIgnore private val mapper = XmlMapper(JacksonXmlModule().apply { 30 | setDefaultUseWrapper(false)}).registerKotlinModule().configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true) 31 | .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).also { it.enable(SerializationFeature.INDENT_OUTPUT) } 32 | 33 | internal fun save(){ 34 | val content = mapper.writeValueAsString(this) 35 | val header = "\r\n" 36 | File("./data/autobots/config.xml").writeText(header + content, Charset.forName("UTF-8")) 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/config/AutobotSymbol.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.config 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty 4 | import net.sf.l2j.gameserver.enums.actors.ClassId 5 | 6 | data class AutobotSymbol(@JsonProperty("classId") val classId: ClassId, @JsonProperty("symbols")val symbols: String){ 7 | val symbolIds : Array = symbols.split(";").map { it.toInt() }.toTypedArray() 8 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/extensions/AutobotExtensions.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.extensions 2 | 3 | import dev.l2j.autobots.Autobot 4 | import dev.l2j.autobots.utils.getSupportedClasses 5 | import net.sf.l2j.gameserver.enums.actors.ClassId 6 | 7 | 8 | internal fun Autobot.shouldChangeClass(oldLevel: Int, newLevel: Int) : Boolean { 9 | return oldLevel < 20 && newLevel >= 20 || 10 | oldLevel < 40 && newLevel >= 40 || 11 | oldLevel < 76 && newLevel >= 76 12 | } 13 | 14 | internal fun Autobot.getClassLevelForPlayerLevel(level: Int) : Int{ 15 | return when{ 16 | level in 1..19 -> 0 17 | level in 20..39 -> 1 18 | level in 40..75 -> 2 19 | level >= 76 -> 3 20 | else -> 3 21 | } 22 | } 23 | 24 | @OptIn(ExperimentalStdlibApi::class) 25 | internal fun Autobot.getNewClassId(currentClassId: ClassId) : ClassId? { 26 | val classLevels = getClassLevelForPlayerLevel(level) - classId.level() 27 | if(classLevels == 0) 28 | return currentClassId 29 | 30 | val newClassId = (if(currentClassId.level() < 2) ClassId.values().filter { it.parent == currentClassId && getSupportedClasses.contains(it) }.randomOrNull() else ClassId.values().firstOrNull { it.parent == currentClassId }) 31 | ?: return null 32 | 33 | if(newClassId.level() == getClassLevelForPlayerLevel(level)) { 34 | return newClassId 35 | } 36 | 37 | return getNewClassId(newClassId) 38 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/models/AutobotInfo.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.models 2 | 3 | import net.sf.l2j.gameserver.enums.actors.ClassId 4 | 5 | internal data class AutobotInfo(val name: String, val level:Int, val isOnline: Boolean, val classId: ClassId, val botId: Int, val clanId: Int) 6 | 7 | internal data class ScheduledSpawnInfo(val botName: String, val loginTime: String, val logoutTime: String) -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/models/AutobotLoc.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.models 2 | 3 | internal data class AutobotLoc(var x: Int, var y: Int, var z: Int) -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/models/BotChat.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.models 2 | 3 | internal data class BotChat(val chatType: ChatType, val senderName: String, val message: String, val createdDate: Long = System.currentTimeMillis()) -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/models/BotDebugAction.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.models 2 | 3 | enum class BotDebugAction { 4 | VisualizeVision 5 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/models/ChatType.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.models 2 | 3 | internal enum class ChatType { 4 | All, 5 | Hero, 6 | PmReceived, 7 | PmSent, 8 | Shout, 9 | Trade 10 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/models/CreateBotDetails.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.models 2 | 3 | import dev.l2j.autobots.AutobotsNameService 4 | import dev.l2j.autobots.utils.getSupportedClassesForLevel 5 | import net.sf.l2j.commons.random.Rnd 6 | import net.sf.l2j.gameserver.enums.actors.ClassId 7 | import net.sf.l2j.gameserver.enums.actors.ClassRace 8 | import net.sf.l2j.gameserver.enums.actors.Sex 9 | import net.sf.l2j.gameserver.model.actor.player.Appearance 10 | 11 | internal data class CreateBotDetails( 12 | var name: String = AutobotsNameService.getRandomAvailableName(), 13 | var level: Int = 80, 14 | var race: String = "Human", 15 | var classType: String = "Fighter", 16 | var genger: String = "Male", 17 | var hairStyle: String = "Type A", 18 | var hairColor: String = "Type A", 19 | var face: String = "Type A", 20 | var className: String = getSupportedClassesForLevel(level).filter { it.race == textToRace(race) }.random().toString(), 21 | var weaponEnchant: Int = 0, 22 | var armorEnchant: Int = 0, 23 | var jewelEnchant: Int = 0){ 24 | 25 | fun getClassId(): ClassId{ 26 | return ClassId.values().first { it.toString() == className } 27 | } 28 | 29 | fun getAppearance() : Appearance { 30 | return Appearance(textToFace(face), textToHairColor(hairColor), if(genger == "Male" && (hairStyle == "Type F" || hairStyle == "Type G")) 0 else textToHairStyle(hairStyle), textToSex(genger)) 31 | } 32 | 33 | fun getRace(): ClassRace{ 34 | return textToRace(race) 35 | } 36 | 37 | fun randomize(){ 38 | name = AutobotsNameService.getRandomAvailableName() 39 | level = Rnd.get(1, 80) 40 | race = racesForDropdown().random() 41 | classType = if(race == "Dwarf") "Fighter" else listOf("Fighter", "Mystic").random() 42 | genger = listOf("Male", "Female").random() 43 | hairStyle = if(genger == "Male") listOf("Type A", "Type B", "Type C", "Type D", "Type E").random() else listOf("Type A", "Type B", "Type C", "Type D", "Type E", "Type F", "Type G").random() 44 | hairColor = listOf("Type A", "Type B", "Type C", "Type D", "Type E").random() 45 | face = listOf("Type A", "Type B", "Type C", "Type D").random() 46 | className = getSupportedClassesForLevel(level).filter { it.race == textToRace(race) }.random().toString() 47 | } 48 | 49 | companion object{ 50 | fun textToHairColor(text: String): Byte{ 51 | return when(text){ 52 | "Type A" -> 0 53 | "Type B" -> 1 54 | "Type C" -> 2 55 | "Type D" -> 3 56 | "Type E" -> 4 57 | else -> 0 58 | } 59 | } 60 | 61 | fun textToSex(text: String): Sex { 62 | return when(text){ 63 | "Male" -> Sex.MALE 64 | "Female" -> Sex.FEMALE 65 | else -> Sex.MALE 66 | } 67 | } 68 | 69 | fun textToHairStyle(text: String): Byte{ 70 | return when(text){ 71 | "Type A" -> 0 72 | "Type B" -> 1 73 | "Type C" -> 2 74 | "Type D" -> 3 75 | "Type E" -> 4 76 | "Type F" -> 5 77 | "Type G" -> 6 78 | else -> 0 79 | } 80 | } 81 | 82 | fun textToFace(text: String): Byte{ 83 | return when(text){ 84 | "Type A" -> 0 85 | "Type B" -> 1 86 | "Type C" -> 2 87 | "Type D" -> 3 88 | else -> 0 89 | } 90 | } 91 | 92 | fun textToRace(text: String): ClassRace{ 93 | return when(text){ 94 | "Human" -> ClassRace.HUMAN 95 | "Elf" -> ClassRace.ELF 96 | "Dark elf" -> ClassRace.DARK_ELF 97 | "Orc" -> ClassRace.ORC 98 | "Dwarf" -> ClassRace.DWARF 99 | else -> ClassRace.HUMAN 100 | } 101 | } 102 | 103 | fun racesForDropdown() : MutableList { 104 | return mutableListOf("Human", "Elf", "Dark elf", "Orc", "Dwarf") 105 | } 106 | 107 | fun gendersForDropdown() : MutableList { 108 | return mutableListOf("Male", "Female") 109 | } 110 | 111 | fun facesForDropdown() : MutableList { 112 | return mutableListOf("Type A", "Type B", "Type C") 113 | } 114 | 115 | fun hairColorForDropdown() : MutableList { 116 | return mutableListOf("Type A", "Type B", "Type C", "Type D") 117 | } 118 | 119 | fun hairstyleForDropdown() : MutableList{ 120 | return mutableListOf("Type A", "Type B", "Type C", "Type D", "Type E", "Type F", "Type G") 121 | } 122 | 123 | fun classesForDropdown(race: String) : MutableList{ 124 | return when(race){ 125 | "Human", "Elf", "Dark elf", "Orc" -> mutableListOf("Fighter", "Mystic") 126 | "Dwarf" -> mutableListOf("Fighter") 127 | else -> mutableListOf("Fighter") 128 | } 129 | } 130 | } 131 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/models/RespawnAction.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.models 2 | 3 | enum class RespawnAction { 4 | None, 5 | ReturnToDeathLocation, 6 | Logout 7 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/skills/BotSkill.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.skills 2 | 3 | import dev.l2j.autobots.extensions.getCombatBehavior 4 | import dev.l2j.autobots.utils.hasEffect 5 | import net.sf.l2j.gameserver.model.L2Skill 6 | import net.sf.l2j.gameserver.model.actor.Creature 7 | import net.sf.l2j.gameserver.model.actor.Player 8 | 9 | internal class BotSkill(val skillId: Int) { 10 | 11 | var condition: ((Player, L2Skill, Creature?) -> Boolean) = { _, _, _ -> true } 12 | var forceTargetSelf = false 13 | var isTogglableSkill: Boolean = false 14 | 15 | constructor(skillId: Int, isConditionalSkill: Boolean, isTogglableSkill: Boolean, useWhenEffectIsNotPresent:Boolean = false, forceTargetSelf: Boolean = false) : 16 | this(skillId, { player, skill, _ -> 17 | (!isConditionalSkill || (isConditionalSkill && player.getCombatBehavior().validateConditionalSkill(skill))) && 18 | (!isTogglableSkill || (isTogglableSkill && player.getCombatBehavior().skillPreferences.togglableSkills[skillId]!!)) && 19 | (!useWhenEffectIsNotPresent || (useWhenEffectIsNotPresent && !player.hasEffect(skillId))) 20 | }) { 21 | this.isTogglableSkill = isTogglableSkill 22 | this.forceTargetSelf = forceTargetSelf 23 | } 24 | 25 | constructor(skillId: Int, condition: (player: Player, skill: L2Skill, target: Creature?) -> Boolean) : this(skillId){ 26 | this.condition = condition 27 | } 28 | 29 | constructor(skillId: Int, condition: (player: Player, skill: L2Skill, target: Creature?) -> Boolean, isTogglableSkill: Boolean) : this(skillId){ 30 | this.condition = condition 31 | this.isTogglableSkill = isTogglableSkill 32 | } 33 | 34 | constructor(skillId: Int, forceTargetSelf: Boolean = false, condition: (player: Player, skill: L2Skill, target: Creature?) -> Boolean) : this(skillId, condition){ 35 | this.condition = condition 36 | this.forceTargetSelf = forceTargetSelf 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/ui/AdminActions.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.ui 2 | 3 | import dev.l2j.autobots.Autobot 4 | import dev.l2j.autobots.AutobotsManager 5 | import dev.l2j.autobots.CoScopes 6 | import dev.l2j.autobots.behaviors.preferences.* 7 | import dev.l2j.autobots.dao.AutobotsDao 8 | import dev.l2j.autobots.ui.states.BotDetailsViewState 9 | import dev.l2j.autobots.ui.states.ViewStates 10 | import dev.l2j.autobots.ui.tabs.BotDetailsTab 11 | import kotlinx.coroutines.launch 12 | import net.sf.l2j.commons.random.Rnd 13 | import net.sf.l2j.gameserver.data.SkillTable 14 | import net.sf.l2j.gameserver.data.sql.ClanTable 15 | import net.sf.l2j.gameserver.model.actor.Player 16 | 17 | internal object AdminActions { 18 | internal fun createAndSpawnRandomBots(splitCommand: List, activeChar: Player) { 19 | val count = splitCommand.getOrElse(2) { "1" }.toInt() 20 | createAndSpawnRandomAutobots(count, activeChar) 21 | } 22 | 23 | internal fun toggleSitting(bot: Autobot) { 24 | if (bot.isSitting) { 25 | bot.forceStandUp() 26 | } else { 27 | bot.sitDown() 28 | } 29 | } 30 | 31 | internal fun selectBotDetailsTab(activeChar: Player, tab: BotDetailsTab) { 32 | val state = ViewStates.getActiveState(activeChar) 33 | if (state is BotDetailsViewState) { 34 | state.activeTab = tab 35 | } 36 | } 37 | 38 | internal fun removeSkillPreference(splitCommand: List, state: BotDetailsViewState) { 39 | val skillId = splitCommand[4].toInt() 40 | state.activeBot.combatBehavior.skillPreferences.skillUsageConditions.removeAll { it.skillId == skillId } 41 | AutobotsDao.saveSkillPreferences(state.activeBot) 42 | } 43 | 44 | internal fun removeSelectedBotsFromClan(activeChar: Player) { 45 | ViewStates.indexViewState(activeChar).selectedBots.forEach { 46 | val bot = AutobotsManager.getBotFromOnlineOrDb(it.key) ?: return@forEach 47 | 48 | if (bot.clan == null) return@forEach 49 | 50 | if (bot.isClanLeader) { 51 | if (bot.clan.allyId != 0) { 52 | activeChar.sendMessage("You cannot delete a clan in an ally. Delete the ally first.") 53 | return@forEach 54 | } 55 | 56 | ClanTable.getInstance().destroyClan(bot.clan) 57 | return@forEach 58 | } 59 | 60 | AutobotsDao.removeClanMember(bot, bot.clan) 61 | if (!bot.isOnline) { 62 | AutobotsDao.saveAutobot(bot) 63 | } 64 | } 65 | } 66 | 67 | internal fun saveSkillUsageCondition(splitCommand: List, state: BotDetailsViewState, statusCondition: StatusCondition, comparisonCondition: ComparisonCondition, conditionValueType: ConditionValueType, targetCondition: TargetCondition, value: Int) { 68 | val skillName = splitCommand.subList(9, splitCommand.size).joinToString(" ") 69 | val skillId = state.activeBot.combatBehavior.conditionalSkills.filter { SkillTable.getInstance().getInfo(it, 1).name == skillName }.map { it }.first() 70 | val skillUsageCondition = SkillUsageCondition(skillId, statusCondition, comparisonCondition, conditionValueType, targetCondition, value) 71 | 72 | if (splitCommand[3] == "s") { 73 | state.activeBot.combatBehavior.skillPreferences.skillUsageConditions.removeAll { it.skillId == skillId } 74 | } 75 | 76 | state.activeBot.combatBehavior.skillPreferences.skillUsageConditions.add(skillUsageCondition) 77 | AutobotsDao.saveSkillPreferences(state.activeBot) 78 | state.skillUnderEdit = 0 79 | } 80 | 81 | internal fun setCurrentPagination(splitCommand: List, pageNumberIndex: Int, pageSizeIndex: Int): Pair { 82 | val pageNumber = splitCommand[pageNumberIndex].toInt() 83 | val pageSize = splitCommand[pageSizeIndex].toInt() 84 | return Pair(pageNumber, pageSize) 85 | } 86 | 87 | internal fun despawnBotsInRadius(activeChar: Player, radius: String) { 88 | val botsInRadius = activeChar.getKnownTypeInRadius(Autobot::class.java, radius.toInt()) 89 | CoScopes.massDespawnerScope.launch { 90 | for (bot in botsInRadius) { 91 | 92 | despawnAutobot(bot) 93 | } 94 | } 95 | } 96 | 97 | internal fun createAndSpawnRandomAutobots(count: Int, activeChar: Player) { 98 | CoScopes.generalScope.launch { 99 | for (i in 1..count) { 100 | CoScopes.massSpawnerScope.launch { 101 | AutobotsManager.createAndSpawnAutobot(activeChar.x + Rnd.get(-150, 150), activeChar.y + Rnd.get(-150, 150), activeChar.z) 102 | } 103 | } 104 | } 105 | } 106 | 107 | internal fun despawnAutobot(autobot: Autobot?) { 108 | autobot?.despawn() 109 | } 110 | } -------------------------------------------------------------------------------- /src/main/kotlin/dev/l2j/autobots/ui/AutofarmUi.kt: -------------------------------------------------------------------------------- 1 | package dev.l2j.autobots.ui 2 | 3 | import dev.l2j.autobots.AutobotsNameService 4 | import dev.l2j.autobots.autofarm.AutofarmManager 5 | import net.sf.l2j.gameserver.model.actor.Player 6 | import net.sf.l2j.gameserver.network.serverpackets.TutorialCloseHtml 7 | import net.sf.l2j.gameserver.network.serverpackets.TutorialShowHtml 8 | 9 | internal object AutofarmUi { 10 | 11 | private fun readFileText(fileName: String) = AutobotsNameService.javaClass.classLoader.getResource(fileName)!!.readText() 12 | 13 | fun index(player: Player) { 14 | val html = readFileText("views/autofarm_main.htv") 15 | .replace("{{startstopcmd}}", if(AutofarmManager.isAutoFarming(player)) "stop" else "start") 16 | .replace("{{startstoptext}}", if(AutofarmManager.isAutoFarming(player)) "Stop" else "Start") 17 | .replace("{{closebtn}}", if(AutofarmManager.isAutoFarming(player)) "" else "