Improved the performance of drop table rolling
Chromatic Dragon eggs now only drop at a 1/1000 rate if the player has 99 summoning, impossible to obtain otherwise
This commit is contained in:
@@ -0,0 +1,43 @@
|
|||||||
|
package content.global.handlers.npc
|
||||||
|
|
||||||
|
import core.game.node.entity.Entity
|
||||||
|
import core.game.node.entity.npc.NPC
|
||||||
|
import core.game.node.entity.npc.NPCBehavior
|
||||||
|
import core.game.node.entity.skill.Skills
|
||||||
|
import core.game.node.item.Item
|
||||||
|
import core.tools.RandomFunction
|
||||||
|
import org.rs09.consts.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
class ChromaticDragonBehavior : NPCBehavior(*greenDragons, *blueDragons, *redDragons, *blackDragons)
|
||||||
|
{
|
||||||
|
override fun onDropTableRolled (self: NPC, killer: Entity, drops: ArrayList<Item>) {
|
||||||
|
val removeList = ArrayList<Item>()
|
||||||
|
for (item in drops) {
|
||||||
|
when (item.id) {
|
||||||
|
Items.BLACK_DRAGON_EGG_12480,
|
||||||
|
Items.RED_DRAGON_EGG_12477,
|
||||||
|
Items.BLUE_DRAGON_EGG_12478,
|
||||||
|
Items.GREEN_DRAGON_EGG_12479 -> removeList.add(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drops.removeAll(removeList)
|
||||||
|
|
||||||
|
if (killer.skills.getStaticLevel(Skills.SUMMONING) >= 99 && RandomFunction.roll(EGG_RATE))
|
||||||
|
drops.add(when(self.id) {
|
||||||
|
in greenDragons -> Item(Items.GREEN_DRAGON_EGG_12479)
|
||||||
|
in blueDragons -> Item(Items.BLUE_DRAGON_EGG_12478)
|
||||||
|
in redDragons -> Item(Items.RED_DRAGON_EGG_12477)
|
||||||
|
in blackDragons -> Item(Items.BLACK_DRAGON_EGG_12480)
|
||||||
|
else -> Item(Items.DRAGON_BONES_536)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val greenDragons = intArrayOf (NPCs.GREEN_DRAGON_941, NPCs.GREEN_DRAGON_4677, NPCs.GREEN_DRAGON_4678, NPCs.GREEN_DRAGON_4679, NPCs.GREEN_DRAGON_4680)
|
||||||
|
val blueDragons = intArrayOf (NPCs.BLUE_DRAGON_55, NPCs.BLUE_DRAGON_4681, NPCs.BLUE_DRAGON_4682, NPCs.BLUE_DRAGON_4683, NPCs.BLUE_DRAGON_4684)
|
||||||
|
val redDragons = intArrayOf (NPCs.RED_DRAGON_53, NPCs.RED_DRAGON_4669, NPCs.RED_DRAGON_4670, NPCs.RED_DRAGON_4671, NPCs.RED_DRAGON_4672)
|
||||||
|
val blackDragons = intArrayOf (NPCs.BLACK_DRAGON_54, NPCs.BLACK_DRAGON_4673, NPCs.BLACK_DRAGON_4674, NPCs.BLACK_DRAGON_4675, NPCs.BLACK_DRAGON_4676)
|
||||||
|
var EGG_RATE = 1000
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,12 +10,12 @@ class NPCDropTable : WeightBasedTable() {
|
|||||||
return charmDrops.add(element)
|
return charmDrops.add(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun roll(receiver: Entity?): ArrayList<Item> {
|
override fun roll(receiver: Entity?, times: Int): ArrayList<Item> {
|
||||||
val items = ArrayList<Item>()
|
val items = ArrayList<Item>()
|
||||||
// Charms table is always rolled, and should contain explicit "Nothing"
|
// Charms table is always rolled, and should contain explicit "Nothing"
|
||||||
// entries at the data level to account for the chance to not drop a charm.
|
// entries at the data level to account for the chance to not drop a charm.
|
||||||
items.addAll(charmDrops.roll())
|
items.addAll(charmDrops.roll(receiver, times))
|
||||||
items.addAll(super.roll(receiver))
|
items.addAll(super.roll(receiver, times))
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,23 +38,19 @@ open class WeightBasedTable : ArrayList<WeightedItem>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun roll(receiver: Entity? = null, rollCount: Int) : ArrayList<Item> {
|
open fun roll(receiver: Entity? = null) : ArrayList<Item> {
|
||||||
val items = ArrayList<Item>()
|
return roll(receiver, 1)
|
||||||
|
|
||||||
for (i in 0 until rollCount)
|
|
||||||
items.addAll(roll(receiver))
|
|
||||||
|
|
||||||
return items
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun roll(receiver: Entity? = null): ArrayList<Item>{
|
open fun roll(receiver: Entity? = null, times: Int = 1): ArrayList<Item>{
|
||||||
val items = ArrayList<WeightedItem>()
|
val items = ArrayList<WeightedItem>((guaranteedItems.size + 1) * times)
|
||||||
|
|
||||||
|
for (i in 0 until times) {
|
||||||
items.addAll(guaranteedItems)
|
items.addAll(guaranteedItems)
|
||||||
|
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
items.add(get(0))
|
items.add(get(0))
|
||||||
}
|
} else if (isNotEmpty()) {
|
||||||
else if (isNotEmpty()) {
|
|
||||||
var rngWeight = RandomFunction.randomDouble(totalWeight)
|
var rngWeight = RandomFunction.randomDouble(totalWeight)
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
rngWeight -= item.weight
|
rngWeight -= item.weight
|
||||||
@@ -64,6 +60,7 @@ open class WeightBasedTable : ArrayList<WeightedItem>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return convertWeightedItems(items, receiver)
|
return convertWeightedItems(items, receiver)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ import kotlin.math.floor
|
|||||||
* @author Emperor
|
* @author Emperor
|
||||||
* @author Ceikry - Kotlin refactoring, general cleanup
|
* @author Ceikry - Kotlin refactoring, general cleanup
|
||||||
*/
|
*/
|
||||||
abstract class CombatSwingHandler(var type: CombatStyle?, vararg val flags: SwingHandlerFlag) {
|
abstract class CombatSwingHandler(var type: CombatStyle?) {
|
||||||
|
var flags: Array<out SwingHandlerFlag> = emptyArray()
|
||||||
|
constructor(type: CombatStyle?, vararg flags: SwingHandlerFlag) : this(type) { this.flags = flags }
|
||||||
/**
|
/**
|
||||||
* The mapping of the special attack handlers.
|
* The mapping of the special attack handlers.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -74,11 +74,17 @@ public final class NPCDropTables {
|
|||||||
*/
|
*/
|
||||||
public void drop(NPC npc, Entity looter) {
|
public void drop(NPC npc, Entity looter) {
|
||||||
Player p = looter instanceof Player ? (Player) looter : null;
|
Player p = looter instanceof Player ? (Player) looter : null;
|
||||||
ArrayList<Item> drops = table.roll(looter);
|
ArrayList<Item> drops = table.roll(looter, 1);
|
||||||
npc.behavior.onDropTableRolled(npc, looter, drops);
|
npc.behavior.onDropTableRolled(npc, looter, drops);
|
||||||
drops.forEach(item -> createDrop(item,p,npc,npc.getDropLocation()));
|
drops.forEach(item -> createDrop(item,p,npc,npc.getDropLocation()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Item> roll (NPC npc, Entity looter, int times) {
|
||||||
|
ArrayList<Item> drops = table.roll(looter, times);
|
||||||
|
npc.behavior.onDropTableRolled(npc, looter, drops);
|
||||||
|
return drops;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a dropped item.
|
* Creates a dropped item.
|
||||||
* @param item The item to drop.
|
* @param item The item to drop.
|
||||||
|
|||||||
@@ -167,13 +167,8 @@ class DevelopmentCommandSet : CommandSet(Privilege.ADMIN) {
|
|||||||
val amount = args[2].toInt()
|
val amount = args[2].toInt()
|
||||||
|
|
||||||
container.clear()
|
container.clear()
|
||||||
|
val drops = NPCDefinition.forId(npcId).dropTables.table.roll(player, amount)
|
||||||
for(i in 0..amount)
|
for(drop in drops) container.add(drop, false)
|
||||||
{
|
|
||||||
val drops = NPCDefinition.forId(npcId).dropTables.table.roll(player)
|
|
||||||
for(drop in drops) container.add(drop)
|
|
||||||
}
|
|
||||||
|
|
||||||
container.open(player)
|
container.open(player)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ public class RandomFunction {
|
|||||||
* @return true if you hit the roll, false otherwise
|
* @return true if you hit the roll, false otherwise
|
||||||
*/
|
*/
|
||||||
public static boolean roll(int chance){
|
public static boolean roll(int chance){
|
||||||
|
if (chance <= 1) return true;
|
||||||
return random(chance + 1) == chance / 2;
|
return random(chance + 1) == chance / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package content
|
||||||
|
|
||||||
|
import TestUtils
|
||||||
|
import content.global.handlers.npc.ChromaticDragonBehavior
|
||||||
|
import core.ServerConstants
|
||||||
|
import core.api.utils.NPCDropTable
|
||||||
|
import core.api.utils.WeightedItem
|
||||||
|
import core.game.node.entity.npc.NPC
|
||||||
|
import core.game.node.entity.skill.Skills
|
||||||
|
import core.game.node.item.Item
|
||||||
|
import org.junit.jupiter.api.Assertions
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.rs09.consts.Items
|
||||||
|
import org.rs09.consts.NPCs
|
||||||
|
|
||||||
|
class DropTableTests {
|
||||||
|
init {
|
||||||
|
TestUtils.preTestSetup()
|
||||||
|
}
|
||||||
|
@Test fun chromaticDragonsShouldDropEggsOnlyAfter99Summoning() {
|
||||||
|
val npc = NPC.create(NPCs.BLACK_DRAGON_54, ServerConstants.HOME_LOCATION)
|
||||||
|
val oldTable = npc.definition.dropTables.table
|
||||||
|
|
||||||
|
val testTable = NPCDropTable() //manufacture a fake table that's guaranteed to give an egg, for testing safety.
|
||||||
|
testTable.add(WeightedItem(Items.BLACK_DRAGON_EGG_12480, 1, 1, 1.0))
|
||||||
|
|
||||||
|
npc.definition.dropTables.table = testTable
|
||||||
|
npc.behavior = ChromaticDragonBehavior()
|
||||||
|
|
||||||
|
TestUtils.getMockPlayer("chromaticeggdrop").use { p ->
|
||||||
|
ChromaticDragonBehavior.EGG_RATE = 1 //guarantee egg drop if other parameters are satisfied
|
||||||
|
var hasEgg = false
|
||||||
|
|
||||||
|
var items = npc.definition.dropTables.roll(npc, p, 1)
|
||||||
|
for (item in items)
|
||||||
|
if (item.id == Items.BLACK_DRAGON_EGG_12480) hasEgg = true
|
||||||
|
Assertions.assertEquals(false, hasEgg)
|
||||||
|
|
||||||
|
p.skills.setStaticLevel(Skills.SUMMONING, 99)
|
||||||
|
|
||||||
|
items = npc.definition.dropTables.roll(npc, p, 1)
|
||||||
|
for (item in items)
|
||||||
|
if (item.id == Items.BLACK_DRAGON_EGG_12480) hasEgg = true
|
||||||
|
Assertions.assertEquals(true, hasEgg)
|
||||||
|
}
|
||||||
|
|
||||||
|
npc.definition.dropTables.table = oldTable
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user