Add expanded fishing gear and presentation
This commit is contained in:
parent
551db3ccc6
commit
72d3a303f5
29 changed files with 783 additions and 86 deletions
|
|
@ -22,8 +22,10 @@ var target: Vector3
|
|||
var bobber_position: Vector3
|
||||
var fish_id: StringName
|
||||
var bait_tags: Array[StringName] = []
|
||||
var lure_effects: Array[StringName] = []
|
||||
var encounter_seed: int = 0
|
||||
var bite_time_remaining: float = 0.0
|
||||
var bite_confirmation_pending: bool = false
|
||||
var withdrawal_progress: float = 0.0
|
||||
var reel_speed: float = 0.0
|
||||
var barrier_damage: int = 1
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ static func validate_cast_request(data: Variant) -> String:
|
|||
return "Malformed fishing request."
|
||||
if payload.has("bait_id") and typeof(payload["bait_id"]) not in [TYPE_STRING, TYPE_STRING_NAME]:
|
||||
return "Malformed fishing request."
|
||||
if payload.has("lure_id") and typeof(payload["lure_id"]) not in [TYPE_STRING, TYPE_STRING_NAME]:
|
||||
return "Malformed fishing request."
|
||||
var request_id: String = payload["request_id"]
|
||||
var session_id: String = payload["session_id"]
|
||||
var origin: Array = payload["origin"]
|
||||
|
|
@ -89,6 +91,7 @@ static func validate_cast_request(data: Variant) -> String:
|
|||
or discovered.size() > MAX_EVIDENCE_FISH_IDS
|
||||
or str(payload["rod_id"]).is_empty()
|
||||
or str(payload["rod_id"]).length() > 96
|
||||
or str(payload.get("lure_id", "")).length() > 96
|
||||
):
|
||||
return "Fishing request values are outside allowed limits."
|
||||
for value: Variant in rarity:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ const MIN_CAST_INTERVAL: float = 0.25
|
|||
signal local_cast_accepted(attempt_id: String, target: Vector3)
|
||||
signal local_cast_rejected(message: String)
|
||||
signal local_bite_started(attempt_id: String)
|
||||
signal local_bite_pending(attempt_id: String)
|
||||
signal local_snapshot_received(snapshot: Dictionary)
|
||||
signal local_catch_received(fish_catch: FishCatch)
|
||||
signal local_attempt_ended(outcome: StringName, message: String)
|
||||
|
|
@ -111,6 +112,7 @@ func request_local_cast(
|
|||
"discovered_fish_ids": evidence.get("discovered_fish_ids", []),
|
||||
"capacity_available": bool(evidence.get("capacity_available", false)),
|
||||
"bait_id": str(evidence.get("bait_id", "")),
|
||||
"lure_id": str(evidence.get("lure_id", "")),
|
||||
}
|
||||
if _session.is_host():
|
||||
_handle_cast_request(_session.get_local_peer_id(), data)
|
||||
|
|
@ -176,12 +178,17 @@ func _process(delta: float) -> void:
|
|||
continue
|
||||
match attempt.phase:
|
||||
NetworkFishingAttempt.Phase.WAITING_FOR_BITE:
|
||||
if attempt.bite_confirmation_pending:
|
||||
continue
|
||||
_update_waiting_attempt(attempt, delta)
|
||||
if not _attempts.has(peer_id):
|
||||
continue
|
||||
attempt.bite_time_remaining -= delta
|
||||
if attempt.bite_time_remaining <= 0.0:
|
||||
_start_bite(attempt)
|
||||
if &"deferred_fight" in attempt.lure_effects:
|
||||
_set_bite_pending(attempt)
|
||||
else:
|
||||
_start_bite(attempt)
|
||||
NetworkFishingAttempt.Phase.PENDING_CAPACITY:
|
||||
if now >= attempt.capacity_deadline:
|
||||
_cancel_attempt(peer_id, "Fishing attempt ended.")
|
||||
|
|
@ -296,6 +303,23 @@ func _handle_cast_request(peer_id: int, data: Dictionary) -> void:
|
|||
return
|
||||
var bait_id: StringName = StringName(str(data.get("bait_id", "")))
|
||||
var avatar_bag: PlayerBag = avatar.bag
|
||||
var lure_id: StringName = StringName(str(data.get("lure_id", "")))
|
||||
var lure: ItemDataType = (
|
||||
_item_catalog.get_item_by_id(lure_id)
|
||||
if not lure_id.is_empty() and _item_catalog != null
|
||||
else null
|
||||
)
|
||||
if (
|
||||
not lure_id.is_empty()
|
||||
and (
|
||||
lure == null
|
||||
or not lure.is_lure()
|
||||
or avatar_bag == null
|
||||
or not avatar_bag.owns_item(lure_id)
|
||||
)
|
||||
):
|
||||
_record_and_reject(peer_id, request_id, "Lure is unavailable.")
|
||||
return
|
||||
if not bait_id.is_empty() and (avatar_bag == null or not avatar_bag.remove_item(bait_id, 1)):
|
||||
_record_and_reject(peer_id, request_id, "No bait available.")
|
||||
return
|
||||
|
|
@ -310,6 +334,10 @@ func _handle_cast_request(peer_id: int, data: Dictionary) -> void:
|
|||
attempt.bobber_position = authoritative_target
|
||||
attempt.fish_id = selected_fish.id
|
||||
attempt.bait_tags = _bait_tags_for_request(data)
|
||||
attempt.lure_effects.clear()
|
||||
if lure != null:
|
||||
for effect_id: StringName in lure.lure_effects:
|
||||
attempt.lure_effects.append(effect_id)
|
||||
attempt.reel_speed = float(data["reel_speed"]) * (
|
||||
effects.get_reel_multiplier() if effects != null else 1.0
|
||||
)
|
||||
|
|
@ -437,6 +465,23 @@ func _bait_tags_for_request(data: Dictionary) -> Array[StringName]:
|
|||
return bait.bait_tags.duplicate() if bait != null and bait.is_bait() else []
|
||||
|
||||
|
||||
func _set_bite_pending(attempt: NetworkFishingAttempt) -> void:
|
||||
if (
|
||||
attempt.phase != NetworkFishingAttempt.Phase.WAITING_FOR_BITE
|
||||
or attempt.bite_confirmation_pending
|
||||
):
|
||||
return
|
||||
attempt.bite_confirmation_pending = true
|
||||
attempt.bite_time_remaining = 0.0
|
||||
attempt.input_held = false
|
||||
var data: Dictionary = {
|
||||
"attempt_id": attempt.attempt_id,
|
||||
"owner_peer_id": attempt.owner_peer_id,
|
||||
}
|
||||
_apply_bite_pending(data)
|
||||
receive_bite_pending.rpc(data)
|
||||
|
||||
|
||||
func _start_bite(attempt: NetworkFishingAttempt) -> void:
|
||||
if attempt.phase != NetworkFishingAttempt.Phase.WAITING_FOR_BITE:
|
||||
return
|
||||
|
|
@ -444,6 +489,7 @@ func _start_bite(attempt: NetworkFishingAttempt) -> void:
|
|||
if fish == null or fish.catch_profile == null:
|
||||
_cancel_attempt(attempt.owner_peer_id, "Fishing attempt ended.")
|
||||
return
|
||||
attempt.bite_confirmation_pending = false
|
||||
attempt.phase = NetworkFishingAttempt.Phase.FIGHTING
|
||||
attempt.encounter_seed = _new_seed()
|
||||
var selector := FishSelectorType.new()
|
||||
|
|
@ -496,6 +542,14 @@ func _handle_fishing_input(peer_id: int, data: Dictionary) -> void:
|
|||
return
|
||||
attempt.last_input_sequence = int(data["sequence"])
|
||||
attempt.input_held = bool(data["held"])
|
||||
if (
|
||||
attempt.phase == NetworkFishingAttempt.Phase.WAITING_FOR_BITE
|
||||
and attempt.bite_confirmation_pending
|
||||
):
|
||||
if bool(data["pressed"]):
|
||||
attempt.input_held = false
|
||||
_start_bite(attempt)
|
||||
return
|
||||
if attempt.phase != NetworkFishingAttempt.Phase.FIGHTING:
|
||||
return
|
||||
attempt.controller.set_reel_input(attempt.input_held)
|
||||
|
|
@ -978,6 +1032,21 @@ func _apply_cast_accepted(data: Dictionary) -> void:
|
|||
presentation.show_cast(origin, target)
|
||||
|
||||
|
||||
@rpc("authority", "call_remote", "reliable", 0)
|
||||
func receive_bite_pending(data: Dictionary) -> void:
|
||||
_apply_bite_pending(data)
|
||||
|
||||
|
||||
func _apply_bite_pending(data: Dictionary) -> void:
|
||||
if (
|
||||
typeof(data.get("attempt_id")) != TYPE_STRING
|
||||
or typeof(data.get("owner_peer_id")) != TYPE_INT
|
||||
):
|
||||
return
|
||||
if int(data["owner_peer_id"]) == _session.get_local_peer_id():
|
||||
local_bite_pending.emit(str(data["attempt_id"]))
|
||||
|
||||
|
||||
@rpc("authority", "call_remote", "reliable", 0)
|
||||
func receive_bite_started(data: Dictionary) -> void:
|
||||
_apply_bite_started(data)
|
||||
|
|
|
|||
|
|
@ -50,9 +50,19 @@ func request_use(item_id: StringName) -> String:
|
|||
if not _pending_local.is_empty():
|
||||
local_item_use_finished.emit(false, "An item use is already pending.")
|
||||
return ""
|
||||
var consumed_item_id: StringName = _consumed_item_id(item_id)
|
||||
if item_id == PlayerItemEffects.FISH_FINDER_ID and (
|
||||
_local_bag == null
|
||||
or not _local_bag.owns_item(item_id)
|
||||
or _local_bag.get_quantity(consumed_item_id) < 1
|
||||
):
|
||||
local_item_use_finished.emit(
|
||||
false, PlayerItemEffects.FISH_FINDER_DEAD_MESSAGE
|
||||
)
|
||||
return ""
|
||||
if (
|
||||
_reservations != null
|
||||
and _reservations.get_available_item_quantity(item_id) < 1
|
||||
and _reservations.get_available_item_quantity(consumed_item_id) < 1
|
||||
):
|
||||
local_item_use_finished.emit(false, "Reserved in a letter.")
|
||||
return ""
|
||||
|
|
@ -73,7 +83,7 @@ func request_use(item_id: StringName) -> String:
|
|||
"request_id": request_id,
|
||||
"session_id": _session.get_session_id(),
|
||||
"item_id": str(item_id),
|
||||
"quantity": _local_bag.get_quantity(item_id),
|
||||
"quantity": _local_bag.get_quantity(consumed_item_id),
|
||||
}
|
||||
_pending_local = data.duplicate(true)
|
||||
local_item_use_pending.emit(request_id)
|
||||
|
|
@ -109,14 +119,28 @@ func _handle_use_request(peer_id: int, data: Dictionary) -> void:
|
|||
var item: ItemData = _catalog.get_item_by_id(item_id)
|
||||
var avatar: Player = _spawn_service.get_avatar(peer_id)
|
||||
var duration: float = 0.0
|
||||
var is_fish_finder: bool = (
|
||||
item_id == PlayerItemEffects.FISH_FINDER_ID
|
||||
and item != null
|
||||
and item.category == ItemData.Category.TOOL
|
||||
and item.usable
|
||||
and item.equippable
|
||||
)
|
||||
if error.is_empty() and (
|
||||
item == null
|
||||
or item.category != ItemData.Category.CONSUMABLE
|
||||
or (
|
||||
item.category != ItemData.Category.CONSUMABLE
|
||||
and not is_fish_finder
|
||||
)
|
||||
or not item.usable
|
||||
):
|
||||
error = "That item cannot be used now."
|
||||
if error.is_empty() and int(data["quantity"]) < 1:
|
||||
error = "You do not have that item."
|
||||
error = (
|
||||
PlayerItemEffects.FISH_FINDER_DEAD_MESSAGE
|
||||
if is_fish_finder
|
||||
else "You do not have that item."
|
||||
)
|
||||
if error.is_empty() and (
|
||||
avatar == null
|
||||
or avatar.is_water_recovery_active()
|
||||
|
|
@ -180,9 +204,10 @@ func _apply_result(data: Dictionary) -> void:
|
|||
_acknowledge(data, false, str(data["message"]))
|
||||
return
|
||||
var item_id := StringName(str(data["item_id"]))
|
||||
var consumed_item_id: StringName = _consumed_item_id(item_id)
|
||||
if (
|
||||
_reservations != null
|
||||
and _reservations.get_available_item_quantity(item_id) < 1
|
||||
and _reservations.get_available_item_quantity(consumed_item_id) < 1
|
||||
):
|
||||
_pending_local.clear()
|
||||
local_item_use_finished.emit(false, "Reserved in a letter.")
|
||||
|
|
@ -190,8 +215,8 @@ func _apply_result(data: Dictionary) -> void:
|
|||
return
|
||||
var bag_snapshot := _local_bag.get_all_items()
|
||||
if (
|
||||
_local_bag.get_quantity(item_id) < 1
|
||||
or not _local_bag.remove_item(item_id, 1)
|
||||
_local_bag.get_quantity(consumed_item_id) < 1
|
||||
or not _local_bag.remove_item(consumed_item_id, 1)
|
||||
or not _save_manager.save_if_dirty()
|
||||
):
|
||||
_local_bag.replace_all_items(bag_snapshot)
|
||||
|
|
@ -409,3 +434,11 @@ func _new_id(prefix: String) -> String:
|
|||
return "%s:%s" % [
|
||||
prefix, Crypto.new().generate_random_bytes(16).hex_encode(),
|
||||
]
|
||||
|
||||
|
||||
func _consumed_item_id(item_id: StringName) -> StringName:
|
||||
return (
|
||||
PlayerItemEffects.BATTERIES_ID
|
||||
if item_id == PlayerItemEffects.FISH_FINDER_ID
|
||||
else item_id
|
||||
)
|
||||
|
|
|
|||
|
|
@ -335,15 +335,29 @@ func _build_authoritative_result(
|
|||
var bait_topoff: bool = (
|
||||
FishingShopStockType.is_bait_topoff(product_id)
|
||||
)
|
||||
var permanent_unlock: bool = (
|
||||
FishingShopStockType.is_permanent_unlock(product_id, item)
|
||||
)
|
||||
if (
|
||||
item == null
|
||||
or not item.is_valid()
|
||||
or product_id not in (
|
||||
FishingShopStockType.get_stock_item_ids()
|
||||
)
|
||||
or (item.category != ItemDataType.Category.CONSUMABLE and not bait_topoff)
|
||||
or not item.stackable
|
||||
or (not item.usable and not bait_topoff)
|
||||
or (
|
||||
item.category != ItemDataType.Category.CONSUMABLE
|
||||
and not bait_topoff
|
||||
and not permanent_unlock
|
||||
)
|
||||
or (not item.stackable and not permanent_unlock)
|
||||
or (
|
||||
not item.usable
|
||||
and not bait_topoff
|
||||
and not permanent_unlock
|
||||
and not FishingShopStockType.is_passive_supply(
|
||||
product_id
|
||||
)
|
||||
)
|
||||
or current_state >= item.max_stack
|
||||
or current_state + quantity > item.max_stack
|
||||
):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue