diff options
Diffstat (limited to '')
| -rw-r--r-- | src/server.cpp | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/src/server.cpp b/src/server.cpp index 19be144..c2864c8 100644 --- a/src/server.cpp +++ b/src/server.cpp | |||
| @@ -50,6 +50,7 @@ static int g_srv_relationship = -1; | |||
| 50 | static int g_srv_followtarget = -1; | 50 | static int g_srv_followtarget = -1; |
| 51 | static int g_srv_spawnflags = -1; | 51 | static int g_srv_spawnflags = -1; |
| 52 | static int g_srv_hacked = -1; | 52 | static int g_srv_hacked = -1; |
| 53 | static int g_srv_npcstate = -1; | ||
| 53 | static bool g_srv_ready = false; | 54 | static bool g_srv_ready = false; |
| 54 | static bool g_srv_checked = false; | 55 | static bool g_srv_checked = false; |
| 55 | 56 | ||
| @@ -139,15 +140,16 @@ bool resolve_server_netvars() { | |||
| 139 | // CBaseEntity::m_spawnflags is a DEFINE_KEYFIELD at a low offset. | 140 | // CBaseEntity::m_spawnflags is a DEFINE_KEYFIELD at a low offset. |
| 140 | g_srv_spawnflags = datamap_offset("m_spawnflags", FIELD_INTEGER, 0x4); | 141 | g_srv_spawnflags = datamap_offset("m_spawnflags", FIELD_INTEGER, 0x4); |
| 141 | g_srv_hacked = datamap_offset("m_bHackedByAlyx", FIELD_BOOLEAN); | 142 | g_srv_hacked = datamap_offset("m_bHackedByAlyx", FIELD_BOOLEAN); |
| 143 | g_srv_npcstate = datamap_offset("m_NPCState", FIELD_INTEGER); | ||
| 142 | g_srv_ready = g_srv_health > 0; | 144 | g_srv_ready = g_srv_health > 0; |
| 143 | if (g_srv_ready) { | 145 | if (g_srv_ready) { |
| 144 | logf("server datamap (%s): health=%d maxhealth=%d lifeste=%d " | 146 | logf("server datamap (%s): health=%d maxhealth=%d lifeste=%d " |
| 145 | "modelindex=%d absvel=%d vel=%d activeweapon=%d relationship=%d " | 147 | "modelindex=%d absvel=%d vel=%d activeweapon=%d relationship=%d " |
| 146 | "followtarget=%d spawnflags=%d hacked=%d", | 148 | "followtarget=%d spawnflags=%d hacked=%d npcstate=%d", |
| 147 | g_server.path.c_str(), g_srv_health, g_srv_maxhealth, g_srv_lifestate, | 149 | g_server.path.c_str(), g_srv_health, g_srv_maxhealth, g_srv_lifestate, |
| 148 | g_srv_modelindex, g_srv_absvelocity, g_srv_velocity, | 150 | g_srv_modelindex, g_srv_absvelocity, g_srv_velocity, |
| 149 | g_srv_activeweapon, g_srv_relationship, g_srv_followtarget, | 151 | g_srv_activeweapon, g_srv_relationship, g_srv_followtarget, |
| 150 | g_srv_spawnflags, g_srv_hacked); | 152 | g_srv_spawnflags, g_srv_hacked, g_srv_npcstate); |
| 151 | fail_logged = false; | 153 | fail_logged = false; |
| 152 | } else if (!fail_logged) { | 154 | } else if (!fail_logged) { |
| 153 | fail_logged = true; | 155 | fail_logged = true; |
| @@ -254,6 +256,18 @@ int server_npc_relation(int idx, int local_idx) { | |||
| 254 | return class_relation; | 256 | return class_relation; |
| 255 | } | 257 | } |
| 256 | 258 | ||
| 259 | // NPC_STATE_SCRIPT = 4 (ai_npcstate.h). Scripted NPCs are passive: cutscene | ||
| 260 | // actors, Kleiner's Lamarr, scripted soldiers standing down, and so on. | ||
| 261 | int server_npc_state(int idx) { | ||
| 262 | if (!g_srv_ready || g_srv_npcstate < 0) | ||
| 263 | return -1; | ||
| 264 | void *base = nullptr; | ||
| 265 | server_entity_health(idx, nullptr, nullptr, &base); | ||
| 266 | if (!base) | ||
| 267 | return -1; | ||
| 268 | return *(int *)((uintptr_t)base + g_srv_npcstate); | ||
| 269 | } | ||
| 270 | |||
| 257 | bool server_npc_has_follow_target(int idx) { | 271 | bool server_npc_has_follow_target(int idx) { |
| 258 | if (!g_srv_ready || g_srv_followtarget < 0) | 272 | if (!g_srv_ready || g_srv_followtarget < 0) |
| 259 | return false; | 273 | return false; |
