M2.5: wildlife, wolves, hunting, fishing and sleeping on the server
This commit is contained in:
@@ -65,11 +65,25 @@ func _ask(what: String, args: Array = []) -> bool:
|
||||
PlayerNet.ask(what, args)
|
||||
return true
|
||||
|
||||
const NOT_ONLINE := "Hunting and fishing aren't on servers yet (they come with the animals)"
|
||||
## A message for one player: on screen in single-player; on a server, to
|
||||
## that player's game (player_net.gd). For things that happen later than the
|
||||
## request that caused them (a fish biting, an arrow landing a kill).
|
||||
func tell(player: Node, text: String) -> void:
|
||||
if Net.is_server() and player != null and player.get("peer") != null:
|
||||
PlayerNet.tell(int(player.peer), text)
|
||||
else:
|
||||
notify.emit(text)
|
||||
|
||||
func _not_online() -> bool:
|
||||
notify.emit(NOT_ONLINE)
|
||||
return false
|
||||
## A message for everyone (the wolves howling).
|
||||
func tell_all(text: String) -> void:
|
||||
if Net.is_server():
|
||||
PlayerNet.tell_all(text)
|
||||
else:
|
||||
notify.emit(text)
|
||||
|
||||
## Online, a creature is known by its net id (creature_net.gd).
|
||||
static func _cid(c: Node) -> int:
|
||||
return int(c.get_meta("cid", 0))
|
||||
|
||||
func _in_reach(player: Node3D, target: Node3D, extra: float = 0.0) -> bool:
|
||||
return player.global_position.distance_to(target.global_position) <= REACH + 2.5 + extra
|
||||
@@ -251,7 +265,12 @@ func melee_stats(player: Node) -> Dictionary:
|
||||
## One melee blow at an animal.
|
||||
func melee(player: Node3D, target: Node3D) -> bool:
|
||||
if _online():
|
||||
return _not_online()
|
||||
if not is_instance_valid(target) or not target.is_in_group("creature"):
|
||||
return false
|
||||
if not melee_stats(player).armed:
|
||||
notify.emit(NEED_WEAPON)
|
||||
return false
|
||||
return _ask("melee", [_cid(target)])
|
||||
if not is_instance_valid(target) or not target.is_in_group("creature"):
|
||||
return false
|
||||
var m := melee_stats(player)
|
||||
@@ -275,12 +294,12 @@ func projectile_hit(shooter: Node3D, target: Node3D, damage: float, at: Vector3,
|
||||
var was_alive: bool = not target.is_dead()
|
||||
target.take_hit(damage, shooter.global_position if shooter != null else at, embed_id)
|
||||
if was_alive and target.is_dead():
|
||||
notify.emit("Killed a %s" % target.display_name().to_lower())
|
||||
tell(shooter, "Killed a %s" % target.display_name().to_lower())
|
||||
|
||||
## Throws the spear in `slot` from `origin` along `dir`.
|
||||
func throw_spear(player: Node3D, slot: int, origin: Vector3, dir: Vector3, world: Node3D) -> bool:
|
||||
if _online():
|
||||
return _not_online()
|
||||
return _ask("throw", [slot, dir])
|
||||
var s = player.inventory.get_slot(slot)
|
||||
if s == null:
|
||||
return false
|
||||
@@ -298,9 +317,15 @@ func throw_spear(player: Node3D, slot: int, origin: Vector3, dir: Vector3, world
|
||||
|
||||
## Starts drawing the held bow: needs arrows and a little stamina.
|
||||
func can_draw(player: Node3D) -> bool:
|
||||
if _online():
|
||||
return _not_online()
|
||||
var bow: Dictionary = ItemDB.get_item(player.held_item_id()).get("bow", {})
|
||||
if _online():
|
||||
# (The server checks arrows and spends the stamina when you shoot.)
|
||||
if bow.is_empty():
|
||||
return false
|
||||
if player.inventory.count(bow.ammo) <= 0:
|
||||
notify.emit("No arrows (craft them at a workbench: sticks, flint, feathers)")
|
||||
return false
|
||||
return true
|
||||
if bow.is_empty():
|
||||
return false
|
||||
if player.inventory.count(bow.ammo) <= 0:
|
||||
@@ -314,7 +339,7 @@ func can_draw(player: Node3D) -> bool:
|
||||
## Looses an arrow. `power` 0..1 is how far the bow was drawn.
|
||||
func shoot(player: Node3D, origin: Vector3, dir: Vector3, power: float, world: Node3D) -> bool:
|
||||
if _online():
|
||||
return _not_online()
|
||||
return _ask("shoot", [dir, power])
|
||||
var bow: Dictionary = ItemDB.get_item(player.held_item_id()).get("bow", {})
|
||||
if bow.is_empty() or player.global_position.distance_to(origin) > 2.5:
|
||||
return false
|
||||
@@ -328,7 +353,9 @@ func shoot(player: Node3D, origin: Vector3, dir: Vector3, power: float, world: N
|
||||
|
||||
func butcher(player: Node3D, carcass: Node3D) -> bool:
|
||||
if _online():
|
||||
return _not_online()
|
||||
if not is_instance_valid(carcass) or not carcass.is_in_group("carcass"):
|
||||
return false
|
||||
return _ask("butcher", [_cid(carcass)])
|
||||
if not is_instance_valid(carcass) or not carcass.is_in_group("carcass") or not _in_reach(player, carcass, 1.0):
|
||||
return false
|
||||
var drops: Dictionary = carcass.butcher_drops()
|
||||
@@ -346,7 +373,9 @@ func butcher(player: Node3D, carcass: Node3D) -> bool:
|
||||
## Casts the held rod from `origin` along `dir`.
|
||||
func cast_line(player: Node3D, origin: Vector3, dir: Vector3, world: Node3D) -> bool:
|
||||
if _online():
|
||||
return _not_online()
|
||||
if ItemDB.get_item(player.held_item_id()).get("fishing", {}).is_empty():
|
||||
return false
|
||||
return _ask("cast", [dir])
|
||||
var rod: Dictionary = ItemDB.get_item(player.held_item_id()).get("fishing", {})
|
||||
if rod.is_empty() or player.global_position.distance_to(origin) > 2.5:
|
||||
return false
|
||||
@@ -361,14 +390,14 @@ func cast_line(player: Node3D, origin: Vector3, dir: Vector3, world: Node3D) ->
|
||||
## Reels in. With a fish biting you land it; otherwise the line just comes in.
|
||||
func reel(player: Node3D, world: Node3D) -> bool:
|
||||
if _online():
|
||||
return _not_online()
|
||||
var b: Node3D = world.bobber
|
||||
return _ask("reel")
|
||||
var b: Node3D = world.bobber_of(player)
|
||||
if b == null or not is_instance_valid(b):
|
||||
return false
|
||||
var caught := ""
|
||||
if b.state == "biting":
|
||||
caught = b.fish
|
||||
world.end_fishing()
|
||||
world.end_fishing(player)
|
||||
if caught.is_empty():
|
||||
return false
|
||||
if _give(player, caught, 1) == 0:
|
||||
|
||||
Reference in New Issue
Block a user