@starweave/roblox
v0.1.4
Published
Vedic astrology-driven NPC behavior SDK for Roblox
Maintainers
Readme
@starweave/roblox
Vedic astrology-driven NPC behavior SDK for Roblox. Give your NPCs unique personalities, moods, relationships, and daily routines — all computed from birth charts.
Install
roblox-ts (TypeScript):
npm install @starweave/robloxLuau (native):
Download Starweave.rbxm from Releases and insert it into ReplicatedStorage.
Quick Start
import { NPCSpawner, DEFAULT_SPAWNER_CONFIG } from "@starweave/roblox";
// 1. Create a spawner with your API credentials
const spawner = new NPCSpawner({
...DEFAULT_SPAWNER_CONFIG,
api_base_url: "https://starweave.whimco.com",
api_key: "your-api-key",
});
// 2. Spawn an NPC — birth_time determines their entire personality
await spawner.spawnNPC({
npc_id: "merchant_01",
birth_time: "1985-06-15T14:30:00Z",
model: workspace.NPCs.Merchant,
spawn_position: new Vector3(10, 5, 20),
});
// 3. Start the behavior loop
spawner.startUpdateLoop();
// 4. Read NPC state anytime
const behavior = spawner.getNPCBehavior("merchant_01");
// → {
// current_activity: "trading",
// mood_expression: "content",
// movement_style: "walk",
// social_disposition: "friendly",
// is_busy: false,
// }How It Works
Each NPC gets a birth time (ISO 8601 string). The Starweave engine computes a Vedic birth chart and derives:
- Static Profile (permanent): base personality traits, behavioral flags, preferred activities, daily schedule variance
- Dynamic State (changes over time): current dasha period, active planetary transits, mood, motivation, temporary trait shifts
- Relational State (per relationship): trust, familiarity, social disposition toward players and other NPCs
The SDK handles all API calls, caching, and state management. You just read the results.
API
NPCSpawner
The main entry point. Manages NPC lifecycle, behavior updates, and proximity detection.
const spawner = new NPCSpawner(config: SpawnerConfig);SpawnerConfig
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| api_base_url | string | required | Your Starweave API URL |
| api_key | string | required | API key for authentication |
| update_interval | number | 5 | Seconds between behavior recalculations |
| dynamic_refresh | number | 300 | Seconds between dynamic state API refreshes |
| proximity_radius | number | 20 | Studs for player/NPC detection |
| proximity_check_interval | number | 1 | Seconds between proximity scans |
| cache_ttl_seconds | number | 300 | Seconds to cache API responses |
Use DEFAULT_SPAWNER_CONFIG to start with sensible defaults and override what you need:
const spawner = new NPCSpawner({
...DEFAULT_SPAWNER_CONFIG,
api_base_url: "https://starweave.whimco.com",
api_key: "your-api-key",
proximity_radius: 50, // wider awareness range
});Methods
// Spawn a single NPC
await spawner.spawnNPC({
npc_id: "guard_01",
birth_time: "1972-03-22T08:15:00Z",
model: workspace.NPCs.Guard,
spawn_position: new Vector3(0, 5, 0), // optional
}): Promise<boolean>
// Spawn multiple NPCs
await spawner.spawnBatch(definitions): Promise<number> // returns count spawned
// Start the global update loop (call once after spawning)
spawner.startUpdateLoop(): void
// Query NPC state
spawner.getNPCBehavior(npcId): BehaviorState | undefined
spawner.getNPCProfile(npcId): StaticProfile | undefined
spawner.getController(npcId): NPCBehaviorController | undefined
// Cleanup
spawner.removeNPC(npcId): void
spawner.destroy(): voidNPCBehaviorController
Lower-level controller for a single NPC. Use this if you want manual control instead of NPCSpawner.
const controller = new NPCBehaviorController(config, vedicService);
await controller.initialize();
// Called every frame (or on a timer)
controller.update(dt);
// Proximity events
await controller.onPlayerProximity(player);
await controller.onNPCProximity(otherNpcId, otherProfile);
// Record interactions (trades, combat, conversations)
controller.recordInteraction(targetId, "traded_sword");
// Read state
controller.getBehavior(): BehaviorState
controller.getStaticProfile(): StaticProfile | undefined
controller.getDynamicState(): DynamicState | undefined
controller.getRelationship(targetId): RelationalState | undefinedBehaviorState
What you read from an NPC at any moment:
interface BehaviorState {
current_activity: string; // "idle", "trading", "patrolling", "meditating", ...
target_entity?: string; // player/NPC they're focused on
mood_expression: string; // "joyful", "content", "neutral", "anxious", "angry"
movement_style: "idle" | "walk" | "run" | "sneak" | "patrol";
social_disposition: "friendly" | "neutral" | "wary" | "hostile";
is_busy: boolean;
}VedicService
Direct API client if you want to make raw calls:
const service = new VedicService({
baseUrl: "https://starweave.whimco.com",
apiKey: "your-api-key",
cacheTtlSeconds: 300,
});
const profile = await service.getStaticProfile({
npc_id: "npc_01",
birth_time: "1990-04-15T06:30:00Z",
});
const dynamic = await service.getDynamicState({
npc_id: "npc_01",
current_time: os.date("!%Y-%m-%dT%H:%M:%SZ"),
static_profile: profile,
});
service.clearCache();
service.clearCacheForNPC("npc_01");Birth Time Guide
Birth time is the only input that matters. It determines everything about an NPC's personality through Vedic astrology:
- Lagna (Ascendant): Core personality archetype (12 types)
- Moon Nakshatra: Emotional texture and behavioral nuance (27 types)
- Planetary Aspects: Behavioral flags like
territorial,merchant,healer - Dasha Period: Current life phase and motivation (changes over time)
Tips for variety:
- Spread birth times across a 120-year window (
1920-01-01to2040-01-01) — NPCs born in the same decade will share similar dasha phases - Different birth times on the same day still produce different lagnas (ascendant changes every ~2 hours)
- Store birth times in your NPC data — they never change and the static profile is computed once
// Good: diverse birth times
const npcs = [
{ npc_id: "elder", birth_time: "1935-11-02T04:00:00Z", model: ... },
{ npc_id: "merchant", birth_time: "1978-07-19T16:45:00Z", model: ... },
{ npc_id: "guard", birth_time: "2001-01-30T09:20:00Z", model: ... },
];Configuration Tuning
| Scenario | update_interval | dynamic_refresh | proximity_radius | cache_ttl | |----------|----------------|----------------|-----------------|-----------| | Active NPCs (shops, quest givers) | 2-3s | 300s | 20 studs | 300s | | Background NPCs (crowds, ambient) | 10-30s | 600s | 50 studs | 600s | | Large scenes (50+ NPCs) | 5s | 900s | 30 studs | 900s |
Key rule: dynamic_refresh should equal cache_ttl_seconds. Refreshing faster than the cache wastes API calls; refreshing slower causes stale state.
Types
All Vedic types are exported for TypeScript users:
import type {
StaticProfile,
DynamicState,
RelationalState,
TraitBlock,
BehavioralFlag,
PlanetaryPosition,
DashaPeriod,
Transit,
ZodiacSign,
Nakshatra,
Planet,
} from "@starweave/roblox";TraitBlock
The five core personality dimensions (0.0 to 1.0):
interface TraitBlock {
openness: number; // curiosity, willingness to explore
loyalty: number; // faithfulness, attachment strength
aggression: number; // combativeness, territorial instinct
fear: number; // anxiety, caution level
deception_tendency: number; // cunning, willingness to deceive
}License
MIT — Whimco Studio
