Brandling Safari: LAN safari-zone creature catching on the HD-2D engine

- Authoritative 30 Hz server (ENet, SQLite): accounts, characters, wild AI, tall grass /
  water / wandering spawns, fishing, captures, follower chains, clock + weather, LAN beacon
- Client: title / join / character creator / play screens, prediction + reconciliation,
  interpolated players and parties, HD-2D UI (dialogue with Professor Henry, HUD, collection)
- Shared deterministic zone generator, movement, protocol, roster, appearance
- Paper-doll character art pipeline (PixelLab base walk + per-item animation edits)
- Brandling roster from the company list (logo colors, jev types), Blender safari props
- Headless test bot
This commit is contained in:
Gabe
2026-10-02 15:20:27 -05:00
commit 238cd9c6c3
3409 changed files with 100493 additions and 0 deletions

38
server/Spawns.h Normal file
View File

@@ -0,0 +1,38 @@
#pragma once
// Species selection for wild spawns (habitat, rarity, zone type weights and
// time/weather conditions) and the weather Markov chain.
#include "Protocol.h"
#include "Rng.h"
#include "Roster.h"
#include <string>
#include <vector>
namespace bs {
enum class SpawnHabitat { Land = 0, Water = 1 };
inline bool isNight(float hour) { return hour < 5.5f || hour > 19.5f; }
class SpawnTables {
public:
// Rebuilds the cumulative tables when (night, weather) differs from the cached condition.
void update(const Roster& roster, const std::string& zoneId, float hour, Weather weather);
// Returns false when no species fits the habitat.
bool pick(Rng& rng, SpawnHabitat h, uint16_t& species) const;
private:
struct Table {
std::vector<float> cumulative;
std::vector<uint16_t> ids;
};
Table tables_[2];
int key_ = -1;
const Roster* roster_ = nullptr;
};
// Next weather state; called every 3-8 real minutes.
Weather nextWeather(Rng& rng, Weather current, float hour);
} // namespace bs