View Single Post
Plugin Info:     Modification:          Category:          Approver:   HamletEagle (36)
LunaTheReborn
Junior Member
Join Date: Feb 2020
Old 03-27-2021 , 23:09   [Condition Zero] Career Tasks Fix
Reply With Quote #1

Background & Mechanism
Recently, I noticed that Condition Zero has a special game mode in which you need to achieve certain tasks, decide who your teammates are... Quite fascinating. However, after I looking into the mission pack system, I noticed that there're some task codes that just won't work. Since all of these tasks are used to create a T mission pack, whereas the built-in mission pack is a CT pack, I wonder whether that is the reason why nobody has notice and Valve doesn't even care to have it fixed.

These three unusable vanilla tasks are:
Code:
killdefuser - Kill a CT when he is defusing.
killvip - Kill a VIP.
stoprescue - Kill a CT to whom hostages are following.
These unusable goal codes can hurt a custom T mission pack fatally, since the task codes left for modders are boring regular tasks, like "Kill X enemies with Y weapon. Oh, remember to headshot. And don't get killed. And keep it that way until you win." Therefore I decided to dig into it a bit and try my best to have it fixed.

This is the call chain I built by refering to ReGameDLL-CS:
Code:
CBasePlayer::Killed()
TheCareerTasks->HandleEnemyKill()
CCareerTaskManager::HandleEvent()
CCareerTask::OnEvent()
Strangely, in the CCareerTask::OnEvent() function, it was the attacker's m_bIsVIP and m_bIsDefusing is being checked. But things just getting weirder: I noticed that when CCareerTaskManager::HandleEvent() is iterating through all tasks by calling their corresponding CCareerTask::OnEvent() function, it SWAP the pAttacker and pVictim.
In CCareerTaskManager::HandleEvent() we have:
Code:
for (auto task : m_tasks)
{
	task->OnEvent(event, pAttacker, pVictim);
}
But CCareerTask::OnEvent() was declared like this:
Code:
void CCareerTask::OnEvent(GameEventType event, CBasePlayer *pVictim, CBasePlayer *pAttacker)
{
	...
}
What is going on here? A double flip? Hence I investigate the entire call chain.
The result is:
Code:
CBasePlayer::Killed()
↓ Flipped.
TheCareerTasks->HandleEnemyKill()
↓ Retained.
CCareerTaskManager::HandleEvent()
↓ Flipped.
CCareerTask::OnEvent()
↓ Flipped.
Result: Check flags and identify the victim to complete tasks.
It's genuine an UBISOFT-ish result instead of Valve-ish.
So the simplest fix I can purpose is to flip the param of HandleEnemyKill() via Orpheu module.

But after this patch, one task remains unfixed, which is "Kill a CT whom hostages are following."
Then I go straight into CCareerTask::OnEvent() and as excepted, this code is used to determine whether a player is followed by hostages.
Code:
if (pHostage->m_target == pAttacker)
	hostagesCount++;
The problem is, CHostage::m_target is an unused pointer. In Condition Zero, a class named CHostageImprov is de facto taken over the control of all hostage behavior. The mystery offset 490 in CHostage.

While making a hook in function HostageFollowState::OnUpdate(), I noticed a fatal bug in Orpheu module. It interpreted CHostageImprov as an alias of CBaseEntity by a superfluous configuration file. It is wrong and can cause a serious of CTD.

By hooking HostageFollowState::OnUpdate(), CHostage::m_target can now nicely syncing with HostageFollowState::m_leader and CCareerTask::OnEvent() can now properly handle everything rest. At last, it is all fixed.


Requirement
- Orpheu
- AMX Mod X start from 1.8.1
Tested & Works on
Counter-Strike: Condition Zero EXCLUSIVELY
Installation
After regular Orpheu installation steps, you have to delete
czero\addons\amxmodx\configs\orpheu\types\CBa seEntity\aliases\CHostageImprov
This is a must-step or you will have a guaranteed CTD since this is a misinterpretation in Orpheu.

The other zip is a custom mission pack for you to test these fixed tasks. Install it just like any other Condition-Zero mission packs.
You can also confirm the bugs by disabling this plugin then try to finish the tasks.
Reference Book
ReGameDLL-CS
Credits
Arkshine's plugin Infinite Round. From which I learned how to modify a member of a non-CBaseEntity class.
Attached Files
File Type: zip CZ Test Missionpack.zip (4.1 KB, 353 views)
File Type: zip CareerTasksFix.zip (8.5 KB, 320 views)

Last edited by HamletEagle; 04-04-2021 at 07:53.
LunaTheReborn is offline