P5 the Old Stag: standing stones and altar, three-phase boss with charges, stun window, spirit wolves and stomps; antler pickaxe and trophy; group scaling and credit for every fighter; online 3-player test (protocol 12)

This commit is contained in:
Paul Bailey
2026-11-05 13:39:06 +00:00
parent 3389ec9a21
commit e03411ffdb
24 changed files with 1587 additions and 17 deletions

View File

@@ -20,7 +20,8 @@ extends Node
const Creature = preload("res://scripts/creatures/creature.gd")
const BearScript = preload("res://scripts/creatures/bear.gd")
const CrowScript = preload("res://scripts/creatures/crow.gd")
const GuardScript = preload("res://scripts/creatures/guard.gd") # (falls apart in its own way)
const GuardScript = preload("res://scripts/creatures/guard.gd")
const StagScript = preload("res://scripts/creatures/old_stag.gd") # (rears and lowers its antlers) # (falls apart in its own way)
const Bobber = preload("res://scripts/fishing/bobber.gd")
const Projectile = preload("res://scripts/creatures/projectile.gd")
const WolfPack = preload("res://scripts/creatures/wolf_pack.gd")
@@ -98,9 +99,9 @@ func _server_tick(w: Node3D, delta: float) -> void:
const PER_PACKET := 40
const ENTRY := 23
const KIND_IDS := ["rabbit", "deer", "boar", "wolf", "alpha", "bear", "crow", "fox", "guard"]
const KIND_IDS := ["rabbit", "deer", "boar", "wolf", "alpha", "bear", "crow", "fox", "guard", "old_stag", "spirit_wolf"]
const STATE_IDS := ["idle", "wander", "flee", "charge", "dead", "rest", "alert", "stalk", "lunge", "retreat", "home", "defend", "bash",
"warn", "raid", "eat", "fly", "fly_off", "peck", "sneak", "carry"]
"warn", "raid", "eat", "fly", "fly_off", "peck", "sneak", "carry", "circle", "telegraph", "stunned", "summon", "stomp"]
## One creature in 23 bytes: id, kind, state, position, facing, speed, health.
static func _encode(buf: PackedByteArray, o: int, c: Node3D) -> void:
@@ -113,13 +114,13 @@ static func _encode(buf: PackedByteArray, o: int, c: Node3D) -> void:
buf.encode_float(o + 14, p.z)
buf.encode_u16(o + 18, int(fposmod(c.yaw, TAU) / TAU * 65535.0))
buf.encode_u8(o + 20, clampi(int(c.speed * 20.0), 0, 255))
buf.encode_u16(o + 21, clampi(int(c.hp * 100.0), 0, 65535))
buf.encode_u16(o + 21, clampi(roundi(c.hp * 10.0), 0, 65535)) # (tenths: up to 6553, the Old Stag has 900)
static func _decode(buf: PackedByteArray, o: int) -> Array:
return [buf.decode_u32(o), KIND_IDS[mini(buf.decode_u8(o + 4), KIND_IDS.size() - 1)],
Vector3(buf.decode_float(o + 6), buf.decode_float(o + 10), buf.decode_float(o + 14)),
buf.decode_u16(o + 18) / 65535.0 * TAU, STATE_IDS[mini(buf.decode_u8(o + 5), STATE_IDS.size() - 1)],
buf.decode_u8(o + 20) / 20.0, buf.decode_u16(o + 21) / 100.0]
buf.decode_u8(o + 20) / 20.0, buf.decode_u16(o + 21) / 10.0]
func _on_launched(id: String, origin: Vector3, vel: Vector3, shooter: Node3D) -> void:
var by := int(shooter.peer) if shooter != null and is_instance_valid(shooter) and shooter.get("peer") != null else 0
@@ -197,7 +198,7 @@ func _s2c_life(packed: PackedByteArray, fl: Array) -> void:
var c: Node3D = got if is_instance_valid(got) else null
if c == null:
# (Kinds with their own look: the bear rears up, a crow flaps.)
var script: Script = {"bear": BearScript, "crow": CrowScript, "guard": GuardScript}.get(kind, Creature)
var script: Script = {"bear": BearScript, "crow": CrowScript, "guard": GuardScript, "old_stag": StagScript}.get(kind, Creature)
c = script.new()
c.puppet = true
c.setup(kind, world, e[2], cid)