Rewrote impling system

Fixed static impling spawns
Fixed impling spawn ratio
Reworked Puro-Puro, much more authentic
Imp defenders now work properly
Crop circles now appear
Added admin command ::implings to list active implings (excludes implings from Puro-Puro)
Fixed bug where you could add to a finished compost bin
This commit is contained in:
Ceikry
2023-04-20 12:16:21 +00:00
committed by Ryan
parent 41c970efd4
commit f6096e3020
24 changed files with 915 additions and 457 deletions
@@ -32,6 +32,7 @@ import core.game.world.update.flag.npc.NPCForceChat;
import core.game.world.update.flag.npc.NPCSwitchId;
import core.tools.RandomFunction;
import core.api.utils.GlobalKillCounter;
import core.api.utils.Vector;
import core.game.shops.Shops;
import core.game.node.entity.combat.CombatSwingHandler;
import core.game.system.config.NPCConfigParser;
@@ -142,7 +143,7 @@ public class NPC extends Entity {
*/
private String forceTalk;
public final NPCBehavior behavior;
public NPCBehavior behavior;
/**
* Constructs a new {@code NPC} {@code Object}.
@@ -373,7 +374,7 @@ public class NPC extends Entity {
@Override
public boolean isAttackable(Entity entity, CombatStyle style, boolean message) {
if ((entity instanceof Player && !definition.hasAction("attack")) || isInvisible()) {
if (isInvisible()) {
return false;
}
if (task != null && entity instanceof Player && task.levelReq > entity.getSkills().getStaticLevel(Skills.SLAYER)) {
@@ -719,15 +720,10 @@ public class NPC extends Entity {
Location returnToSpawnLocation = getProperties().getSpawnLocation().transform(-5 + RandomFunction.random(getWalkRadius()), -5 + RandomFunction.random(getWalkRadius()), 0);
int dist = (int) Location.getDistance(location, returnToSpawnLocation);
int pathLimit = 15;
if(dist > pathLimit || dist < -pathLimit)
{
int diffX = returnToSpawnLocation.getX() - location.getX();
int diffY = returnToSpawnLocation.getY() - location.getY();
returnToSpawnLocation = location.transform(
Math.min(Math.max(-pathLimit, diffX), pathLimit), //Try to path no more than pathLimit and no less than -pathLimit tiles away in the X and Y directions
Math.min(Math.max(-pathLimit, diffY), pathLimit),
0);
}
if (dist > pathLimit) {
Vector normalizedDir = Vector.betweenLocs(this.location, returnToSpawnLocation).normalized();
returnToSpawnLocation = this.location.transform (normalizedDir.times(pathLimit));
}
return returnToSpawnLocation;
}
Location l = movementPath[movementIndex++];
@@ -1,11 +1,14 @@
package core.game.node.entity.npc
import core.game.node.item.Item
import core.api.ContentInterface
import core.game.node.entity.Entity
import core.game.world.map.RegionManager
import core.game.node.entity.player.Player
import core.game.node.entity.combat.BattleState
import core.game.node.entity.combat.CombatStyle
import core.game.node.entity.combat.CombatSwingHandler
import core.game.node.item.Item
import core.game.world.map.path.ClipMaskSupplier
open class NPCBehavior(vararg val ids: Int = intArrayOf()) : ContentInterface {
companion object {
@@ -19,6 +22,12 @@ open class NPCBehavior(vararg val ids: Int = intArrayOf()) : ContentInterface {
ids.forEach { idMap[it] = behavior }
}
}
object StandardClipMaskSupplier : ClipMaskSupplier {
override fun getClippingFlag (z: Int, x: Int, y: Int) : Int {
return RegionManager.getClippingFlag(z,x,y)
}
}
/**
* Called every tick, before the base NPC tick() method.
@@ -102,7 +111,11 @@ open class NPCBehavior(vararg val ids: Int = intArrayOf()) : ContentInterface {
* @param shouldSendMessage whether the core combat code believes you should send a message e.g. "You can't attack this NPC with that weapon"
* @return whether the attacker should be able to attack this NPC.
*/
open fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean) : Boolean {return true}
open fun canBeAttackedBy(self: NPC, attacker: Entity, style: CombatStyle, shouldSendMessage: Boolean) : Boolean {
if (attacker is Player && !self.definition.hasAction("attack"))
return false
return true
}
/**
* Called by combat-related code to check if this NPC should ignore multi-combat rules when attempting to attack the given victim.
@@ -119,4 +132,11 @@ open class NPCBehavior(vararg val ids: Int = intArrayOf()) : ContentInterface {
* @return the SwingHandler instance to be used for this cycle of combat
*/
open fun getSwingHandlerOverride(self: NPC, original: CombatSwingHandler) : CombatSwingHandler {return original}
}
/**
* Called by pathfinding code to determine the clipping mask supplier this NPC should use. You can use this to ignore water, etc.
*/
open fun getClippingSupplier(self: NPC) : ClipMaskSupplier? {
return StandardClipMaskSupplier
}
}
@@ -10,6 +10,7 @@ import core.game.node.entity.player.link.IronmanMode
import core.game.node.entity.player.link.SpellBookManager
import core.game.node.entity.player.link.emote.Emotes
import core.game.node.entity.player.link.music.MusicEntry
import core.game.world.map.Location
import org.json.simple.JSONArray
import org.json.simple.JSONObject
import org.json.simple.parser.JSONParser
@@ -122,6 +123,7 @@ class PlayerSaveParser(val player: Player) {
"long" -> attr["value"].toString().toLong()
"bool" -> attr["value"] as Boolean
"byte" -> Base64.getDecoder().decode(attr["value"].toString())[0]
"location" -> Location.fromString(attr["value"].toString())
else -> null.also { log(this::class.java, Log.WARN, "Invalid data type for key: $key in PlayerSaveParser.kt Line 115") }
})
}
@@ -363,4 +365,4 @@ class PlayerSaveParser(val player: Player) {
}
}
}
@@ -9,6 +9,7 @@ import core.game.container.Container
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.IronmanMode
import core.game.node.entity.skill.Skills
import core.game.world.map.Location
import core.tools.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
@@ -116,6 +117,7 @@ class PlayerSaver (val player: Player){
is Short -> "short"
is String -> "str"
is Byte -> "byte"
is Location -> "location"
else -> "null".also { log(this::class.java, Log.WARN, "Invalid attribute type for key: $key in PlayerSaver.kt Line 115") }
}
attr.put("type",type)
@@ -6,9 +6,11 @@ import core.game.world.map.path.Path;
import core.game.world.map.path.Pathfinder;
import core.tools.RandomFunction;
import org.jetbrains.annotations.NotNull;
import core.api.utils.Vector;
import java.util.ArrayList;
import java.util.List;
import java.lang.Math;
/**
* Represents a location on the world map.
@@ -277,14 +279,14 @@ public final class Location extends Node {
public ArrayList<Location> getSurroundingTiles() {
ArrayList<Location> locs = new ArrayList<>();
locs.add(transform(0,1,0)); //N
locs.add(transform(1,1,0)); //NE
locs.add(transform(1,0,0)); //E
locs.add(transform(1,-1,0)); //SE
locs.add(transform(0,-1,0)); //S
locs.add(transform(-1,-1,0));//SW
locs.add(transform(-1,0,0));//W
locs.add(transform(0,-1,0)); //S
locs.add(transform(1,-1,0)); //SE
locs.add(transform(1,0,0)); //E
locs.add(transform(1,1,0)); //NE
locs.add(transform(0,1,0)); //N
locs.add(transform(-1,1,0));//NW
locs.add(transform(-1,0,0));//W
return locs;
}
@@ -554,4 +556,8 @@ public final class Location extends Node {
if (sb.length() == 0) return null;
return Direction.valueOf(sb.toString());
}
public Location transform (Vector vector) {
return Location.create(this.x + (int) Math.floor(vector.getX()), this.y + (int) Math.floor(vector.getY()));
}
}
@@ -2,6 +2,7 @@ package core.game.world.map.path;
import core.game.node.Node;
import core.game.node.entity.Entity;
import core.game.node.entity.npc.NPC;
import core.game.node.item.GroundItem;
import core.game.node.scenery.Scenery;
import core.game.world.map.Direction;
@@ -124,7 +125,13 @@ public abstract class Pathfinder {
* @return The path.
*/
public static Path find(Entity mover, Node destination, boolean near, Pathfinder finder) {
return find(mover.getLocation(), mover.size(), destination, near, finder, RegionManager::getClippingFlag);
ClipMaskSupplier cms = null;
if (mover instanceof NPC) {
cms = ((NPC) mover).behavior.getClippingSupplier(((NPC) mover));
}
if (cms == null)
cms = RegionManager::getClippingFlag;
return find(mover.getLocation(), mover.size(), destination, near, finder, cms);
}
public static Path findWater(Entity mover, Node destination, boolean near, Pathfinder finder){