aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/shared/eventlist.cpp
blob: f52f802169683acc84c6b07ade7a7612e2b86506 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//
//=============================================================================//
#include "cbase.h"
#include "eventlist.h"
#include "stringregistry.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

// NOTE: If CStringRegistry allowed storing arbitrary data, we could just use that.
// in this case we have the "isPrivate" member and the replacement rules 
// (eventIndex can be reused by private activities), so a custom table is necessary
struct eventlist_t
{
	int					eventIndex;
	int					iType;
	unsigned short		stringKey;
	short				isPrivate;
};

CUtlVector<eventlist_t> g_EventList;

// This stores the actual event names.  Also, the string ID in the registry is simply an index 
// into the g_EventList array.
CStringRegistry	g_EventStrings;

// this is just here to accelerate adds
static int g_HighestEvent = 0;

int g_nEventListVersion = 1;


void EventList_Init( void )
{
	g_HighestEvent = 0;
}

void EventList_Free( void )
{
	g_EventStrings.ClearStrings();
	g_EventList.Purge();

	// So studiohdrs can reindex event indices
	++g_nEventListVersion;
}

// add a new event to the database
eventlist_t *EventList_AddEventEntry( const char *pName, int iEventIndex, bool isPrivate, int iType )
{
	MEM_ALLOC_CREDIT();
	int index = g_EventList.AddToTail();
	eventlist_t *pList = &g_EventList[index];
	pList->eventIndex = iEventIndex;
	pList->stringKey = g_EventStrings.AddString( pName, index );
	pList->isPrivate = isPrivate;
	pList->iType = iType;	

	// UNDONE: This implies that ALL shared activities are added before ANY custom activities
	// UNDONE: Segment these instead?  It's a 32-bit int, how many activities do we need?
	if ( iEventIndex > g_HighestEvent )
	{
		g_HighestEvent = iEventIndex;
	}

	return pList;
}

// get the database entry from a string
static eventlist_t *ListFromString( const char *pString )
{
	// just use the string registry to do this search/map
	int stringID = g_EventStrings.GetStringID( pString );
	if ( stringID < 0 )
		return NULL;

	return &g_EventList[stringID];
}

// Get the database entry for an index
static eventlist_t *ListFromEvent( int eventIndex )
{
	// ugly linear search
	for ( int i = 0; i < g_EventList.Size(); i++ )
	{
		if ( g_EventList[i].eventIndex == eventIndex )
		{
			return &g_EventList[i];
		}
	}

	return NULL;
}

int EventList_GetEventType( int eventIndex )
{
	eventlist_t *pEvent = ListFromEvent( eventIndex );

	if ( pEvent )
	{
		return pEvent->iType;
	}

	return -1;
}


bool EventList_RegisterSharedEvent( const char *pszEventName, int iEventIndex, int iType )
{
	// UNDONE: Do we want to do these checks when not in developer mode? or maybe DEBUG only?
	// They really only matter when you change the list of code controlled activities.  IDs
	// for content controlled activities never collide because they are generated.

	// first, check to make sure the slot we're asking for is free. It must be for 
	// a shared event.
	eventlist_t *pList = ListFromString( pszEventName );
	if ( !pList )
	{
		pList = ListFromEvent( iEventIndex );
	}

	//Already in list.
	if ( pList )
	{
		return false;
	}
	// ----------------------------------------------------------------

	EventList_AddEventEntry( pszEventName, iEventIndex, false, iType );
	return true;
}

Animevent EventList_RegisterPrivateEvent( const char *pszEventName )
{
	eventlist_t *pList = ListFromString( pszEventName );
	if ( pList )
	{
		// this activity is already in the list. If the activity we collided with is also private, 
		// then the collision is OK. Otherwise, it's a bug.
		if ( pList->isPrivate )
		{
			return (Animevent)pList->eventIndex;
		}
		else
		{
			// this private activity collides with a shared activity. That is not allowed.
			Warning( "***\nShared<->Private Event collision!\n***\n" );
			Assert(0);
			return AE_INVALID;
		}
	}

	pList = EventList_AddEventEntry( pszEventName, g_HighestEvent+1, true, AE_TYPE_SERVER );
	return (Animevent)pList->eventIndex;
}

// Get the index for a given Event name
// Done at load time for all models
int EventList_IndexForName( const char *pszEventName )
{
	// this is a fast O(lgn) search (actually does 2 O(lgn) searches)
	eventlist_t *pList = ListFromString( pszEventName );

	if ( pList )
	{
		return pList->eventIndex;
	}

	return -1;
}

// Get the name for a given index
// This should only be used in debug code, it does a linear search
// But at least it only compares integers
const char *EventList_NameForIndex( int eventIndex )
{
	eventlist_t *pList = ListFromEvent( eventIndex );
	if ( pList )
	{
		return g_EventStrings.GetStringForKey( pList->stringKey );
	}
	return NULL;
}

void EventList_RegisterSharedEvents( void )
{
	REGISTER_SHARED_ANIMEVENT( AE_EMPTY, AE_TYPE_SERVER );
	
	REGISTER_SHARED_ANIMEVENT( AE_NPC_LEFTFOOT, AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_RIGHTFOOT, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_BODYDROP_LIGHT, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_BODYDROP_HEAVY, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_SWISHSOUND, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_180TURN, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_ITEM_PICKUP, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_DROP, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_SET_SEQUENCE_NAME, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_SET_SEQUENCE_NUMBER, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_SET_ACTIVITY, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_HOLSTER, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_DRAW, AE_TYPE_SERVER  );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_FIRE, AE_TYPE_SERVER | AE_TYPE_WEAPON );

	REGISTER_SHARED_ANIMEVENT( AE_CL_PLAYSOUND, AE_TYPE_CLIENT );
	REGISTER_SHARED_ANIMEVENT( AE_SV_PLAYSOUND, AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_CL_STOPSOUND, AE_TYPE_CLIENT );

	REGISTER_SHARED_ANIMEVENT( AE_START_SCRIPTED_EFFECT, AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_STOP_SCRIPTED_EFFECT, AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_CLIENT_EFFECT_ATTACH, AE_TYPE_CLIENT );

	REGISTER_SHARED_ANIMEVENT( AE_MUZZLEFLASH, AE_TYPE_CLIENT );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_MUZZLEFLASH, AE_TYPE_CLIENT );

	REGISTER_SHARED_ANIMEVENT( AE_THUMPER_THUMP, AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_AMMOCRATE_PICKUP_AMMO, AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_NPC_RAGDOLL, AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_NPC_ADDGESTURE, AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_RESTARTGESTURE, AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_NPC_ATTACK_BROADCAST, AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_NPC_HURT_INTERACTION_PARTNER, AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_NPC_SET_INTERACTION_CANTDIE, AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_SV_DUSTTRAIL, AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_CL_CREATE_PARTICLE_EFFECT, AE_TYPE_CLIENT );

	REGISTER_SHARED_ANIMEVENT( AE_RAGDOLL, AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_CL_ENABLE_BODYGROUP, AE_TYPE_CLIENT );
	REGISTER_SHARED_ANIMEVENT( AE_CL_DISABLE_BODYGROUP, AE_TYPE_CLIENT );
	REGISTER_SHARED_ANIMEVENT( AE_CL_BODYGROUP_SET_VALUE, AE_TYPE_CLIENT );
	REGISTER_SHARED_ANIMEVENT( AE_CL_BODYGROUP_SET_VALUE_CMODEL_WPN, AE_TYPE_CLIENT );

	REGISTER_SHARED_ANIMEVENT( AE_WPN_PRIMARYATTACK, AE_TYPE_CLIENT | AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_WPN_INCREMENTAMMO, AE_TYPE_CLIENT | AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_WPN_HIDE, AE_TYPE_CLIENT | AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_WPN_UNHIDE, AE_TYPE_CLIENT | AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_WPN_PLAYWPNSOUND, AE_TYPE_CLIENT | AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_RD_ROBOT_POP_PANELS_OFF, AE_TYPE_CLIENT | AE_TYPE_SERVER );

	REGISTER_SHARED_ANIMEVENT( AE_TAUNT_ENABLE_MOVE, AE_TYPE_CLIENT | AE_TYPE_SERVER );
	REGISTER_SHARED_ANIMEVENT( AE_TAUNT_DISABLE_MOVE, AE_TYPE_CLIENT | AE_TYPE_SERVER );
}