New "spawns" mechanic

the current .spawns property for a mob only allows for spawning 1 mob at a set interval. 
this doesnt change that, but now also allows for a mob to spawn additional mobs at %hp thresholds.
it also allows for a quantity of mobs to be spawned for both versions.

Example:
for franky he has "spawns":[[200,"nerfedmummy"]]
it can now be "spawns":[[200,"nerfedmummy",2]] and he would spawn 2 mummies at a time per interval

or "spawns":[["hp:0.50", "nerfedmummy", 3]] and he will spawn 3 mummies once he reaches 50% hp
This commit is contained in:
Crowns3bc
2025-08-21 14:26:39 -06:00
committed by GitHub
parent 3588ab6e71
commit 066b4aeb6c
+48 -16
View File
@@ -11968,23 +11968,24 @@ function update_instance(instance) {
} }
} }
if (monster.target && monster.spawns && get_player(monster.target) && !is_disabled(monster)) { if (monster.target && monster.spawns && get_player(monster.target) && !is_disabled(monster)) {
monster.spawns.forEach(function (spi) { monster.spawns.forEach((spi) => {
var interval = spi[0]; const condition = spi[0]; // interval or "hp:0.75"
var name = spi[1]; const name = spi[1]; // monster type
if (!monster.last[name] || mssince(monster.last[name]) > interval) { const count = spi[2] || 1; // default to 1
var pname = random_one(Object.keys(monster.points));
var player = get_player(pname); // --- Timed spawns (existing) ---
if (!player || player.npc || distance(monster, player) > 400) { if (typeof condition === "number") {
return; if (!monster.last[name] || mssince(monster.last[name]) > condition) {
} for (let i = 0; i < count; i++) {
if (!is_same(player, get_player(monster.target), true)) { const pname = random_one(Object.keys(monster.points));
return; const player = get_player(pname);
} if (!player || player.npc || distance(monster, player) > 400) return;
if (!is_same(player, get_player(monster.target), true)) return;
monster.last[name] = new Date(); monster.last[name] = new Date();
var spot = safe_xy_nearby(player.map, player.x + Math.random() * 20 - 10, player.y + Math.random() * 20 - 10); const spot = safe_xy_nearby(player.map, player.x + Math.random() * 20 - 10, player.y + Math.random() * 20 - 10);
if (!spot) { if (!spot) return;
return;
}
new_monster(instance.name, { new_monster(instance.name, {
type: name, type: name,
stype: "spawn", stype: "spawn",
@@ -11994,6 +11995,37 @@ function update_instance(instance) {
master: monster.id, master: monster.id,
}); });
} }
}
}
// --- HP threshold spawns (new) ---
if (typeof condition === "string" && condition.startsWith("hp:")) {
const threshold = parseFloat(condition.split(":")[1]); // e.g. 0.75
const currentHpRatio = monster.hp / monster.max_hp;
const key = name + "_hp_" + threshold;
if (currentHpRatio <= threshold && !monster.last[key]) { // trigger once per fight
for (let i = 0; i < count; i++) {
const pname = random_one(Object.keys(monster.points));
const player = get_player(pname);
if (!player || player.npc || distance(monster, player) > 400) return;
if (!is_same(player, get_player(monster.target), true)) return;
const spot = safe_xy_nearby(player.map, player.x + Math.random() * 20 - 10, player.y + Math.random() * 20 - 10);
if (!spot) return;
new_monster(instance.name, {
type: name,
stype: "spawn",
x: spot.x,
y: spot.y,
target: player.name,
master: monster.id,
});
}
monster.last[key] = true; // mark this threshold as triggered
}
}
}); });
} }
function attack_target_or_move() { function attack_target_or_move() {