Skip to content

Comments

New COMBAT event#59

Draft
canefe wants to merge 3 commits intoCircuitLord:masterfrom
canefe:master
Draft

New COMBAT event#59
canefe wants to merge 3 commits intoCircuitLord:masterfrom
canefe:master

Conversation

@canefe
Copy link

@canefe canefe commented May 26, 2025

For servers that use Boss bar for exp, quest tracking or where nearby hostile mobs shouldn't necessarily call a boss song because they could be player-disguised zombie mob for example, a new combat event should be perfect.

Currently it triggers when:

  • Player damages an entity
  • Player gets damaged by a non-null attack source? (I am not sure if this limits to LivingEntity attacks)

Example usage in custom songpacks:

  - events: ["COMBAT"]
    forceStopMusicOnChanged: true
    forceStartMusicOnValid: true
    songs:
      - "LastStand"
      - "Combat1"
      - "Combat2"
      - "Combat3"

How it works

Following two mixin events trigger lastCombatTime:

public abstract class PlayerEntityMixin {
    @Shadow @Final private static Logger LOGGER;

    @Inject(method = "attack", at = @At("HEAD"))
    private void onAttack(Entity target, CallbackInfo ci) {
        if ((Object)this instanceof ClientPlayerEntity) {
            ClientPlayerEntity player = (ClientPlayerEntity)(Object)this;
            World world = player.getWorld();
            SongPicker.lastCombatTime = world.getTime();
        }
    }
    @Inject(method = "damage", at = @At("HEAD"))
    private void onDamage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
        PlayerEntity player = (PlayerEntity) (Object) this;
        World playerWorld = player.getWorld();
        // cause of source
        if (source.getAttacker() != null) {
            SongPicker.lastCombatTime = playerWorld.getTime();
        }
    }
}

Where we invalidate after timeout:

public static final long COMBAT_TIMEOUT = 200; // ticks (10 seconds)

// then in tickEventMap

// Check if player was recently in combat (attacked or was attacked)
boolean inCombat = (world.getTime() - lastCombatTime) < COMBAT_TIMEOUT;
songpackEventMap.put(SongpackEventType.COMBAT, inCombat);

Better customization for combat timeout could be nice.

I have tested it, it works but I will be trying this further during gameplays with few friends.

@CircuitLord
Copy link
Owner

let me know how your testing goes, it's something i'd be interested in integrating but i'd likely want to do a bunch of my own testing as well and tweak it so it's not annoying and constantly triggering everytime you hit a zombie or whatever

I was thinking it could also factor in current health and the amount of mobs nearby or something so that it only starts playing if there's actually a certain amount of danger

thanks for starting to tackle this heh, I've been lazy

@canefe
Copy link
Author

canefe commented May 28, 2025

Thanks for the mod! It really enhances the game.

Here's a few stuff I observed so far:

  • Breaking item frames (and likely armor stands and boats?) currently triggers the combat event. It might be better to filter for specific hostile mob types instead. We probably don’t need combat music for passive mobs.
  • I also agree that a single hit shouldn’t be enough to trigger combat. A short time-based counter stacking damage dealt/taken, with a threshold like 3–5, sounds like a solid approach.
  • And yes, I think some measure of 'actual danger' is important. Combining the threshold with nearby hostile mobs or a danger score would help make it feel more intentional.

@canefe canefe marked this pull request as draft May 28, 2025 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants