diff --git a/modules/cstrike/cstrike/CstrikeNatives.cpp b/modules/cstrike/cstrike/CstrikeNatives.cpp index fd43cb86..1940abbf 100644 --- a/modules/cstrike/cstrike/CstrikeNatives.cpp +++ b/modules/cstrike/cstrike/CstrikeNatives.cpp @@ -849,7 +849,8 @@ static cell AMX_NATIVE_CALL cs_reset_user_model(AMX *amx, cell *params) // native cs_get_hostage_foll(index); static cell AMX_NATIVE_CALL cs_get_hostage_follow(AMX *amx, cell *params) { - GET_OFFSET("CBaseMonster" , m_hTargetEnt); + GET_OFFSET("CBaseMonster", m_hTargetEnt); + GET_OFFSET("CHostage" , m_improv ); int index = params[1]; @@ -858,7 +859,25 @@ static cell AMX_NATIVE_CALL cs_get_hostage_follow(AMX *amx, cell *params) CHECK_HOSTAGE(pHostage); - edict_t *pEntity = get_pdata(pHostage, m_hTargetEnt).Get(); + void *pImprov = get_pdata(pHostage, m_improv); + edict_t *pEntity = nullptr; + + if (pImprov) // Specific to CS + { + GET_OFFSET("CHostageImprov", m_behavior); + GET_OFFSET("CHostageImprov", m_followState); + GET_OFFSET("SimpleStateMachine", m_state); // +4 for virtual table pointer of IImprovEvent. + GET_OFFSET("HostageFollowState", m_leader); + + if (get_pdata(pImprov, m_behavior + 4 + m_state) == reinterpret_cast(pImprov) + m_followState) + { + pEntity = get_pdata(pImprov, m_followState + m_leader).Get(); + } + } + else + { + pEntity = get_pdata(pHostage, m_hTargetEnt).Get(); + } return pEntity ? ENTINDEX(pEntity) : 0; } @@ -867,6 +886,7 @@ static cell AMX_NATIVE_CALL cs_get_hostage_follow(AMX *amx, cell *params) static cell AMX_NATIVE_CALL cs_set_hostage_follow(AMX *amx, cell *params) { GET_OFFSET("CBaseMonster", m_hTargetEnt); + GET_OFFSET("CHostage" , m_improv ); int index = params[1]; int target = params[2]; @@ -881,7 +901,36 @@ static cell AMX_NATIVE_CALL cs_set_hostage_follow(AMX *amx, cell *params) CHECK_HOSTAGE(pHostage); - get_pdata(pHostage, m_hTargetEnt).Set(target ? GETEDICT(target) : nullptr); + void *pImprov = get_pdata(pHostage, m_improv); + + if (pImprov) // Specific to CS + { + GET_OFFSET("CHostageImprov", m_behavior); + GET_OFFSET("CHostageImprov", m_followState); + GET_OFFSET("CHostageImprov", m_idleState); + GET_OFFSET("HostageFollowState", m_leader); + GET_OFFSET("SimpleStateMachine", m_state); // +4 for virtual table pointer of IImprovEvent. + GET_OFFSET("SimpleStateMachine", m_stateTimer); // + + if (target) + { + set_pdata(pImprov, m_behavior + 4 + m_state, reinterpret_cast(pImprov) + m_followState); + set_pdata(pImprov, m_behavior + 4 + m_stateTimer, gpGlobals->time); + + get_pdata(pImprov, m_followState + m_leader).Set(GETEDICT(target)); + } + else + { + set_pdata(pImprov, m_behavior + 4 + m_state, reinterpret_cast(pImprov) + m_idleState); + set_pdata(pImprov, m_behavior + 4 + m_stateTimer, gpGlobals->time); + + get_pdata(pImprov, m_followState + m_leader).Set(nullptr); + } + } + else + { + get_pdata(pHostage, m_hTargetEnt).Set(target ? GETEDICT(target) : nullptr); + } return 1; } @@ -1365,6 +1414,7 @@ static cell AMX_NATIVE_CALL cs_set_user_hostagekills(AMX *amx, cell *params) static cell AMX_NATIVE_CALL cs_get_hostage_lastuse(AMX *amx, cell *params) { GET_OFFSET("CHostage", m_flPathAcquired); + GET_OFFSET("CHostage", m_improv); int index = params[1]; @@ -1373,6 +1423,16 @@ static cell AMX_NATIVE_CALL cs_get_hostage_lastuse(AMX *amx, cell *params) CHECK_HOSTAGE(pHostage); + void *pImprov = get_pdata(pHostage, m_improv); + + if (pImprov) // Specific to CZ + { + GET_OFFSET("CHostageImprov", m_behavior); + GET_OFFSET("SimpleStateMachine", m_stateTimer); // +4 for virtual table pointer of IImprovEvent. + + return amx_ftoc(get_pdata(pImprov, m_behavior + 4 + m_stateTimer + 0)); // m_timestamp + } + return amx_ftoc(get_pdata(pHostage, m_flPathAcquired)); } @@ -1380,6 +1440,7 @@ static cell AMX_NATIVE_CALL cs_get_hostage_lastuse(AMX *amx, cell *params) static cell AMX_NATIVE_CALL cs_set_hostage_lastuse(AMX *amx, cell *params) { GET_OFFSET("CHostage", m_flPathAcquired); + GET_OFFSET("CHostage", m_improv); int index = params[1]; @@ -1388,6 +1449,16 @@ static cell AMX_NATIVE_CALL cs_set_hostage_lastuse(AMX *amx, cell *params) CHECK_HOSTAGE(pHostage); + void *pImprov = get_pdata(pHostage, m_improv); + + if (pImprov) // Specific to CZ + { + GET_OFFSET("CHostageImprov", m_behavior); + GET_OFFSET("SimpleStateMachine", m_stateTimer); // +4 for virtual table pointer of IImprovEvent. + + return amx_ftoc(get_pdata(pImprov, m_behavior + 4 + m_stateTimer + 0)); // m_timestamp + + } set_pdata(pHostage, m_flPathAcquired, amx_ctof(params[2])); return 1; diff --git a/modules/cstrike/cstrike/CstrikeUtils.h b/modules/cstrike/cstrike/CstrikeUtils.h index 7275cf3e..c5100d39 100644 --- a/modules/cstrike/cstrike/CstrikeUtils.h +++ b/modules/cstrike/cstrike/CstrikeUtils.h @@ -78,7 +78,7 @@ bool UTIL_CheckForPublic(const char *publicname); static int member = -1; \ if (member == -1) \ { \ - if (!OffsetConfig->GetOffsetByClass(classname, #member, &member) || !member)\ + if (!OffsetConfig->GetOffsetByClass(classname, #member, &member) || member < 0)\ { \ MF_LogError(amx, AMX_ERR_NATIVE, "Invalid %s offset. Native %s is disabled", #member, __FUNCTION__);\ return 0; \ @@ -89,7 +89,7 @@ bool UTIL_CheckForPublic(const char *publicname); static int member = -1; \ if (member == -1) \ { \ - if (!OffsetConfig->GetOffsetByClass(classname, #member, &member) || !member)\ + if (!OffsetConfig->GetOffsetByClass(classname, #member, &member) || member < 0)\ { \ return; \ } \ diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index 3171ee75..8d3e93a3 100755 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -166,8 +166,6 @@ native cs_set_user_deaths(index, newdeaths, bool:scoreboard = true); * * @note Hostages can theoretically follow any entity in the game, so the * returned entity index is not necessarily a client index. - * @note This native does not work on Condition Zero, which has a different - * hostage AI than other versions of Counter-Strike. * * @param index Hostage entity index * @@ -182,8 +180,6 @@ native cs_get_hostage_foll(index); * * @note Hostages can theoretically follow any entity in the game, so the * followedindex does not have to be a client index. - * @note This native does not work on Condition Zero, which has a different - * hostage AI than other versions of Counter-Strike. * * @param index Hostage entity index * @param followedindex New entity to follow