implement mob "panic" behavior

This commit is contained in:
p2r3
2025-09-14 15:37:05 +03:00
parent e7e9d307e6
commit a34134918a
2 changed files with 23 additions and 3 deletions

View File

@@ -238,7 +238,8 @@ typedef struct {
uint8_t y; uint8_t y;
short z; short z;
// Lower 5 bits: health // Lower 5 bits: health
// Upper 3 bits: reserved (?) // Middle 1 bit: reserved for future use
// Upper 2 bits: panic timer
uint8_t data; uint8_t data;
} MobData; } MobData;

View File

@@ -1400,6 +1400,9 @@ void hurtEntity (int entity_id, int attacker_id, uint8_t damage_type, uint8_t da
// Don't continue if the mob is already dead // Don't continue if the mob is already dead
if (mob_health == 0) return; if (mob_health == 0) return;
// Set the mob's panic timer
mob->data |= (3 << 6);
// Process health change on the server // Process health change on the server
if (mob_health <= damage) { if (mob_health <= damage) {
@@ -1544,6 +1547,9 @@ void handleServerTick (int64_t time_since_last_tick) {
mob_data[i].type == 95 || // Pig mob_data[i].type == 95 || // Pig
mob_data[i].type == 106 // Sheep mob_data[i].type == 106 // Sheep
); );
// Mob "panic" timer, set to 3 after being hit
// Currently has no effect on hostile mobs
uint8_t panic = (mob_data[i].data >> 6) & 3;
// Burn hostile mobs if above ground during sunlight // Burn hostile mobs if above ground during sunlight
if (!passive && (world_time < 13000 || world_time > 23460) && mob_data[i].y > 48) { if (!passive && (world_time < 13000 || world_time > 23460) && mob_data[i].y > 48) {
@@ -1553,8 +1559,21 @@ void handleServerTick (int64_t time_since_last_tick) {
uint32_t r = fast_rand(); uint32_t r = fast_rand();
if (passive) { if (passive) {
// Update passive mobs once per 4 seconds on average if (panic) {
if (r % (4 * (unsigned int)TICKS_PER_SECOND) != 0) continue; // If panicking, move randomly at up to 4 times per second
if (TICKS_PER_SECOND >= 4) {
uint32_t ticks_per_panic = (uint32_t)(TICKS_PER_SECOND / 4);
if (server_ticks % ticks_per_panic != 0) continue;
}
// Reset panic state after timer runs out
// Each panic timer tick takes one second
if (server_ticks % (uint32_t)TICKS_PER_SECOND == 0) {
mob_data[i].data -= (1 << 6);
}
} else {
// When not panicking, move idly once per 4 seconds on average
if (r % (4 * (unsigned int)TICKS_PER_SECOND) != 0) continue;
}
} else { } else {
// Update hostile mobs once per second // Update hostile mobs once per second
if (server_ticks % (uint32_t)TICKS_PER_SECOND != 0) continue; if (server_ticks % (uint32_t)TICKS_PER_SECOND != 0) continue;