mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-27 20:46:27 -04:00
Pokemon that don't defend themselves will instead run for their life when hurt
This commit is contained in:
@@ -117,7 +117,7 @@ Example behaviour (`uses_healing_machine.json`):
|
||||
"configurations": [
|
||||
{
|
||||
"type": "add_tasks_to_activity",
|
||||
"activity": "idle",
|
||||
"activity": "minecraft:idle",
|
||||
"tasksByPriority": {
|
||||
"1": [
|
||||
"heal_using_healing_machine",
|
||||
|
||||
+18
-26
@@ -9,44 +9,36 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.FLEE_DESIRED_DISTANCE
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.FLEE_SPEED_MULTIPLIER
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.ai.FleeFromAttackerTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetWalkTargetAwayFrom
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class FleeAttackerTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.FEAR_CATEGORY, "flee_attacker", true).asExpressible()
|
||||
var speedMultiplier = numberVariable(SharedEntityVariables.FEAR_CATEGORY, FLEE_SPEED_MULTIPLIER, 0.5).asExpressible()
|
||||
var desiredDistance = numberVariable(SharedEntityVariables.FEAR_CATEGORY, FLEE_DESIRED_DISTANCE, 9).asExpressible()
|
||||
val avoidDurationTicks: ExpressionOrEntityVariable = Either.left("600".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
condition,
|
||||
speedMultiplier,
|
||||
desiredDistance
|
||||
).asVariables()
|
||||
override fun getVariables(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): List<MoLangConfigVariable> {
|
||||
return listOf(avoidDurationTicks).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime) || entity !is PathfinderMob) return null
|
||||
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.WALK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
|
||||
val speedMultiplier = speedMultiplier.resolveFloat(behaviourConfigurationContext.runtime)
|
||||
val desiredDistance = desiredDistance.resolveInt(behaviourConfigurationContext.runtime)
|
||||
return WrapperLivingEntityTask(
|
||||
SetWalkTargetAwayFrom.entity(MemoryModuleType.HURT_BY_ENTITY, speedMultiplier, desiredDistance, false),
|
||||
PathfinderMob::class.java
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.AVOID_TARGET
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
return FleeFromAttackerTask.create(avoidDurationTicks.asExpression())
|
||||
}
|
||||
}
|
||||
@@ -162,11 +162,11 @@ on the entity type and this piggy-backs off the Minecraft list of aggressive mob
|
||||
The 'calm_down' type creates a task that will make the entity calm down when it is no longer being hurt and is far from hostiles and its attacker.
|
||||
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
|
||||
|
||||
### flee_attacker
|
||||
The 'flee_attacker' type creates a task that will make the entity flee from its attacker when it is hurt.
|
||||
### walk_away_from_avoid_target
|
||||
The 'flee_attacker' type creates a task that will make the entity flee from its avoid target.
|
||||
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
|
||||
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for fleeing from the attacker. Defaults to 0.5 which is an elevated speed to usual.
|
||||
- `desiredDistance`: A MoLang expression that determines the distance from the attacker that the entity should try to maintain. Defaults to 9.
|
||||
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for fleeing from the avoid target. Defaults to 0.5 which is an elevated speed to usual.
|
||||
- `desiredDistance`: A MoLang expression that determines the distance from the target that the entity should try to maintain. Defaults to 9.
|
||||
|
||||
### flee_nearest_hostile
|
||||
The 'flee_nearest_hostile' type creates a task that will make the entity flee from the nearest hostile entity when it is hurt.
|
||||
|
||||
@@ -78,8 +78,9 @@ interface TaskConfig {
|
||||
cobblemonResource("switch_to_panic_when_hurt") to SwitchToPanicWhenHurtTaskConfig::class.java,
|
||||
cobblemonResource("switch_to_panic_when_hostiles_nearby") to SwitchToPanicWhenHostilesNearbyTaskConfig::class.java,
|
||||
cobblemonResource("calm_down") to CalmDownTaskConfig::class.java,
|
||||
cobblemonResource("flee_attacker") to FleeAttackerTaskConfig::class.java,
|
||||
cobblemonResource("walk_away_from_avoid_target") to WalkAwayFromAvoidTargetTaskConfig::class.java,
|
||||
cobblemonResource("flee_nearest_hostile") to FleeNearestHostileTaskConfig::class.java,
|
||||
cobblemonResource("flee_attacker") to FleeAttackerTaskConfig::class.java,
|
||||
cobblemonResource("fly_in_circles") to FlyInCirclesTaskConfig::class.java,
|
||||
cobblemonResource("run_script") to RunScript::class.java,
|
||||
cobblemonResource("look_in_direction") to LookInDirectionTaskConfig::class.java,
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.FLEE_DESIRED_DISTANCE
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.FLEE_SPEED_MULTIPLIER
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetWalkTargetAwayFrom
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class WalkAwayFromAvoidTargetTaskConfig : SingleTaskConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
var speedMultiplier = numberVariable(SharedEntityVariables.FEAR_CATEGORY, FLEE_SPEED_MULTIPLIER, 0.7).asExpressible()
|
||||
var desiredDistance = numberVariable(SharedEntityVariables.FEAR_CATEGORY, FLEE_DESIRED_DISTANCE, 9).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
condition,
|
||||
speedMultiplier,
|
||||
desiredDistance
|
||||
).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime) || entity !is PathfinderMob) return null
|
||||
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.WALK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
|
||||
val speedMultiplier = speedMultiplier.resolveFloat(behaviourConfigurationContext.runtime)
|
||||
val desiredDistance = desiredDistance.resolveInt(behaviourConfigurationContext.runtime)
|
||||
return WrapperLivingEntityTask(
|
||||
SetWalkTargetAwayFrom.entity(MemoryModuleType.HURT_BY_ENTITY, speedMultiplier, desiredDistance, false),
|
||||
PathfinderMob::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.entity.ai
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.OneShot
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
@@ -15,7 +20,7 @@ import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
object FleeFromAttackerTask {
|
||||
fun create(): OneShot<LivingEntity> {
|
||||
fun create(avoidDurationTicks: Expression): OneShot<LivingEntity> {
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.present(MemoryModuleType.HURT_BY_ENTITY),
|
||||
@@ -27,7 +32,9 @@ object FleeFromAttackerTask {
|
||||
if (avoidTarget != null && avoidTarget == hurtByEntity.uuid) {
|
||||
return@Trigger false
|
||||
}
|
||||
entity.brain.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, hurtByEntity, 30 * 20)
|
||||
mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val avoidDurationTicks = mainThreadRuntime.resolveInt(avoidDurationTicks)
|
||||
entity.brain.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, hurtByEntity, avoidDurationTicks.toLong())
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ object GoToSleepTask {
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
it.registered(CobblemonMemories.POKEMON_DROWSY)
|
||||
).apply(it) { _, pokemonDrowsy ->
|
||||
Trigger { world, entity, _ ->
|
||||
Trigger { _, entity, _ ->
|
||||
val hasSleepStatus = entity.pokemon.status?.status === Statuses.SLEEP
|
||||
if (entity.behaviour.resting.canSleep && ((it.tryGet(pokemonDrowsy).orElse(false) && entity.canSleepAt(entity.blockPosition().below())) || hasSleepStatus) && entity.pokemon.storeCoordinates.get()?.store !is PartyStore) {
|
||||
if (!hasSleepStatus) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
|
||||
class CombatBehaviour {
|
||||
var willDefendSelf = false
|
||||
var willFlee = false
|
||||
var willFlee = true
|
||||
var willDefendOwner = false
|
||||
var fightsMelee = true
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.DrowsySensor
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.*
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.toDF
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.google.common.collect.ImmutableSet
|
||||
@@ -59,6 +60,11 @@ object PokemonBrain {
|
||||
private val ADULT_FOLLOW_RANGE = UniformInt.of(5, 16)
|
||||
private val AVOID_MEMORY_DURATION = TimeUtil.rangeOfSeconds(5, 20)
|
||||
|
||||
/**
|
||||
* The things that absolutely should be on all pokemon can be put in here. Things that make no sense
|
||||
* without specific activities/Behaviours should be given as part of those activities. Some of the things
|
||||
* in this list currently violate this rule but it's whatever, I'll get to them later.
|
||||
*/
|
||||
val SENSORS: Collection<SensorType<out Sensor<in PokemonEntity>>> = listOf(
|
||||
SensorType.NEAREST_LIVING_ENTITIES,
|
||||
SensorType.HURT_BY,
|
||||
@@ -206,7 +212,7 @@ object PokemonBrain {
|
||||
if (pokemon.form.behaviour.combat.willDefendSelf) {
|
||||
add(0 toDF GetAngryAtAttackerTask.create())
|
||||
} else {
|
||||
add(0 toDF FleeFromAttackerTask.create())
|
||||
add(0 toDF FleeFromAttackerTask.create("600".asExpression()))
|
||||
}
|
||||
|
||||
add(0 toDF StopBeingAngryIfTargetDead.create())
|
||||
|
||||
@@ -3,29 +3,34 @@
|
||||
"description": "cobblemon.behaviour.panics.desc",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "add_tasks_to_activity",
|
||||
"activity": "idle",
|
||||
"type": "cobblemon:add_tasks_to_activity",
|
||||
"activity": "minecraft:idle",
|
||||
"tasksByPriority": {
|
||||
"0": ["switch_to_panic_when_hurt"]
|
||||
"0": ["cobblemon:flee_attacker"],
|
||||
"10": ["cobblemon:switch_to_panic_when_hurt"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "add_tasks_to_activity",
|
||||
"activity": "panic",
|
||||
"type": "cobblemon:add_tasks_to_activity",
|
||||
"activity": "minecraft:panic",
|
||||
"tasksByPriority": {
|
||||
"0": [
|
||||
"calm_down",
|
||||
"follow_walk_target"
|
||||
"cobblemon:flee_attacker",
|
||||
{
|
||||
"type": "cobblemon:activity_change",
|
||||
"activity": "minecraft:idle",
|
||||
"condition": "q.entity.lacks_memory_value('minecraft:avoid_target')"
|
||||
}
|
||||
],
|
||||
"1": [
|
||||
"flee_nearest_hostile"
|
||||
"cobblemon:flee_nearest_hostile"
|
||||
],
|
||||
"2": [
|
||||
"flee_attacker"
|
||||
"cobblemon:walk_away_from_avoid_target"
|
||||
],
|
||||
"3": [
|
||||
{
|
||||
"type": "wander",
|
||||
"type": "cobblemon:wander",
|
||||
"speedMultiplier": {
|
||||
"variableName": "flee_speed_multiplier",
|
||||
"category": "cobblemon.entity.variable.category.fear",
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
},
|
||||
{
|
||||
"type": "apply_behaviours",
|
||||
"condition": "!q.entity.is_in_party && q.entity.behaviour.combat.will_flee",
|
||||
"condition": "!q.entity.is_in_party && (q.entity.behaviour.combat.will_flee && !q.entity.behaviour.combat.will_defend_self)",
|
||||
"behaviours": [
|
||||
"cobblemon:panics"
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user