New server config option to preload the world map on boot, removes lag caused by lazy loading (server.preload_map = true)
Cached region clipping flags for faster lookups Minor optimizations to setAttribute codepath which avoids unnecessary checks Fixed a bug that would allow entities to attack through walls Fixed two separate bugs that would cause odd behavior attacking large entities from certain angles Removed unnecessary schema from global.sql Ensured that all but the `members` and `worlds` tables could be safely dropped out of the DB Better automatic handling for creating the default server account and creating the default server clan Fixed bugs related to interfaces flagged as uncloseable that would cause stack overflows Fixed premature home teleport while in tutorial Fixed getting stuck by going back up ladder in tutorial Fixed bug that prevented bots from taking damage Fixed a bug where players would not be in the default clan after completion of the tutorial Green Dragon bots reintroduced, no longer buy any items (these bots sell loot from green dragons in the wilderness on the GE)
This commit is contained in:
@@ -217,5 +217,8 @@ class ServerConstants {
|
||||
|
||||
@JvmField
|
||||
var DISCORD_GE_WEBHOOK = ""
|
||||
|
||||
@JvmField
|
||||
var PRELOAD_MAP = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@ import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.game.world.update.flag.context.ChatMessage
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import core.game.world.update.flag.player.ChatFlag
|
||||
import core.tools.RandomFunction
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -99,6 +101,11 @@ class ScriptAPI(private val bot: Player) {
|
||||
return entity
|
||||
}
|
||||
|
||||
fun sendChat(message: String) {
|
||||
bot.sendChat(message)
|
||||
bot.updateMasks.register(ChatFlag(ChatMessage(bot, message, 0, 0)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nearest node with a name contained in the list of acceptable names
|
||||
* @param acceptedNames the list of accepted npc/object names
|
||||
@@ -422,7 +429,10 @@ class ScriptAPI(private val bot: Player) {
|
||||
* A function for teleporting the bot to the GE
|
||||
* @author Ceikry
|
||||
*/
|
||||
fun teleportToGE(){
|
||||
fun teleportToGE() : Boolean{
|
||||
if (bot.isTeleBlocked) {
|
||||
return false
|
||||
}
|
||||
bot.lock()
|
||||
bot.visualize(ANIMATIONUP, GRAPHICSUP)
|
||||
bot.impactHandler.disabledTicks = 4
|
||||
@@ -435,6 +445,7 @@ class ScriptAPI(private val bot: Player) {
|
||||
return true
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -548,7 +559,10 @@ class ScriptAPI(private val bot: Player) {
|
||||
* @param loc the location to teleport to
|
||||
* @author Ceikry
|
||||
*/
|
||||
fun teleport(loc: Location){
|
||||
fun teleport(loc: Location) : Boolean {
|
||||
if (bot.isTeleBlocked) {
|
||||
return false
|
||||
}
|
||||
bot.lock()
|
||||
bot.visualize(ANIMATIONUP, GRAPHICSUP)
|
||||
bot.impactHandler.disabledTicks = 4
|
||||
@@ -561,6 +575,7 @@ class ScriptAPI(private val bot: Player) {
|
||||
return true
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -457,8 +457,7 @@ class Adventurer(val style: CombatStyle): Script() {
|
||||
.replace("@name", localPlayer.username)
|
||||
.replace("@timer", until.toString())
|
||||
|
||||
bot.sendChat(chat)
|
||||
bot.updateMasks.register(ChatFlag(ChatMessage(bot, chat, 0, 0)))
|
||||
scriptAPI.sendChat(chat)
|
||||
}
|
||||
|
||||
enum class State{
|
||||
|
||||
@@ -8,6 +8,7 @@ import core.game.node.entity.combat.CombatStyle
|
||||
import core.game.node.entity.combat.InteractionType
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.entity.skill.prayer.BoneBuryingOptionPlugin
|
||||
import core.game.node.entity.state.EntityState
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.task.Pulse
|
||||
@@ -15,6 +16,7 @@ import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
import core.game.world.map.zone.impl.WildernessZone
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import rs09.game.ai.AIRepository
|
||||
import rs09.game.ai.pvmbots.CombatBotAssembler
|
||||
@@ -25,16 +27,24 @@ import rs09.game.node.entity.combat.handlers.RangeSwingHandler
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* A bot script for killing green dragons in the wilderness.. Capable of banking, selling on ge, buying on ge, eating and more.
|
||||
* A bot script for killing green dragons in the wilderness.. Capable of banking, selling on ge, eating, trash talking, buries bones when fleeing and more.
|
||||
* @param style The combat style the bot is going to use.
|
||||
* @param area (optional) What area the bot tries to kill dragons in.
|
||||
* @author Ceikry
|
||||
*/
|
||||
class GreenDragonKiller(val style: CombatStyle, area: ZoneBorders? = null) : Script() {
|
||||
var state = State.KILLING
|
||||
companion object {
|
||||
val westDragons = ZoneBorders(2971,3606,2991,3628)
|
||||
val wildernessLine = ZoneBorders(3078,3523,3096,3523)
|
||||
val edgevilleLine = ZoneBorders(3078,3520,3096,3520)
|
||||
val bankZone = ZoneBorders(3092,3489,3094,3493)
|
||||
val trashTalkLines = arrayOf("Bro, seriously?", "Ffs.", "Jesus christ.", "????", "Friendly!", "Get a life dude", "Do you mind??? lol", "Lol.", "Kek.", "One sec burying all the bones.", "Yikes.", "Yeet", "Ah shit, here we go again.", "Cmonnnn", "Plz", "Do you have nothing better to do?", "Cmon bro pls", "I just need to get my prayer up bro jesus", "Reeeeeee", "I cant believe you've done this", "Really m8", "Zomg", "Aaaaaaaaaaaaaaaaaaaaa", "Rofl.", "Oh god oh fuck oh shit", "....", ":|", "A q p", "Hcim btw", "I hope the revenants kill your mum", "Wrap your ass titties", "Why do this", "Bruh", "Straight sussin no cap fr fr", "This ain't bussin dawg", "Really bro?")
|
||||
}
|
||||
var state = State.TO_BANK
|
||||
var handler: CombatSwingHandler? = null
|
||||
var lootDelay = 0
|
||||
var offerMade = false
|
||||
var trashTalkDelay = 0
|
||||
|
||||
var food = if (Random.nextBoolean()){
|
||||
Items.LOBSTER_379
|
||||
@@ -45,28 +55,18 @@ class GreenDragonKiller(val style: CombatStyle, area: ZoneBorders? = null) : Scr
|
||||
}
|
||||
|
||||
var myBorders: ZoneBorders? = null
|
||||
val type = when(style){
|
||||
CombatStyle.MELEE -> CombatBotAssembler.Type.MELEE
|
||||
CombatStyle.MAGIC -> CombatBotAssembler.Type.MAGE
|
||||
CombatStyle.RANGE -> CombatBotAssembler.Type.RANGE
|
||||
}
|
||||
val type = CombatBotAssembler.Type.MELEE
|
||||
|
||||
val westDragons = ZoneBorders(2971,3606,2991,3628)
|
||||
val wildernessLine = ZoneBorders(3078,3523,3096,3523)
|
||||
val edgevilleLine = ZoneBorders(3078,3520,3096,3520)
|
||||
val bankZone = ZoneBorders(3092,3489,3094,3493)
|
||||
override fun tick() {
|
||||
if(!bot.isActive){
|
||||
running = false
|
||||
return
|
||||
}
|
||||
if(bot.inventory.getAmount(food) < 3 && state == State.KILLING)
|
||||
state = State.TO_BANK
|
||||
scriptAPI.eat(food)
|
||||
|
||||
checkFoodStockAndEat()
|
||||
|
||||
when(state){
|
||||
|
||||
|
||||
|
||||
State.KILLING -> {
|
||||
bot.properties.combatPulse.temporaryHandler = handler
|
||||
scriptAPI.attackNpcInRadius(bot,"Green dragon",20)
|
||||
@@ -86,11 +86,13 @@ class GreenDragonKiller(val style: CombatStyle, area: ZoneBorders? = null) : Scr
|
||||
if(players.isEmpty()){
|
||||
state = State.TO_DRAGONS
|
||||
} else {
|
||||
if(bot.skullManager.level < 21 && bot.stateManager.get(EntityState.TELEBLOCK) != null){
|
||||
scriptAPI.teleportToGE()
|
||||
state = State.REFRESHING
|
||||
if(bot.skullManager.level < 21){
|
||||
if (scriptAPI.teleportToGE())
|
||||
state = State.REFRESHING
|
||||
return
|
||||
}
|
||||
sendTrashTalk()
|
||||
attemptToBuryBone()
|
||||
scriptAPI.walkTo(WildernessZone.getInstance().borders.random().randomLoc)
|
||||
}
|
||||
}
|
||||
@@ -107,7 +109,7 @@ class GreenDragonKiller(val style: CombatStyle, area: ZoneBorders? = null) : Scr
|
||||
}
|
||||
return
|
||||
}
|
||||
items.forEach {it: Item -> scriptAPI.takeNearestGroundItem(it.id)}
|
||||
items.toTypedArray().forEach {it: Item -> scriptAPI.takeNearestGroundItem(it.id)}
|
||||
}
|
||||
|
||||
State.TO_BANK -> {
|
||||
@@ -157,25 +159,10 @@ class GreenDragonKiller(val style: CombatStyle, area: ZoneBorders? = null) : Scr
|
||||
}
|
||||
|
||||
State.BUYING_FOOD -> {
|
||||
if(!offerMade)
|
||||
{
|
||||
scriptAPI.buyFromGE(bot, food, 100)
|
||||
offerMade = true
|
||||
} else
|
||||
{
|
||||
val offer = AIRepository.getOffer(bot)
|
||||
if (offer == null) {
|
||||
offerMade = false
|
||||
} else {
|
||||
if (offer.completedAmount == offer.amount) {
|
||||
state = State.TO_DRAGONS
|
||||
offer.offerState = OfferState.REMOVED
|
||||
bot.bank.add(Item(offer.itemID, offer.completedAmount))
|
||||
bot.bank.refresh()
|
||||
scriptAPI.withdraw(food, 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
state = State.TO_DRAGONS
|
||||
bot.bank.add(Item(food,50))
|
||||
bot.bank.refresh()
|
||||
scriptAPI.withdraw(food, 10)
|
||||
}
|
||||
|
||||
State.TO_DRAGONS -> {
|
||||
@@ -236,13 +223,29 @@ class GreenDragonKiller(val style: CombatStyle, area: ZoneBorders? = null) : Scr
|
||||
}
|
||||
}
|
||||
|
||||
private fun attemptToBuryBone() {
|
||||
if (bot.inventory.containsAtLeastOneItem(Items.DRAGON_BONES_536)) {
|
||||
BoneBuryingOptionPlugin().handle(bot, bot.inventory.get(Item(Items.DRAGON_BONES_536)), "bury")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkFoodStockAndEat() {
|
||||
if (bot.inventory.getAmount(food) < 3 && state == State.KILLING)
|
||||
state = State.TO_BANK
|
||||
scriptAPI.eat(food)
|
||||
}
|
||||
|
||||
private fun sendTrashTalk() {
|
||||
if (trashTalkDelay-- == 0)
|
||||
scriptAPI.sendChat(trashTalkLines.random())
|
||||
else
|
||||
trashTalkDelay = RandomFunction.random(10, 30)
|
||||
}
|
||||
|
||||
override fun newInstance(): Script {
|
||||
val script = GreenDragonKiller(style)
|
||||
val tier = CombatBotAssembler.Tier.HIGH
|
||||
if(type == CombatBotAssembler.Type.RANGE)
|
||||
script.bot = CombatBotAssembler().assembleRangeDragonBot(tier,bot.startLocation)
|
||||
else
|
||||
script.bot = CombatBotAssembler().assembleMeleeDragonBot(tier, bot.startLocation)
|
||||
val tier = CombatBotAssembler.Tier.MED
|
||||
script.bot = CombatBotAssembler().assembleMeleeDragonBot(tier, bot.startLocation)
|
||||
return script
|
||||
}
|
||||
|
||||
@@ -262,11 +265,7 @@ class GreenDragonKiller(val style: CombatStyle, area: ZoneBorders? = null) : Scr
|
||||
}
|
||||
|
||||
init {
|
||||
handler = when(style){
|
||||
CombatStyle.MELEE -> MeleeSwinger(this)
|
||||
CombatStyle.MAGIC -> MageSwinger(this)
|
||||
CombatStyle.RANGE -> RangeSwinger(this)
|
||||
}
|
||||
handler = MeleeSwinger(this)
|
||||
equipment.add(Item(Items.ANTI_DRAGON_SHIELD_1540))
|
||||
myBorders = westDragons
|
||||
skills[Skills.AGILITY] = 99
|
||||
@@ -276,22 +275,10 @@ class GreenDragonKiller(val style: CombatStyle, area: ZoneBorders? = null) : Scr
|
||||
|
||||
internal class MeleeSwinger(val script: GreenDragonKiller) : MeleeSwingHandler() {
|
||||
override fun canSwing(entity: Entity, victim: Entity): InteractionType? {
|
||||
if(script.state == State.TO_BANK) {script.bot.pulseManager.current.stop()}
|
||||
if(victim is Player) {script.state = State.RUNNING; script.bot.pulseManager.current.stop()}
|
||||
return super.canSwing(entity, victim)
|
||||
}
|
||||
}
|
||||
|
||||
internal class MageSwinger(val script: GreenDragonKiller) : MagicSwingHandler() {
|
||||
override fun canSwing(entity: Entity, victim: Entity): InteractionType? {
|
||||
if(victim is Player) {script.state = State.RUNNING; script.bot.pulseManager.current.stop()}
|
||||
return super.canSwing(entity, victim)
|
||||
}
|
||||
}
|
||||
|
||||
internal class RangeSwinger(val script: GreenDragonKiller) : RangeSwingHandler() {
|
||||
override fun canSwing(entity: Entity, victim: Entity): InteractionType? {
|
||||
if(victim is Player) {script.state = State.RUNNING; script.bot.pulseManager.current.stop()}
|
||||
if(victim is Player || victim.name.contains("revenant", ignoreCase = true)) {
|
||||
script.state = State.RUNNING
|
||||
script.bot.pulseManager.current.stop()
|
||||
}
|
||||
return super.canSwing(entity, victim)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@ import core.game.content.dialogue.FacialExpression
|
||||
import core.game.content.global.action.ClimbActionHandler
|
||||
import core.game.content.global.action.DoorActionHandler
|
||||
import core.game.node.scenery.Scenery
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.world.map.Location
|
||||
import org.rs09.consts.NPCs
|
||||
import rs09.game.interaction.InteractionListener
|
||||
import rs09.game.world.repository.Repository
|
||||
|
||||
/**
|
||||
* Handles tutorial-specific node interactions
|
||||
@@ -19,6 +21,7 @@ class TutorialListeners : InteractionListener {
|
||||
val COOKS_EXIT = 3018
|
||||
val QUEST_ENTER = 3019
|
||||
val QUEST_LADDER = 3029
|
||||
val QUEST_EXIT_LADDER = 3028
|
||||
val COMBAT_EXIT = 3030
|
||||
val BANK_EXIT = 3024
|
||||
val FINANCE_EXIT = 3025
|
||||
@@ -80,14 +83,30 @@ class TutorialListeners : InteractionListener {
|
||||
}
|
||||
|
||||
on(QUEST_LADDER, SCENERY, "climb-down") {player, ladder ->
|
||||
if(getAttribute(player, "tutorial:stage", 0) != 29)
|
||||
if(getAttribute(player, "tutorial:stage", 0) < 29)
|
||||
return@on true
|
||||
|
||||
setAttribute(player, "tutorial:stage", 30)
|
||||
TutorialStage.load(player, 30)
|
||||
if (getAttribute(player, "tutorial:stage", 0) == 29) {
|
||||
setAttribute(player, "tutorial:stage", 30)
|
||||
TutorialStage.load(player, 30)
|
||||
}
|
||||
ClimbActionHandler.climbLadder(player, ladder.asScenery(), "climb-down")
|
||||
}
|
||||
|
||||
on(QUEST_EXIT_LADDER, SCENERY, "climb-up") { player, ladder ->
|
||||
ClimbActionHandler.climbLadder(player, ladder.asScenery(), "climb-up")
|
||||
|
||||
submitWorldPulse(object : Pulse(2) {
|
||||
override fun pulse(): Boolean {
|
||||
val questTutor = Repository.findNPC(NPCs.QUEST_GUIDE_949) ?: return true
|
||||
sendChat(questTutor, "What are you doing, ${player.username}? Get back down the ladder.")
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
return@on true
|
||||
}
|
||||
|
||||
on(COMBAT_GATES, SCENERY, "open"){player, gate ->
|
||||
if(getAttribute(player, "tutorial:stage", 0) != 43)
|
||||
return@on true
|
||||
|
||||
@@ -10,15 +10,19 @@ import core.game.node.entity.player.link.InterfaceManager
|
||||
import core.game.node.entity.player.link.IronmanMode
|
||||
import core.game.node.entity.player.link.TeleportManager
|
||||
import core.game.node.item.Item
|
||||
import core.game.system.communication.ClanRepository
|
||||
import core.game.world.map.Location
|
||||
import core.net.amsc.MSPacketRepository
|
||||
import core.net.amsc.WorldCommunicator
|
||||
import core.plugin.Initializable
|
||||
import org.rs09.consts.Items
|
||||
import org.rs09.consts.NPCs
|
||||
import proto.management.JoinClanRequest
|
||||
import rs09.ServerConstants
|
||||
import rs09.game.interaction.inter.RulesAndInfo
|
||||
import rs09.game.world.GameWorld
|
||||
import rs09.tools.END_DIALOGUE
|
||||
import rs09.worker.ManagementEvents
|
||||
|
||||
/**
|
||||
* Handles the magic tutor's dialogue
|
||||
@@ -179,6 +183,16 @@ class TutorialMagicTutorDialogue(player: Player? = null) : DialoguePlugin(player
|
||||
player.unhook(TutorialInteractionReceiver)
|
||||
player.unhook(TutorialButtonReceiver)
|
||||
RulesAndInfo.openFor(player)
|
||||
|
||||
if (GameWorld.settings!!.enable_default_clan) {
|
||||
player.communication.currentClan = ServerConstants.SERVER_NAME
|
||||
|
||||
val clanJoin = JoinClanRequest.newBuilder()
|
||||
clanJoin.clanName = ServerConstants.SERVER_NAME
|
||||
clanJoin.username = player.name
|
||||
|
||||
ManagementEvents.publish(clanJoin.build())
|
||||
}
|
||||
}
|
||||
|
||||
12 -> {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package rs09.game.node.entity.combat
|
||||
|
||||
import core.game.component.Component
|
||||
import core.game.container.Container
|
||||
import core.game.container.impl.EquipmentContainer
|
||||
import core.game.node.Node
|
||||
import core.game.node.entity.Entity
|
||||
@@ -15,8 +14,12 @@ import core.game.node.entity.player.link.audio.Audio
|
||||
import core.game.node.entity.player.link.prayer.PrayerType
|
||||
import core.game.node.entity.skill.Skills
|
||||
import core.game.node.entity.skill.summoning.familiar.Familiar
|
||||
import core.game.world.map.Direction
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.RegionManager.getClippingFlag
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import core.game.world.map.path.Pathfinder.*
|
||||
import core.game.world.update.flag.context.Animation
|
||||
import core.tools.RandomFunction
|
||||
import rs09.game.system.SystemLogger
|
||||
@@ -207,6 +210,11 @@ abstract class CombatSwingHandler(var type: CombatStyle?) {
|
||||
* @return `True` if so.
|
||||
*/
|
||||
open fun isAttackable(entity: Entity, victim: Entity): InteractionType? {
|
||||
if (type == CombatStyle.MELEE) {
|
||||
val stepType = canStepTowards(entity, victim)
|
||||
if (stepType != InteractionType.STILL_INTERACT) return stepType
|
||||
}
|
||||
|
||||
val comp = entity.getAttribute("autocast_component",null) as Component?
|
||||
if((comp != null || type == CombatStyle.MAGIC) && (entity.properties.autocastSpell == null || entity.properties.autocastSpell.spellId == 0) && entity is Player){
|
||||
val weapEx = entity.getExtension<Any>(WeaponInterface::class.java) as WeaponInterface?
|
||||
@@ -235,6 +243,74 @@ abstract class CombatSwingHandler(var type: CombatStyle?) {
|
||||
return InteractionType.STILL_INTERACT
|
||||
}
|
||||
|
||||
private fun canStepTowards(entity: Entity, victim: Entity): InteractionType {
|
||||
val closestVictimTile = victim.getClosestOccupiedTile(entity.location)
|
||||
val closestEntityTile = entity.getClosestOccupiedTile(closestVictimTile)
|
||||
val dir = closestEntityTile.deriveDirection(closestVictimTile)
|
||||
?: return InteractionType.STILL_INTERACT //if we cannot derive a direction, it's because both tiles are the same, so hand off control to the main logic which already handles this case
|
||||
var next = closestEntityTile
|
||||
|
||||
while (next.getDistance(closestVictimTile) > 3) { //skip the initial gap in distance if it exists, because standard pathfinding would already stop us before this point if something was between us and the NPC or vice versa
|
||||
next = next.transform(dir)
|
||||
}
|
||||
|
||||
var result: InteractionType = InteractionType.STILL_INTERACT
|
||||
val maxIterations = next.getDistance(closestVictimTile).toInt()
|
||||
for (i in 0..maxIterations) { //step towards the target tile, checking if anything would obstruct us on the way, and immediately breaking + returning if it does.
|
||||
next = next.transform(dir)
|
||||
result = checkStepInterval(dir, next)
|
||||
if (result == InteractionType.NO_INTERACT) break
|
||||
}
|
||||
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun checkStepInterval(
|
||||
dir: Direction,
|
||||
next: Location
|
||||
): InteractionType {
|
||||
val components = next.getStepComponents(dir)
|
||||
|
||||
when (dir) {
|
||||
Direction.NORTH -> if (getClippingFlag(next) and PREVENT_NORTH != 0) return InteractionType.NO_INTERACT
|
||||
Direction.EAST -> if (getClippingFlag(next) and PREVENT_EAST != 0) return InteractionType.NO_INTERACT
|
||||
Direction.SOUTH -> if (getClippingFlag(next) and PREVENT_SOUTH != 0) return InteractionType.NO_INTERACT
|
||||
Direction.WEST -> if (getClippingFlag(next) and PREVENT_WEST != 0) return InteractionType.NO_INTERACT
|
||||
|
||||
Direction.NORTH_EAST -> {
|
||||
if (getClippingFlag(components[0]) and PREVENT_EAST != 0
|
||||
|| getClippingFlag(components[1]) and PREVENT_NORTH != 0
|
||||
|| getClippingFlag(next) and PREVENT_NORTHEAST != 0
|
||||
) return InteractionType.NO_INTERACT
|
||||
}
|
||||
|
||||
Direction.NORTH_WEST -> {
|
||||
if (getClippingFlag(components[0]) and PREVENT_WEST != 0
|
||||
|| getClippingFlag(components[1]) and PREVENT_NORTH != 0
|
||||
|| getClippingFlag(next) and PREVENT_NORTHWEST != 0
|
||||
) return InteractionType.NO_INTERACT
|
||||
}
|
||||
|
||||
Direction.SOUTH_EAST -> {
|
||||
if (getClippingFlag(components[0]) and PREVENT_EAST != 0
|
||||
|| getClippingFlag(components[1]) and PREVENT_SOUTH != 0
|
||||
|| getClippingFlag(next) and PREVENT_SOUTHEAST != 0
|
||||
) return InteractionType.NO_INTERACT
|
||||
}
|
||||
|
||||
Direction.SOUTH_WEST -> {
|
||||
if (getClippingFlag(components[0]) and PREVENT_WEST != 0
|
||||
|| getClippingFlag(components[1]) and PREVENT_SOUTH != 0
|
||||
|| getClippingFlag(next) and PREVENT_SOUTHWEST != 0
|
||||
) return InteractionType.NO_INTERACT
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return InteractionType.STILL_INTERACT
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the dragonfire message.
|
||||
* @param protection The protection value.
|
||||
|
||||
@@ -55,6 +55,9 @@ class ModernListeners : SpellListener("modern"){
|
||||
override fun defineListeners() {
|
||||
|
||||
onCast(Modern.HOME_TELEPORT,NONE){player, _ ->
|
||||
if (!getAttribute(player, "tutorial:complete", false)) {
|
||||
return@onCast
|
||||
}
|
||||
requires(player)
|
||||
player.teleporter.send(ServerConstants.HOME_LOCATION,TeleportManager.TeleportType.HOME)
|
||||
setDelay(player,true)
|
||||
|
||||
@@ -115,6 +115,7 @@ object ServerConfigParser {
|
||||
ServerConstants.SERVER_GE_NAME = data.getString("world.name_ge") ?: ServerConstants.SERVER_NAME
|
||||
ServerConstants.RULES_AND_INFO_ENABLED = data.getBoolean("world.show_rules", true)
|
||||
ServerConstants.BOTS_INFLUENCE_PRICE_INDEX = data.getBoolean("world.bots_influence_ge_price", true)
|
||||
ServerConstants.PRELOAD_MAP = data.getBoolean("server.preload_map", false)
|
||||
ServerConstants.REVENANT_POPULATION = data.getLong("world.revenant_population", 30L).toInt()
|
||||
ServerConstants.BANK_BOOTH_QUICK_OPEN = data.getBoolean("world.bank_booth_quick_open", false)
|
||||
ServerConstants.DISCORD_GE_WEBHOOK = data.getString("server.discord_webhook", "")
|
||||
|
||||
@@ -9,6 +9,7 @@ import core.game.system.SystemState
|
||||
import core.game.system.task.Pulse
|
||||
import core.game.system.task.TaskExecutor
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.Region
|
||||
import core.game.world.map.RegionManager
|
||||
import core.plugin.CorePluginTypes.StartupPlugin
|
||||
import core.tools.RandomFunction
|
||||
@@ -179,6 +180,12 @@ object GameWorld {
|
||||
SystemManager.flag(if (settings?.isDevMode == true) SystemState.PRIVATE else SystemState.ACTIVE)
|
||||
}
|
||||
SceneryDefinition.getDefinitions().values.forEach(Consumer { obj: SceneryDefinition -> obj.examine })
|
||||
|
||||
if (ServerConstants.PRELOAD_MAP) {
|
||||
//force early loading of all commonly accessed regions to improve performance at the cost of memory usage
|
||||
(7483..15420).forEach { id -> RegionManager.forId(id).also { Region.load(it) } }
|
||||
}
|
||||
|
||||
System.gc()
|
||||
SystemLogger.initTradeLogger()
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class ImmerseWorld : StartupListener {
|
||||
immerseSeersAndCatherby()
|
||||
immerseLumbridgeDraynor()
|
||||
immerseVarrock()
|
||||
// immerseWilderness() temp disabled due to unbalanced exchange rates
|
||||
immerseWilderness()
|
||||
immerseFishingGuild()
|
||||
immerseAdventurer()
|
||||
// immerseSlayer()
|
||||
@@ -193,20 +193,13 @@ class ImmerseWorld : StartupListener {
|
||||
}
|
||||
|
||||
fun immerseWilderness() {
|
||||
val wilderness = Location.create(2979, 3603, 0)
|
||||
for (i in (0..1)) {
|
||||
GeneralBotCreator(
|
||||
GreenDragonKiller(CombatStyle.MELEE),
|
||||
assembler.assembleMeleeDragonBot(CombatBotAssembler.Tier.HIGH, wilderness)
|
||||
)
|
||||
GeneralBotCreator(
|
||||
val wilderness = Location.create(3092, 3493, 0)
|
||||
|
||||
repeat(6) {
|
||||
GeneralBotCreator (
|
||||
GreenDragonKiller(CombatStyle.MELEE),
|
||||
assembler.assembleMeleeDragonBot(CombatBotAssembler.Tier.MED, wilderness)
|
||||
)
|
||||
GeneralBotCreator(
|
||||
GreenDragonKiller(CombatStyle.RANGE),
|
||||
assembler.assembleRangedBot(CombatBotAssembler.Tier.HIGH, wilderness)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ class MajorUpdateWorker {
|
||||
|
||||
//remove all null or finished pulses from the list
|
||||
rmlist.forEach {
|
||||
if (GameWorld.Pulser.TASKS.contains(it)) GameWorld.Pulser.TASKS.remove(it)
|
||||
GameWorld.Pulser.TASKS.remove(it)
|
||||
}
|
||||
|
||||
rmlist.clear()
|
||||
|
||||
@@ -30,6 +30,8 @@ import proto.management.SendClanInfo
|
||||
import proto.management.SendClanInfo.ClanMember
|
||||
import proto.management.SendContactInfo
|
||||
import proto.management.SendContactInfo.Contact
|
||||
import rs09.ServerConstants
|
||||
import rs09.auth.UserAccountInfo
|
||||
import rs09.game.system.SystemLogger
|
||||
import rs09.game.world.GameWorld
|
||||
import rs09.game.world.repository.Repository
|
||||
@@ -262,40 +264,29 @@ object ManagementEvents {
|
||||
|
||||
is SendClanInfo -> {
|
||||
if (event.hasInfo) {
|
||||
val clan = ClanRepository.getClans().getOrPut(event.clanOwner) { ClanRepository(event.clanOwner) }
|
||||
clan.name = event.clanName
|
||||
clan.joinRequirement = ClanRank.values()[event.joinRequirement]
|
||||
clan.kickRequirement = ClanRank.values()[event.kickRequirement]
|
||||
clan.messageRequirement = ClanRank.values()[event.messageRequirement]
|
||||
clan.lootRequirement = ClanRank.values()[event.lootRequirement]
|
||||
|
||||
for (member in event.membersList) {
|
||||
val entry = ClanEntry(member.username, member.world)
|
||||
clan.ranks[member.username] = ClanRank.values()[member.rank]
|
||||
if (member.world == GameWorld.settings!!.worldId) {
|
||||
val p = Repository.getPlayerByName(member.username)
|
||||
entry.player = p
|
||||
p?.communication?.clan = clan
|
||||
}
|
||||
clan.players.add(entry)
|
||||
}
|
||||
|
||||
clan.update()
|
||||
initializeClanFrom(event)
|
||||
} else {
|
||||
val info = GameWorld.accountStorage.getAccountInfo(event.clanOwner)
|
||||
var info = GameWorld.accountStorage.getAccountInfo(event.clanOwner)
|
||||
if (info.clanName.isNotEmpty()) {
|
||||
val reqs = CommunicationInfo.parseClanRequirements(info.clanReqs)
|
||||
val c = ClanRepository(event.clanOwner)
|
||||
val contacts = CommunicationInfo.parseContacts(info.contacts)
|
||||
c.name = info.clanName
|
||||
c.joinRequirement = reqs[0]
|
||||
c.messageRequirement = reqs[1]
|
||||
c.kickRequirement = reqs[2]
|
||||
c.lootRequirement = reqs[3]
|
||||
for ((username, contact) in contacts) {
|
||||
c.ranks[username] = contact.rank
|
||||
initializeClanWith(info)
|
||||
} else {
|
||||
SystemLogger.logMS("Creating default server clan")
|
||||
if (GameWorld.settings!!.enable_default_clan && event.clanOwner == ServerConstants.SERVER_NAME) {
|
||||
//Create a user with the default clan and some basic settings and stick them in the account storage
|
||||
if (info == UserAccountInfo.createDefault()) {
|
||||
info.username = ServerConstants.SERVER_NAME
|
||||
info.password = ServerConstants.MS_SECRET_KEY
|
||||
info.rights = 2
|
||||
SystemLogger.logAlert("Creating default server account: ${info.username}, password is your MS_SECRET_KEY!")
|
||||
GameWorld.authenticator.createAccountWith(info)
|
||||
info = GameWorld.accountStorage.getAccountInfo(event.clanOwner)
|
||||
}
|
||||
|
||||
info.clanName = "Global"
|
||||
info.clanReqs = "-1,-1,7,7" //Any join, any message, owner kick, owner loot
|
||||
GameWorld.accountStorage.update(info)
|
||||
initializeClanWith(info)
|
||||
}
|
||||
ClanRepository.getClans()[event.clanOwner] = c
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,7 +314,44 @@ object ManagementEvents {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun initializeClanFrom(event: SendClanInfo) {
|
||||
val clan = ClanRepository.getClans().getOrPut(event.clanOwner) { ClanRepository(event.clanOwner) }
|
||||
clan.name = event.clanName
|
||||
clan.joinRequirement = ClanRank.values()[event.joinRequirement]
|
||||
clan.kickRequirement = ClanRank.values()[event.kickRequirement]
|
||||
clan.messageRequirement = ClanRank.values()[event.messageRequirement]
|
||||
clan.lootRequirement = ClanRank.values()[event.lootRequirement]
|
||||
|
||||
for (member in event.membersList) {
|
||||
val entry = ClanEntry(member.username, member.world)
|
||||
clan.ranks[member.username] = ClanRank.values()[member.rank]
|
||||
if (member.world == GameWorld.settings!!.worldId) {
|
||||
val p = Repository.getPlayerByName(member.username)
|
||||
entry.player = p
|
||||
p?.communication?.clan = clan
|
||||
}
|
||||
clan.players.add(entry)
|
||||
}
|
||||
|
||||
clan.update()
|
||||
}
|
||||
|
||||
private fun initializeClanWith(info: UserAccountInfo) {
|
||||
val reqs = CommunicationInfo.parseClanRequirements(info.clanReqs)
|
||||
val c = ClanRepository(info.username)
|
||||
val contacts = CommunicationInfo.parseContacts(info.contacts)
|
||||
c.name = info.clanName
|
||||
c.joinRequirement = reqs[0]
|
||||
c.messageRequirement = reqs[1]
|
||||
c.kickRequirement = reqs[2]
|
||||
c.lootRequirement = reqs[3]
|
||||
for ((username, contact) in contacts) {
|
||||
c.ranks[username] = contact.rank
|
||||
}
|
||||
ClanRepository.getClans()[info.username] = c
|
||||
}
|
||||
|
||||
private fun queueUntilClanInfo(clanName: String, message: Message) {
|
||||
val queue = waitingOnClanInfo.getOrPut(clanName) {LinkedList()}
|
||||
queue.offer(message)
|
||||
|
||||
Reference in New Issue
Block a user