mirror of
https://github.com/s1lentq/ReGameDLL_CS.git
synced 2024-12-27 07:05:38 +03:00
7372573c89
Ignore dormant players Minor refactoring
598 lines
14 KiB
C++
598 lines
14 KiB
C++
#include "precompiled.h"
|
|
|
|
CCareerTaskManager *TheCareerTasks = nullptr;
|
|
|
|
CCareerTask *CPreventDefuseTask::NewTask(const char *taskName, GameEventType event, const char *weaponName, int n, bool mustLive, bool crossRounds, int id, bool isComplete)
|
|
{
|
|
CPreventDefuseTask *pNewTask = new CPreventDefuseTask(taskName, event, weaponName, n, mustLive, crossRounds, id, isComplete);
|
|
|
|
pNewTask->m_bombPlantedThisRound = false;
|
|
pNewTask->m_defuseStartedThisRound = false;
|
|
|
|
return reinterpret_cast<CCareerTask *>(pNewTask);
|
|
}
|
|
|
|
CPreventDefuseTask::CPreventDefuseTask(const char *taskName, GameEventType event, const char *weaponName, int n, bool mustLive, bool crossRounds, int id, bool isComplete) :
|
|
CCareerTask(taskName, event, weaponName, n, mustLive, crossRounds, id, isComplete)
|
|
{
|
|
m_bombPlantedThisRound = false;
|
|
m_defuseStartedThisRound = false;
|
|
}
|
|
|
|
void CPreventDefuseTask::Reset()
|
|
{
|
|
m_bombPlantedThisRound = false;
|
|
m_defuseStartedThisRound = false;
|
|
|
|
CCareerTask::Reset();
|
|
}
|
|
|
|
void CPreventDefuseTask::OnEvent(GameEventType event, CBasePlayer *pAttacker, CBasePlayer *pVictim)
|
|
{
|
|
if (IsComplete())
|
|
return;
|
|
|
|
if (event == EVENT_BOMB_PLANTED)
|
|
{
|
|
m_bombPlantedThisRound = true;
|
|
}
|
|
else if (event == EVENT_BOMB_DEFUSING)
|
|
{
|
|
m_defuseStartedThisRound = true;
|
|
}
|
|
|
|
CCareerTask::OnEvent(event, pAttacker, pVictim);
|
|
|
|
if (event >= EVENT_ROUND_DRAW && event <= EVENT_ROUND_LOSS)
|
|
{
|
|
m_bombPlantedThisRound = false;
|
|
m_defuseStartedThisRound = false;
|
|
}
|
|
}
|
|
|
|
CCareerTask *CCareerTask::NewTask(const char *taskName, GameEventType event, const char *weaponName, int n, bool mustLive, bool crossRounds, int id, bool isComplete)
|
|
{
|
|
CCareerTask *pTask = new CCareerTask(taskName, event, weaponName, n, mustLive, crossRounds, id, isComplete);
|
|
return pTask;
|
|
}
|
|
|
|
CCareerTask::CCareerTask(const char *taskName, GameEventType event, const char *weaponName, int n, bool mustLive, bool crossRounds, int id, bool isComplete)
|
|
{
|
|
m_isComplete = isComplete;
|
|
m_event = event;
|
|
m_eventsNeeded = n;
|
|
|
|
m_name = taskName;
|
|
m_eventsSeen = 0;
|
|
m_mustLive = mustLive;
|
|
m_crossRounds = crossRounds;
|
|
m_diedThisRound = false;
|
|
m_id = id;
|
|
m_weaponId = AliasToWeaponID(weaponName);
|
|
m_weaponClassId = AliasToWeaponClass(weaponName);
|
|
|
|
m_rescuer = (Q_stricmp(taskName, "stoprescue") == 0);
|
|
m_defuser = (Q_stricmp(taskName, "killdefuser") == 0);
|
|
m_vip = (Q_stricmp(taskName, "killvip") == 0);
|
|
|
|
if (event == EVENT_ALL_HOSTAGES_RESCUED)
|
|
{
|
|
m_mustLive = true;
|
|
m_crossRounds = false;
|
|
}
|
|
|
|
if (m_isComplete)
|
|
{
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgCZCareer);
|
|
WRITE_STRING("TASKDONE");
|
|
WRITE_BYTE(m_id);
|
|
MESSAGE_END();
|
|
}
|
|
}
|
|
|
|
void CCareerTask::Reset()
|
|
{
|
|
m_eventsSeen = 0;
|
|
m_isComplete = false;
|
|
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgCZCareer);
|
|
WRITE_STRING("TASKUNDONE");
|
|
WRITE_BYTE(m_id);
|
|
MESSAGE_END();
|
|
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgCZCareer);
|
|
WRITE_STRING("TASKPART");
|
|
WRITE_BYTE(m_id);
|
|
WRITE_SHORT(m_eventsSeen);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void CCareerTask::SendPartialNotification()
|
|
{
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgCZCareer);
|
|
WRITE_STRING("TASKPART");
|
|
WRITE_BYTE(m_id);
|
|
WRITE_SHORT(m_eventsSeen);
|
|
MESSAGE_END();
|
|
|
|
UTIL_LogPrintf("Career Task Partial %d %d\n", m_id, m_eventsSeen);
|
|
}
|
|
|
|
void CCareerTask::OnWeaponKill(int weaponId, int weaponClassId, bool headshot, bool killerHasShield, CBasePlayer *pAttacker, CBasePlayer *pVictim)
|
|
{
|
|
if (m_isComplete || (m_event != EVENT_KILL && (m_event != EVENT_HEADSHOT || !headshot)))
|
|
return;
|
|
|
|
if (!pVictim || (m_defuser && !pVictim->m_bIsDefusing) || (m_vip && !pVictim->m_bIsVIP))
|
|
return;
|
|
|
|
if (m_rescuer)
|
|
{
|
|
int hostagesCount = 0;
|
|
CHostage *pHostage = nullptr;
|
|
|
|
while ((pHostage = UTIL_FindEntityByClassname(pHostage, "hostage_entity")))
|
|
{
|
|
if (!pHostage->IsAlive())
|
|
continue;
|
|
|
|
#ifndef REGAMEDLL_FIXES
|
|
if (!pHostage->IsFollowingSomeone())
|
|
continue;
|
|
|
|
if (pHostage->m_target == pVictim)
|
|
#else
|
|
if (pHostage->IsFollowing(pVictim))
|
|
#endif
|
|
hostagesCount++;
|
|
}
|
|
|
|
if (!hostagesCount)
|
|
return;
|
|
}
|
|
|
|
if (m_weaponId == WEAPON_SHIELDGUN)
|
|
{
|
|
if (!killerHasShield)
|
|
return;
|
|
}
|
|
else if (m_weaponId)
|
|
{
|
|
if (m_weaponId != weaponId)
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (!m_weaponClassId || m_weaponClassId != weaponClassId)
|
|
return;
|
|
}
|
|
|
|
m_eventsSeen++;
|
|
SendPartialNotification();
|
|
}
|
|
|
|
void CCareerTask::OnWeaponInjury(int weaponId, int weaponClassId, bool attackerHasShield, CBasePlayer *pAttacker)
|
|
{
|
|
if (m_isComplete || m_event != EVENT_PLAYER_TOOK_DAMAGE)
|
|
return;
|
|
|
|
if (m_weaponId == WEAPON_SHIELDGUN)
|
|
{
|
|
if (!attackerHasShield)
|
|
return;
|
|
}
|
|
else if (m_weaponId)
|
|
{
|
|
if (m_weaponId != weaponId)
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (!m_weaponClassId || m_weaponClassId != weaponClassId)
|
|
return;
|
|
}
|
|
|
|
m_eventsSeen++;
|
|
SendPartialNotification();
|
|
}
|
|
|
|
void CCareerTask::OnEvent(GameEventType event, CBasePlayer *pVictim, CBasePlayer *pAttacker)
|
|
{
|
|
if (m_isComplete)
|
|
return;
|
|
|
|
if (event == m_event)
|
|
{
|
|
if ((m_defuser && !pAttacker->m_bIsDefusing) || (m_vip && !pAttacker->m_bIsVIP))
|
|
return;
|
|
|
|
if (m_rescuer)
|
|
{
|
|
int hostagesCount = 0;
|
|
CHostage *pHostage = nullptr;
|
|
|
|
while ((pHostage = UTIL_FindEntityByClassname(pHostage, "hostage_entity")))
|
|
{
|
|
if (!pHostage->IsAlive())
|
|
continue;
|
|
#ifndef REGAMEDLL_FIXES
|
|
if (!pHostage->IsFollowingSomeone())
|
|
continue;
|
|
|
|
if (pHostage->m_target == pAttacker)
|
|
#else
|
|
if (pHostage->IsFollowing(pAttacker))
|
|
#endif
|
|
hostagesCount++;
|
|
}
|
|
|
|
if (!hostagesCount)
|
|
return;
|
|
}
|
|
|
|
if ((m_event != EVENT_KILL || (!m_weaponId && !m_weaponClassId))
|
|
&& (m_event != EVENT_HEADSHOT || (!m_weaponId && !m_weaponClassId))
|
|
&& (m_event != EVENT_PLAYER_TOOK_DAMAGE || (!m_weaponId && !m_weaponClassId)))
|
|
{
|
|
if (m_event == EVENT_ROUND_WIN)
|
|
{
|
|
if (!Q_strcmp(m_name, "defendhostages"))
|
|
{
|
|
int hostagesCount = 0;
|
|
CHostage *pHostage = nullptr;
|
|
|
|
while ((pHostage = UTIL_FindEntityByClassname(pHostage, "hostage_entity")))
|
|
{
|
|
if (pHostage->pev->takedamage != DAMAGE_YES && pHostage->pev->deadflag != DEAD_DEAD)
|
|
hostagesCount++;
|
|
}
|
|
|
|
if (!hostagesCount)
|
|
{
|
|
m_eventsSeen++;
|
|
SendPartialNotification();
|
|
}
|
|
}
|
|
else if (!Q_strcmp(m_name, "hostagessurvive"))
|
|
{
|
|
int hostagesCount = 0;
|
|
CHostage *pHostage = nullptr;
|
|
|
|
while ((pHostage = UTIL_FindEntityByClassname(pHostage, "hostage_entity")))
|
|
{
|
|
if (pHostage && pHostage->IsDead())
|
|
hostagesCount++;
|
|
}
|
|
|
|
if (!hostagesCount)
|
|
{
|
|
m_eventsSeen++;
|
|
SendPartialNotification();
|
|
}
|
|
}
|
|
else if (!Q_strcmp(m_name, "winfast"))
|
|
{
|
|
if (m_eventsNeeded >= TheCareerTasks->GetRoundElapsedTime())
|
|
{
|
|
m_eventsSeen = m_eventsNeeded;
|
|
SendPartialNotification();
|
|
}
|
|
}
|
|
else if (IsTaskCompletableThisRound())
|
|
{
|
|
m_eventsSeen++;
|
|
SendPartialNotification();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_eventsSeen++;
|
|
SendPartialNotification();
|
|
}
|
|
}
|
|
}
|
|
|
|
CBasePlayer *pLocalPlayer = UTIL_GetLocalPlayer();
|
|
if (event == m_event && !m_mustLive && m_eventsSeen >= m_eventsNeeded && IsTaskCompletableThisRound())
|
|
{
|
|
EMIT_SOUND(ENT(pLocalPlayer->pev), CHAN_VOICE, "events/task_complete.wav", VOL_NORM, ATTN_NORM);
|
|
|
|
m_isComplete = true;
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgCZCareer);
|
|
WRITE_STRING("TASKDONE");
|
|
WRITE_BYTE(m_id);
|
|
MESSAGE_END();
|
|
|
|
if (TheTutor)
|
|
{
|
|
TheTutor->OnEvent(EVENT_CAREER_TASK_DONE);
|
|
}
|
|
|
|
UTIL_LogPrintf("Career Task Done %d\n", m_id);
|
|
|
|
if (m_event == EVENT_ROUND_WIN && !Q_strcmp(m_name, "winfast"))
|
|
{
|
|
TheCareerTasks->SetFinishedTaskTime(int(TheCareerTasks->GetRoundElapsedTime()));
|
|
pLocalPlayer->SyncRoundTimer();
|
|
}
|
|
}
|
|
else if (event >= EVENT_ROUND_DRAW)
|
|
{
|
|
if (event > EVENT_ROUND_LOSS)
|
|
{
|
|
if (event == EVENT_DIE && (m_mustLive || m_crossRounds))
|
|
{
|
|
m_eventsSeen = 0;
|
|
SendPartialNotification();
|
|
m_diedThisRound = true;
|
|
}
|
|
}
|
|
else if (m_mustLive)
|
|
{
|
|
if (m_eventsSeen >= m_eventsNeeded && !m_diedThisRound && IsTaskCompletableThisRound())
|
|
{
|
|
EMIT_SOUND(ENT(pLocalPlayer->pev), CHAN_VOICE, "events/task_complete.wav", VOL_NORM, ATTN_NORM);
|
|
|
|
m_isComplete = true;
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgCZCareer);
|
|
WRITE_STRING("TASKDONE");
|
|
WRITE_BYTE(m_id);
|
|
MESSAGE_END();
|
|
|
|
UTIL_LogPrintf("Career Task Done %d\n", m_id);
|
|
|
|
if (m_event == EVENT_ROUND_WIN && !Q_strcmp(m_name, "winfast"))
|
|
{
|
|
TheCareerTasks->SetFinishedTaskTime(int(TheCareerTasks->GetRoundElapsedTime()));
|
|
pLocalPlayer->SyncRoundTimer();
|
|
}
|
|
|
|
if (TheTutor)
|
|
{
|
|
TheTutor->OnEvent(EVENT_CAREER_TASK_DONE);
|
|
}
|
|
}
|
|
|
|
m_diedThisRound = false;
|
|
|
|
if (m_mustLive)
|
|
{
|
|
m_eventsSeen = 0;
|
|
SendPartialNotification();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCareerTaskManager::Create()
|
|
{
|
|
if (TheCareerTasks)
|
|
{
|
|
TheCareerTasks->Reset();
|
|
return;
|
|
}
|
|
|
|
TheCareerTasks = new CCareerTaskManager;
|
|
}
|
|
|
|
CCareerTaskManager::CCareerTaskManager()
|
|
{
|
|
m_taskTime = 0;
|
|
Reset();
|
|
}
|
|
|
|
void CCareerTaskManager::Reset(bool deleteTasks)
|
|
{
|
|
if (deleteTasks)
|
|
{
|
|
for (auto task : m_tasks)
|
|
delete task;
|
|
|
|
m_tasks.clear();
|
|
m_nextId = 0;
|
|
}
|
|
else
|
|
{
|
|
for (auto task : m_tasks)
|
|
task->Reset();
|
|
}
|
|
|
|
m_finishedTaskTime = 0;
|
|
m_finishedTaskRound = 0;
|
|
m_shouldLatchRoundEndMessage = false;
|
|
|
|
m_roundStartTime = gpGlobals->time + freezetime.value;
|
|
}
|
|
|
|
void CCareerTaskManager::SetFinishedTaskTime(int val)
|
|
{
|
|
m_finishedTaskTime = val;
|
|
m_finishedTaskRound = CSGameRules()->m_iTotalRoundsPlayed;
|
|
}
|
|
|
|
const TaskInfo CCareerTaskManager::m_taskInfo[] =
|
|
{
|
|
{ "defuse", EVENT_BOMB_DEFUSED, &CCareerTask::NewTask },
|
|
{ "plant", EVENT_BOMB_PLANTED, &CCareerTask::NewTask },
|
|
{ "rescue", EVENT_HOSTAGE_RESCUED, &CCareerTask::NewTask },
|
|
{ "killall", EVENT_KILL_ALL, &CCareerTask::NewTask },
|
|
{ "kill", EVENT_KILL, &CCareerTask::NewTask },
|
|
{ "killwith", EVENT_KILL, &CCareerTask::NewTask },
|
|
{ "killblind", EVENT_KILL_FLASHBANGED, &CCareerTask::NewTask },
|
|
{ "killvip", EVENT_KILL, &CCareerTask::NewTask },
|
|
{ "headshot", EVENT_HEADSHOT, &CCareerTask::NewTask },
|
|
{ "headshotwith", EVENT_HEADSHOT, &CCareerTask::NewTask },
|
|
{ "winfast", EVENT_ROUND_WIN, &CCareerTask::NewTask },
|
|
{ "rescue", EVENT_HOSTAGE_RESCUED, &CCareerTask::NewTask },
|
|
{ "rescueall", EVENT_ALL_HOSTAGES_RESCUED, &CCareerTask::NewTask },
|
|
{ "injure", EVENT_PLAYER_TOOK_DAMAGE, &CCareerTask::NewTask },
|
|
{ "injurewith", EVENT_PLAYER_TOOK_DAMAGE, &CCareerTask::NewTask },
|
|
{ "killdefuser", EVENT_KILL, &CCareerTask::NewTask },
|
|
{ "stoprescue", EVENT_KILL, &CCareerTask::NewTask },
|
|
{ "defendhostages", EVENT_ROUND_WIN, &CCareerTask::NewTask },
|
|
{ "hostagessurvive", EVENT_ROUND_WIN, &CCareerTask::NewTask },
|
|
{ "preventdefuse", EVENT_ROUND_WIN, &CPreventDefuseTask::NewTask },
|
|
{ nullptr, EVENT_INVALID, &CCareerTask::NewTask },
|
|
};
|
|
|
|
void CCareerTaskManager::AddTask(const char *taskName, const char *weaponName, int eventCount, bool mustLive, bool crossRounds, bool isComplete)
|
|
{
|
|
m_nextId++;
|
|
|
|
for (auto &taskInfo : m_taskInfo)
|
|
{
|
|
if (taskInfo.taskName)
|
|
{
|
|
if (!Q_stricmp(taskInfo.taskName, taskName))
|
|
{
|
|
CCareerTask *newTask = taskInfo.factory
|
|
(
|
|
taskInfo.taskName,
|
|
taskInfo.event,
|
|
weaponName,
|
|
eventCount,
|
|
mustLive,
|
|
crossRounds,
|
|
m_nextId,
|
|
isComplete
|
|
);
|
|
|
|
m_tasks.push_back(newTask);
|
|
|
|
if (taskInfo.event == EVENT_ROUND_WIN && !Q_strcmp(taskName, "winfast"))
|
|
{
|
|
m_taskTime = eventCount;
|
|
|
|
if (isComplete)
|
|
{
|
|
m_finishedTaskTime = eventCount;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
MESSAGE_BEGIN(MSG_ALL, gmsgCZCareer);
|
|
WRITE_STRING("TASKDONE");
|
|
WRITE_BYTE(m_nextId);
|
|
MESSAGE_END();
|
|
}
|
|
|
|
void CCareerTaskManager::HandleEvent(GameEventType event, CBasePlayer *pAttacker, CBasePlayer *pVictim)
|
|
{
|
|
if (event == EVENT_ROUND_START)
|
|
{
|
|
m_roundStartTime = gpGlobals->time;
|
|
return;
|
|
}
|
|
|
|
if ((event <= EVENT_ROUND_LOSS && event >= EVENT_ROUND_DRAW) && m_shouldLatchRoundEndMessage)
|
|
{
|
|
m_roundEndMessage = event;
|
|
return;
|
|
}
|
|
|
|
for (auto task : m_tasks) {
|
|
task->OnEvent(event, pAttacker, pVictim);
|
|
}
|
|
}
|
|
|
|
void CCareerTaskManager::HandleWeaponKill(int weaponId, int weaponClassId, bool headshot, bool killerHasShield, CBasePlayer *pAttacker, CBasePlayer *pVictim)
|
|
{
|
|
for (auto task : m_tasks) {
|
|
task->OnWeaponKill(weaponId, weaponClassId, headshot, killerHasShield, pAttacker, pVictim);
|
|
}
|
|
}
|
|
|
|
void CCareerTaskManager::HandleEnemyKill(bool wasBlind, const char *weaponName, bool headshot, bool killerHasShield, CBasePlayer *pAttacker, CBasePlayer *pVictim)
|
|
{
|
|
HandleWeaponKill(AliasToWeaponID(weaponName), AliasToWeaponClass(weaponName), headshot, killerHasShield, pAttacker, pVictim);
|
|
HandleEvent(EVENT_KILL, pAttacker, pVictim);
|
|
|
|
if (headshot)
|
|
{
|
|
HandleEvent(EVENT_HEADSHOT, pAttacker, pVictim);
|
|
}
|
|
if (wasBlind)
|
|
{
|
|
HandleEvent(EVENT_KILL_FLASHBANGED, pAttacker, pVictim);
|
|
}
|
|
}
|
|
|
|
void CCareerTaskManager::HandleWeaponInjury(int weaponId, int weaponClassId, bool attackerHasShield, CBasePlayer *pAttacker)
|
|
{
|
|
for (auto task : m_tasks) {
|
|
task->OnWeaponInjury(weaponId, weaponClassId, attackerHasShield, pAttacker);
|
|
}
|
|
}
|
|
|
|
void CCareerTaskManager::HandleEnemyInjury(const char *weaponName, bool attackerHasShield, CBasePlayer *pAttacker)
|
|
{
|
|
HandleWeaponInjury(AliasToWeaponID(weaponName), AliasToWeaponClass(weaponName), attackerHasShield, pAttacker);
|
|
HandleEvent(EVENT_PLAYER_TOOK_DAMAGE);
|
|
}
|
|
|
|
void CCareerTaskManager::HandleDeath(int team, CBasePlayer *pAttacker)
|
|
{
|
|
int enemyTeam = (Q_strcmp(humans_join_team.string, "CT") != 0) ? CT : TERRORIST;
|
|
int numEnemies = 0;
|
|
|
|
if (enemyTeam != team)
|
|
return;
|
|
|
|
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
|
{
|
|
CBasePlayer *pPlayer = UTIL_PlayerByIndex(i);
|
|
|
|
if (!UTIL_IsValidPlayer(pPlayer))
|
|
continue;
|
|
|
|
if (pPlayer->m_iTeam == enemyTeam && pPlayer->IsAlive())
|
|
numEnemies++;
|
|
}
|
|
|
|
if (!numEnemies)
|
|
{
|
|
HandleEvent(EVENT_KILL_ALL);
|
|
}
|
|
}
|
|
|
|
bool CCareerTaskManager::AreAllTasksComplete()
|
|
{
|
|
for (auto task : m_tasks) {
|
|
if (!task->IsComplete())
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int CCareerTaskManager::GetNumRemainingTasks()
|
|
{
|
|
int nTasksCount = 0;
|
|
for (auto task : m_tasks) {
|
|
if (task->IsComplete())
|
|
nTasksCount++;
|
|
}
|
|
|
|
return nTasksCount;
|
|
}
|
|
|
|
float CCareerTaskManager::GetRoundElapsedTime()
|
|
{
|
|
return (gpGlobals->time - m_roundStartTime);
|
|
}
|
|
|
|
void CCareerTaskManager::LatchRoundEndMessage()
|
|
{
|
|
m_shouldLatchRoundEndMessage = true;
|
|
}
|
|
|
|
void CCareerTaskManager::UnlatchRoundEndMessage()
|
|
{
|
|
m_shouldLatchRoundEndMessage = false;
|
|
HandleEvent(m_roundEndMessage);
|
|
}
|