Skip to content

Commit a281def

Browse files
committed
inferno encounter, shared combat abstractions, zulrah fixes
new inferno encounter (69 waves, prayer switching, pillars, all NPC types). shared osrs_combat_shared.h (hit chance, tbow, barrage AoE, delay formulas). expanded osrs_encounter.h (chase, step-out, pending hits, prayer drain, loadout stats, gear switching). zulrah movement fix (heuristic runs now), dist-0 attack guards. ocean_binding.c for pufferlib-native integration. collision system with LOS, AABB, BFS pathfinding + tests.
1 parent e715f97 commit a281def

24 files changed

Lines changed: 6932 additions & 669 deletions

pufferlib/ocean/osrs_pvp/README.md

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,20 @@
11
# OSRS PvP Environment
22

33
C implementation of Old School RuneScape NH PvP for reinforcement learning.
4+
~1.1M env steps/sec standalone, ~235K+ training SPS on Metal.
45

5-
## Build
6+
## Build and train
67

78
```bash
89
python setup.py build_osrs_pvp --inplace --force
9-
```
10+
python train_pvp.py --no-wandb --total-timesteps 50000000
1011

11-
Zulrah encounter is a separate env that shares headers with osrs_pvp:
12-
```bash
12+
# zulrah (separate build, overwrites _C.so)
1313
python setup.py build_osrs_zulrah --inplace --force
14+
python train_zulrah.py --no-wandb --total-timesteps 500000000
1415
```
1516

16-
## Visual mode
17-
18-
Standalone headed viewer with raylib. supports human play, AI observation, and encounter selection.
19-
20-
```bash
21-
cd pufferlib/ocean/osrs_pvp
22-
make visual
23-
./osrs_pvp_visual --visual # PvP (watch AI vs scripted opponent)
24-
./osrs_pvp_visual --visual --encounter zulrah # Zulrah
25-
./osrs_pvp_visual --visual --human # human control (click to move/attack)
26-
```
27-
28-
requires raylib 5.5 — download from https://github.com/raysan5/raylib/releases and extract to `raylib-5.5_macos/` (or adjust `RAYLIB_DIR` in Makefile for linux).
17+
Two bindings: `binding.c` (metal vecenv.h) and `ocean_binding.c` (PufferLib env_binding.h).
2918

3019
## Data assets
3120

150 KB
Binary file not shown.
1.47 MB
Binary file not shown.

pufferlib/ocean/osrs_pvp/data/item_models.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ typedef struct {
1111
uint8_t has_sleeves;
1212
} ItemModelMapping;
1313

14-
#define ITEM_MODEL_COUNT 94
14+
#define ITEM_MODEL_COUNT 99
1515

1616
static const ItemModelMapping ITEM_MODEL_MAP[] = {
1717
{ 10828, 21938, 917504, 0 },
@@ -108,6 +108,11 @@ static const ItemModelMapping ITEM_MODEL_MAP[] = {
108108
{ 2497, 2507, 917596, 0 },
109109
{ 12788, 48061, 917597, 0 },
110110
{ 10499, 20454, 917598, 0 },
111+
{ 22326, 35751, 917599, 0 },
112+
{ 22327, 35750, 917600, 0 },
113+
{ 22328, 35752, 917601, 0 },
114+
{ 4224, 5198, 917602, 0 },
115+
{ 13237, 29396, 917603, 0 },
111116
};
112117

113118
#endif /* ITEM_MODELS_H */

pufferlib/ocean/osrs_pvp/data/npc_models.h

Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/**
2-
* @fileoverview NPC model/animation mappings for Zulrah encounter rendering.
2+
* @fileoverview NPC model/animation mappings for encounter rendering.
33
*
44
* Maps NPC definition IDs to cache model IDs and animation sequence IDs.
5-
* Generated data — edit export scripts to regenerate.
5+
* Generated by scripts/export_inferno_npcs.py — do not edit.
66
*/
77

88
#ifndef NPC_MODELS_H
@@ -15,13 +15,14 @@ typedef struct {
1515
uint32_t model_id;
1616
uint32_t idle_anim;
1717
uint32_t attack_anim;
18+
uint32_t walk_anim; /* walk cycle animation; 65535 = use idle_anim */
1819
} NpcModelMapping;
1920

2021
/* zulrah forms + snakeling */
21-
static const NpcModelMapping NPC_MODEL_MAP[] = {
22-
{2042, 14408, 5069, 5068}, /* green zulrah (ranged) */
23-
{2043, 14409, 5069, 5068}, /* red zulrah (melee) */
24-
{2044, 14407, 5069, 5068}, /* blue zulrah (magic) */
22+
static const NpcModelMapping NPC_MODEL_MAP_ZULRAH[] = {
23+
{2042, 14408, 5069, 5068, 65535}, /* green zulrah (ranged) */
24+
{2043, 14409, 5069, 5068, 65535}, /* red zulrah (melee) */
25+
{2044, 14407, 5069, 5068, 65535}, /* blue zulrah (magic) */
2526
};
2627

2728
/* snakeling model + animations (NPC 2045 melee, 2046 magic — same model) */
@@ -34,27 +35,104 @@ static const NpcModelMapping NPC_MODEL_MAP[] = {
3435

3536
/* zulrah spotanim (projectile/cloud) model IDs */
3637
#define GFX_RANGED_PROJ_MODEL 20390 /* GFX 1044 ranged projectile */
37-
#define GFX_CLOUD_PROJ_MODEL 11221 /* GFX 1045 cloud projectile (flies to target) */
38+
#define GFX_CLOUD_PROJ_MODEL 11221 /* GFX 1045 cloud projectile */
3839
#define GFX_MAGIC_PROJ_MODEL 26593 /* GFX 1046 magic projectile */
39-
#define GFX_TOXIC_CLOUD_MODEL 4086 /* object 11700 — venom cloud on ground (3x3) */
40-
#define GFX_SNAKELING_SPAWN_MODEL 20390 /* GFX 1047 spawn orb (same mesh as 1044, white recolor) */
40+
#define GFX_TOXIC_CLOUD_MODEL 4086 /* object 11700 */
41+
#define GFX_SNAKELING_SPAWN_MODEL 20390 /* GFX 1047 spawn orb */
4142

4243
/* zulrah animation sequence IDs */
4344
#define ZULRAH_ANIM_ATTACK 5068
4445
#define ZULRAH_ANIM_IDLE 5069
45-
#define ZULRAH_ANIM_DIVE 5072 /* DIG_ANIM_ID from RuneLite plugin — sinks into water */
46-
#define ZULRAH_ANIM_SURFACE 5071 /* INITIAL_RISE_ANIM_ID — first appearance */
47-
#define ZULRAH_ANIM_RISE 5073 /* RISE_ANIM_ID — subsequent phase surfaces */
48-
#define ZULRAH_ANIM_5070 5070 /* unknown — possibly unused */
49-
#define ZULRAH_ANIM_5806 5806 /* melee whip variant 1 */
50-
#define ZULRAH_ANIM_5807 5807 /* melee whip variant 2 */
51-
52-
/* GFX 1047 snakeling spawn orb animation */
46+
#define ZULRAH_ANIM_DIVE 5072
47+
#define ZULRAH_ANIM_SURFACE 5071
48+
#define ZULRAH_ANIM_RISE 5073
49+
#define ZULRAH_ANIM_5070 5070
50+
#define ZULRAH_ANIM_5806 5806
51+
#define ZULRAH_ANIM_5807 5807
5352
#define GFX_SNAKELING_SPAWN_ANIM 5358
5453

54+
/* ================================================================ */
55+
/* inferno NPC model/animation mappings */
56+
/* ================================================================ */
57+
58+
static const NpcModelMapping NPC_MODEL_MAP_INFERNO[] = {
59+
{7691, 0xC1E0B, 7573, 7574, 7572}, /* Jal-Nib (nibbler) */
60+
{7692, 0xC1E0C, 7577, 7578, 7577}, /* Jal-MejRah (bat) — walk = idle */
61+
{7693, 0xC1E0D, 7586, 7581, 7587}, /* Jal-Ak (blob) */
62+
{7694, 0xC1E0E, 7586, 65535, 7587}, /* Jal-Ak-Rek-Ket (blob melee split) */
63+
{7695, 0xC1E0F, 7586, 65535, 7587}, /* Jal-Ak-Rek-Xil (blob range split) */
64+
{7696, 0xC1E10, 7586, 65535, 7587}, /* Jal-Ak-Rek-Mej (blob mage split) */
65+
{7697, 0xC1E11, 7595, 7597, 7596}, /* Jal-ImKot (meleer) */
66+
{7698, 0xC1E12, 7602, 7605, 7603}, /* Jal-Xil (ranger) */
67+
{7699, 0xC1E13, 7609, 7610, 7608}, /* Jal-Zek (mager) */
68+
{7700, 0xC1E14, 7589, 7593, 7588}, /* JalTok-Jad */
69+
{7701, 0xC1E15, 2636, 65535, 2634}, /* Yt-HurKot (jad healer) */
70+
{7706, 0xC1E1A, 7564, 7566, 65535}, /* TzKal-Zuk — no walk */
71+
{7707, 0xC1E1B, 7567, 65535, 7567}, /* Zuk shield */
72+
{7708, 0xC1E1C, 2867, 65535, 2863}, /* Jal-MejJak (zuk healer) */
73+
};
74+
75+
/* inferno NPC walk animation IDs */
76+
#define INF_WALK_ANIM_NIBBLER 7572
77+
#define INF_WALK_ANIM_BAT 7577
78+
#define INF_WALK_ANIM_BLOB 7587
79+
#define INF_WALK_ANIM_BLOB_MELEE_SPLIT 7587
80+
#define INF_WALK_ANIM_BLOB_RANGE_SPLIT 7587
81+
#define INF_WALK_ANIM_BLOB_MAGE_SPLIT 7587
82+
#define INF_WALK_ANIM_MELEER 7596
83+
#define INF_WALK_ANIM_RANGER 7603
84+
#define INF_WALK_ANIM_MAGER 7608
85+
#define INF_WALK_ANIM_JALTOK_JAD 7588
86+
#define INF_WALK_ANIM_JAD_HEALER 2634
87+
#define INF_WALK_ANIM_ZUK_SHIELD 7567
88+
#define INF_WALK_ANIM_ZUK_HEALER 2863
89+
90+
/* inferno spotanim (projectile/effect) model + animation IDs */
91+
#define INF_GFX_157_MODEL 3116 /* Jad magic hit */
92+
#define INF_GFX_157_ANIM 693
93+
#define INF_GFX_447_MODEL 9334 /* Jad ranged projectile (fireball) */
94+
#define INF_GFX_447_ANIM 2658
95+
#define INF_GFX_448_MODEL 9337 /* Jad magic projectile */
96+
#define INF_GFX_448_ANIM 2659
97+
#define INF_GFX_451_MODEL 9342 /* Jad ranged hit */
98+
#define INF_GFX_451_ANIM 2660
99+
#define INF_GFX_942_MODEL 19374 /* Dragon arrow projectile (twisted bow) */
100+
#define INF_GFX_942_ANIM 5233
101+
#define INF_GFX_1374_MODEL 3082 /* Bat ranged projectile */
102+
#define INF_GFX_1374_ANIM 660
103+
#define INF_GFX_1375_MODEL 33006 /* Zuk magic projectile */
104+
#define INF_GFX_1375_ANIM 7571
105+
#define INF_GFX_1376_MODEL 33007 /* Zuk ranged projectile */
106+
#define INF_GFX_1376_ANIM 7571
107+
#define INF_GFX_1377_MODEL 33013 /* Ranger ranged projectile */
108+
#define INF_GFX_1378_MODEL 33015 /* Ranger ranged hit */
109+
#define INF_GFX_1378_ANIM 7615
110+
#define INF_GFX_1379_MODEL 33016 /* Mager magic projectile */
111+
#define INF_GFX_1379_ANIM 7614
112+
#define INF_GFX_1380_MODEL 33008 /* Mager magic hit */
113+
#define INF_GFX_1380_ANIM 7616
114+
#define INF_GFX_1381_MODEL 33009 /* Zuk typeless hit (falling rocks?) */
115+
#define INF_GFX_1381_ANIM 7616
116+
#define INF_GFX_1382_MODEL 33017 /* Blob melee */
117+
#define INF_GFX_1382_ANIM 7614
118+
#define INF_GFX_1383_MODEL 26293 /* Blob ranged */
119+
#define INF_GFX_1383_ANIM 366
120+
#define INF_GFX_1384_MODEL 3136 /* Blob magic */
121+
#define INF_GFX_1385_MODEL 3142 /* Healer magic attack */
122+
#define INF_GFX_1385_ANIM 366
123+
124+
/* inferno pillar models — "Rocky support" objects 30284-30287, 4 HP levels */
125+
#define INF_PILLAR_MODEL_100 33044 /* object 30284 — full health */
126+
#define INF_PILLAR_MODEL_75 33043 /* object 30285 — 75% HP */
127+
#define INF_PILLAR_MODEL_50 33042 /* object 30286 — 50% HP */
128+
#define INF_PILLAR_MODEL_25 33045 /* object 30287 — 25% HP */
129+
55130
static const NpcModelMapping* npc_model_lookup(uint16_t npc_id) {
56-
for (int i = 0; i < (int)(sizeof(NPC_MODEL_MAP) / sizeof(NPC_MODEL_MAP[0])); i++) {
57-
if (NPC_MODEL_MAP[i].npc_id == npc_id) return &NPC_MODEL_MAP[i];
131+
for (int i = 0; i < (int)(sizeof(NPC_MODEL_MAP_ZULRAH) / sizeof(NPC_MODEL_MAP_ZULRAH[0])); i++) {
132+
if (NPC_MODEL_MAP_ZULRAH[i].npc_id == npc_id) return &NPC_MODEL_MAP_ZULRAH[i];
133+
}
134+
for (int i = 0; i < (int)(sizeof(NPC_MODEL_MAP_INFERNO) / sizeof(NPC_MODEL_MAP_INFERNO[0])); i++) {
135+
if (NPC_MODEL_MAP_INFERNO[i].npc_id == npc_id) return &NPC_MODEL_MAP_INFERNO[i];
58136
}
59137
return NULL;
60138
}

0 commit comments

Comments
 (0)