Fixing AI in multiplayer: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(Altered intro, added .patch)
Line 1: Line 1:
This is an updated article about how to fix NPCs in multiplayer. HL2 has no support for NPCs in multiplayer and HL2DM has certainly broken more of the AI.
This article describes the changes that need to be made in order to get NPCs to work in the multiplayer SDK, as there are several key features that need to be re-implemented in a multiplayer context. While it covers the use of the HL2DM SDK, it should be readily convertible to work with the Scratch SDK, by referring to the correct GameRules.
Note that a patch is available for the Orange Box HL2DM source that implements all changes described here, it is listed near the end of the article.


== Relationships ==
== Relationships ==
Line 93: Line 94:


== Zombies ==
== Zombies ==
In <b>AI_BaseNPC.cpp</b> find <b>CAI_BaseNPC::Ignite</b> and remove/comment out the <b>#ifdef HL2_EPISODIC</b> section. In <b>npc_BaseZombie.cpp</b> find <b>CNPC_BaseZombie::MakeAISpookySound</b> and remove/comment out its contents. NPC_FastZombie's seem to work but NPC_Zombie seems to still have some errors.
In <b>AI_BaseNPC.cpp</b> find <b>CAI_BaseNPC::Ignite</b> and remove/comment out the <b>#ifdef HL2_EPISODIC</b> section. In <b>npc_BaseZombie.cpp</b> find <b>CNPC_BaseZombie::MakeAISpookySound</b> and remove/comment out its contents.
 
== Patch ==
Including the 'function calls,' there's an awful lot of changes required to implement AI in a multiplayer mod. [http://winston.m6.net/files/hl2mp_ob_ai_fix.zip This patch file] implements all the changes described here, (crucially) including correcting all the function calls - so it should save you a good deal of dull coding work! See the readme for details of how it replaces calls to functions such as <code>UTIL_GetLocalPlayer()</code> & <code>AI_GetSingleplayer()</code>, and for details of how to apply a patch file.


== Conclusion ==
== Conclusion ==

Revision as of 10:15, 3 April 2008

This article describes the changes that need to be made in order to get NPCs to work in the multiplayer SDK, as there are several key features that need to be re-implemented in a multiplayer context. While it covers the use of the HL2DM SDK, it should be readily convertible to work with the Scratch SDK, by referring to the correct GameRules. Note that a patch is available for the Orange Box HL2DM source that implements all changes described here, it is listed near the end of the article.

Relationships

There is no relationships-table set in HL2DM. Without this table NPCs won't know which entities to hate/like, and if Combine Soldiers likes players, they won't attack them.

This is simple to fix. First go to hl2mp_gamerules.h, under public: add this:

#ifndef CLIENT_DLL 
void InitDefaultAIRelationships( void );
#endif

Next go to hl2_gamerules.cpp and copy the entire InitDefaultAIRelationships function. Paste it in hl2mp_gamerules.cpp. Don't forget to put the copied functions between:

#ifndef CLIENT_DLL
...
#endif

Also add a call to InitDefaultAIRelationships in the constructor of CHL2MPRules.

Weapons

Activities & animation events

The weapons have custom activities and animation events used for the AI in HL2. In the HL2DM-versions of the weapons this is removed.

Open the weapon_hl2mpbase.h file and add the following code after the includes:

#ifndef CLIENT_DLL
	#include "AI_BaseNPC.h"
#endif


Now open the HL2SP files of the AR2, shotgun, SMG1, crowbar, pistol, stunstick and frag grenade (found in dlls/hl2_dll/). The NPCs in HL2 don't use any other weapons. Each weapon has a Operator_HandleAnimEvent and CapabilitiesGet function, which the NPCs use to fire their weapons. Copy these functions and any other functions that are called in Operator_HandleAnimEvent to the HL2DM weaponfiles (found in game_shared/hl2mp/). Don't forget the headers and to put all copied functions between:

#ifndef CLIENT_DLL
...
#endif

Also, you need to copy the activities. Look for m_acttable[] in the HL2SP-variants and copy them to the HL2DM-variants.

SetActivity()

Open basecombatweapon_shared.cpp and look for the function SetActivity. Look for the following code:

//Adrian: Oh man...
#if !defined( CLIENT_DLL ) && defined( HL2MP )
	SetModel( GetWorldModel() );
#endif

int sequence = SelectWeightedSequence( act ); 
	
	// FORCE IDLE on sequences we don't have (which should be many)
	if ( sequence == ACTIVITY_NOT_AVAILABLE )
		sequence = SelectWeightedSequence( ACT_VM_IDLE );

//Adrian: Oh man again...
#if !defined( CLIENT_DLL ) && defined( HL2MP )
	SetModel( GetViewModel() );
#endif

The activities can only be retrieved from weapon world models. However the weapons of players are viewmodels. So with this little hack the models are changed to worldmodel, activies are retrieved and changed back to viewmodel. However considering NPCs don't have to see or work with their viewmodels, this is going to be changed:

	//Adrian: Oh man...
	if ( GetOwner()->IsPlayer() )
		SetModel( GetWorldModel() );
	
	int sequence = SelectWeightedSequence( act ); 
	
	// FORCE IDLE on sequences we don't have (which should be many)
	if ( sequence == ACTIVITY_NOT_AVAILABLE )
		sequence = SelectWeightedSequence( ACT_VM_IDLE );

	//Adrian: Oh man again...
	if ( GetOwner()->IsPlayer() )
		SetModel( GetViewModel() );

Ammotypes

The damage of the weapons need to use the data from skill.cfg. Don't forget the copy HL2's skill.cfg to your mod's cfg directory.

Also, the code needs to be told to use this values. Open hl2_gamerules.cpp again and copy the entire GetAmmoDef function. Replace the same function in hl2mp_gamerules.cpp with the copied code but add the following line:

def.AddAmmoType("slam", DMG_BURN, TRACER_NONE, 0, 0, 5, 0, 0);

HL2 doesn't have the SLAM and without that line the SLAM won't work anymore.

You need to include hl2_shareddefs.h in hl2mp_gamerules.cpp too. Otherwise you will get two compiler errors C2065: 'DMG_SNIPER': undeclared identifier.

Model animations

If you are using HL2DM as base (320 as SteamAppID in gameinfo.txt) then you are using the models of HL2DM. HL2DM has new models for the metropolice, combine soldiers and rebels. These HL2DM models don't have the animations of the HL2-variants and the AI doesn't like that. For that to work, you need to copy the models over from HL2. Also, new player models are needed, considering the ones from HL2DM won't work anymore.

Note.pngNote:Since the August 06 SDK update NPCs have new code that need EP1-models

Function calls

Still, much of the AI code is still not suited to use in multiplayer. All calls to the functions AI_GetSinglePlayer, AI_IsSingleplayer and UTIL_GetLocalPlayer would need fixing. Also pieces of code like if ( gpGlobals->maxClients == 1) and UTIL_PlayerByIndex( 1 ). There are over 200 such calls, and it's lots of work to fix this.

Blood

Thanks to the prediction, the blood of NPCs is suppressed. This is because in HL2DM the blood of players is done client-side. This is not the case with NPCs and the prediction needs to "break":

Open util_shared.cpp and look for the function UTIL_BloodDrips. Add to the top of the function:

IPredictionSystem::SuppressHostEvents( NULL );

Zombies

In AI_BaseNPC.cpp find CAI_BaseNPC::Ignite and remove/comment out the #ifdef HL2_EPISODIC section. In npc_BaseZombie.cpp find CNPC_BaseZombie::MakeAISpookySound and remove/comment out its contents.

Patch

Including the 'function calls,' there's an awful lot of changes required to implement AI in a multiplayer mod. This patch file implements all the changes described here, (crucially) including correcting all the function calls - so it should save you a good deal of dull coding work! See the readme for details of how it replaces calls to functions such as UTIL_GetLocalPlayer() & AI_GetSingleplayer(), and for details of how to apply a patch file.

Conclusion

These are the basic fixes needed for the AI. If you want to use HL2-NPCs in multiplayer, there's a lot of work ahead.

Template:Otherlang:en Template:Otherlang:en:fr