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:
@@ -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)
|
||||
|
||||
@@ -32,7 +32,7 @@ signal clock(day: int, time: float) ## the server's time of day
|
||||
const Identity = preload("res://scripts/net/identity.gd")
|
||||
const ServerConfig = preload("res://scripts/net/server_config.gd")
|
||||
|
||||
const PROTOCOL := 11 ## 3: shared world; 4: the server decides; 5: wildlife; 6: rules and chat (M2.6); 7: the alpha, broken doors; 8: the bear; 9: crows and foxes; 10: the barrow (P3); 11: food spoilage, lightning (P4)
|
||||
const PROTOCOL := 12 ## 3: shared world; 4: the server decides; 5: wildlife; 6: rules and chat (M2.6); 7: the alpha, broken doors; 8: the bear; 9: crows and foxes; 10: the barrow (P3); 11: food spoilage, lightning (P4); 12: the standing stones and the Old Stag (P5)
|
||||
const DEFAULT_PORT := 24242
|
||||
const HANDSHAKE_TIMEOUT := 10.0
|
||||
const JOIN_TIMEOUT := 20.0 ## includes the server building its terrain on first join
|
||||
|
||||
@@ -324,6 +324,9 @@ func _run(p: Node3D, what: String, a: Array) -> void:
|
||||
if d != null and d.get("open") != null and _allowed(Rules.use_problem(p.player_id, d)) \
|
||||
and Actions.toggle_door(p, d):
|
||||
WorldNet.piece_state(d)
|
||||
"stones":
|
||||
if w.stones != null:
|
||||
Actions.use_stones(p, w.stones)
|
||||
"barrow_loot":
|
||||
if w.barrow != null:
|
||||
Actions.loot_barrow(p, w.barrow)
|
||||
@@ -429,8 +432,19 @@ func _run(p: Node3D, what: String, a: Array) -> void:
|
||||
for m in w.get_tree().get_nodes_in_group("processor"):
|
||||
m.step(float(a[0]) if a.size() > 0 and (a[0] is float or a[0] is int) else 60.0)
|
||||
"debug_spawn":
|
||||
if cheats and Creature.KINDS.has(_s(a, 0)) and not (_s(a, 0) in ["wolf", "alpha", "bear", "crow", "fox", "guard"]) and _v(a, 1).is_finite():
|
||||
if cheats and Creature.KINDS.has(_s(a, 0)) and not (_s(a, 0) in ["wolf", "alpha", "bear", "crow", "fox", "guard", "old_stag", "spirit_wolf"]) and _v(a, 1).is_finite():
|
||||
w.creatures.spawn(_s(a, 0), _v(a, 1))
|
||||
"debug_boss":
|
||||
# Tests: ["hold", secs] stands the Old Stag still (stunned);
|
||||
# ["hp", n] sets its health.
|
||||
var s: Node3D = w.stones.stag if w.stones != null and w.stones.fighting() else null
|
||||
if cheats and s != null:
|
||||
match _s(a, 0):
|
||||
"hold":
|
||||
s.state = "stunned"
|
||||
s._state_t = float(a[1]) if a.size() > 1 else 30.0
|
||||
"hp":
|
||||
s.hp = clampf(float(a[1]) if a.size() > 1 else 1.0, 1.0, s.max_hp)
|
||||
"debug_time":
|
||||
if cheats:
|
||||
w.day_night.day = maxi(_i(a, 0), 1)
|
||||
|
||||
@@ -365,6 +365,17 @@ func _s2c_node(uid: String, hp: float, point: Vector3, from: Vector3) -> void:
|
||||
n.apply_remote(hp, point, from)
|
||||
received += 1
|
||||
|
||||
## The standing stones' altar changed (key pieces set, the stag beaten).
|
||||
func stones_state(d: Dictionary) -> void:
|
||||
_all("_s2c_stones", [d])
|
||||
|
||||
@rpc("authority", "call_remote", "reliable")
|
||||
func _s2c_stones(d: Dictionary) -> void:
|
||||
if not is_client() or world.stones == null:
|
||||
return
|
||||
world.stones.load_data(d)
|
||||
received += 1
|
||||
|
||||
## Lightning struck a tree (hazards.gd, P4): everyone sees it burn. (It
|
||||
## falls later through _s2c_node, like any felled tree.)
|
||||
func struck(n: Node3D) -> void:
|
||||
|
||||
Reference in New Issue
Block a user