Updated some CS:GO gamedata.
3 * =============================================================================
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "sm_globals.h"
33 #include <IGameConfigs.h>
34 #include "UserMessages.h"
36 #include "PlayerManager.h"
37 #include "logic_bridge.h"
38 #include "sourcemod.h"
40 #if SOURCE_ENGINE == SE_DOTA
41 #include <game/shared/protobuf/usermessages.pb.h>
42 #elif SOURCE_ENGINE == SE_CSGO
43 #include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
46 #define MAX_HUD_CHANNELS 6
52 int player_channels[256 + 1];
55 struct player_chaninfo_t
57 double chan_times[MAX_HUD_CHANNELS];
58 hud_syncobj_t *chan_syncobjs[MAX_HUD_CHANNELS];
77 public IHandleTypeDispatch,
78 public IClientListener
83 return (g_HudMsgNum != -1);
86 virtual void OnSourceModAllInitialized_Post()
90 key = g_pGameConf->GetKeyValue("HudTextMsg");
93 g_HudMsgNum = g_UserMsgs.GetMessageIndex(key);
103 m_PlayerHuds = new player_chaninfo_t[256+1];
104 m_hHudSyncObj = handlesys->CreateType("HudSyncObj", this, 0, NULL, NULL, g_pCoreIdent, NULL);
106 g_Players.AddClientListener(this);
109 virtual void OnSourceModShutdown()
116 delete [] m_PlayerHuds;
117 handlesys->RemoveType(m_hHudSyncObj, g_pCoreIdent);
119 g_Players.RemoveClientListener(this);
122 virtual void OnHandleDestroy(HandleType_t type, void *object)
124 hud_syncobj_t *obj = (hud_syncobj_t *)object;
129 virtual bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
131 *pSize = sizeof(unsigned int) * g_Players.GetMaxClients();
135 virtual void OnClientConnected(int client)
137 player_chaninfo_t *player;
139 player = &m_PlayerHuds[client];
140 memset(player->chan_syncobjs, 0, sizeof(player->chan_syncobjs));
141 memset(player->chan_times, 0, sizeof(player->chan_times));
144 Handle_t CreateHudSyncObj(IdentityToken_t *pIdent)
151 obj = new hud_syncobj_t;
153 memset(obj->player_channels, 0, sizeof(obj->player_channels));
155 sec = HandleSecurity(pIdent, g_pCoreIdent);
157 if ((hndl = handlesys->CreateHandleEx(m_hHudSyncObj, obj, &sec, NULL, &err))
166 HandleError ReadHudSyncObj(Handle_t hndl,
167 IdentityToken_t *pOwner,
168 hud_syncobj_t **pObj)
170 HandleSecurity sec(pOwner, g_pCoreIdent);
171 return handlesys->ReadHandle(hndl, m_hHudSyncObj, &sec, (void **)pObj);
174 unsigned int AutoSelectChannel(unsigned int client)
177 player_chaninfo_t *player;
179 player = &m_PlayerHuds[client];
182 for (unsigned int i = 1; i < MAX_HUD_CHANNELS; i++)
184 if (player->chan_times[i] < player->chan_times[last_channel])
190 ManualSelectChannel(client, last_channel);
195 int TryReuseLastChannel(unsigned int client, hud_syncobj_t *obj)
198 player_chaninfo_t *player;
200 player = &m_PlayerHuds[client];
202 /* First, see if we can re-use the previous channel. */
203 last_channel = obj->player_channels[client];
205 if (player->chan_syncobjs[last_channel] == obj)
207 player->chan_times[last_channel] = *g_pUniversalTime;
214 int AutoSelectChannel(unsigned int client, hud_syncobj_t *obj)
217 player_chaninfo_t *player;
219 player = &m_PlayerHuds[client];
221 /* First, see if we can re-use the previous channel. */
222 last_channel = obj->player_channels[client];
224 if (player->chan_syncobjs[last_channel] == obj)
226 player->chan_times[last_channel] = *g_pUniversalTime;
231 for (unsigned int i = 1; i < MAX_HUD_CHANNELS; i++)
233 if (player->chan_times[i] < player->chan_times[last_channel])
239 obj->player_channels[client] = last_channel;
240 player->chan_syncobjs[last_channel] = obj;
241 player->chan_times[last_channel] = *g_pUniversalTime;
246 int ManualSelectChannel(unsigned int client, int channel)
248 player_chaninfo_t *player;
250 player = &m_PlayerHuds[client];
251 player->chan_times[channel] = *g_pUniversalTime;
252 player->chan_syncobjs[channel] = NULL;
257 HandleType_t m_hHudSyncObj;
258 player_chaninfo_t *m_PlayerHuds;
261 hud_text_parms g_hud_params;
263 static cell_t CreateHudSynchronizer(IPluginContext *pContext, const cell_t *params)
265 return s_HudMsgHelpers.CreateHudSyncObj(pContext->GetIdentity());
268 static cell_t SetHudTextParams(IPluginContext *pContext, const cell_t *params)
270 g_hud_params.x = sp_ctof(params[1]);
271 g_hud_params.y = sp_ctof(params[2]);
272 g_hud_params.holdTime = sp_ctof(params[3]);
273 g_hud_params.r1 = static_cast<byte>(params[4]);
274 g_hud_params.g1 = static_cast<byte>(params[5]);
275 g_hud_params.b1 = static_cast<byte>(params[6]);
276 g_hud_params.a1 = static_cast<byte>(params[7]);
277 g_hud_params.effect = params[8];
278 g_hud_params.fxTime = sp_ctof(params[9]);
279 g_hud_params.fadeinTime = sp_ctof(params[10]);
280 g_hud_params.fadeoutTime = sp_ctof(params[11]);
281 g_hud_params.r2 = 255;
282 g_hud_params.g2 = 255;
283 g_hud_params.b2 = 250;
289 static cell_t SetHudTextParamsEx(IPluginContext *pContext, const cell_t *params)
291 cell_t *color1, *color2;
293 pContext->LocalToPhysAddr(params[4], &color1);
294 pContext->LocalToPhysAddr(params[5], &color2);
296 g_hud_params.x = sp_ctof(params[1]);
297 g_hud_params.y = sp_ctof(params[2]);
298 g_hud_params.holdTime = sp_ctof(params[3]);
299 g_hud_params.r1 = static_cast<byte>(color1[0]);
300 g_hud_params.g1 = static_cast<byte>(color1[1]);
301 g_hud_params.b1 = static_cast<byte>(color1[2]);
302 g_hud_params.a1 = static_cast<byte>(color1[3]);
303 g_hud_params.effect = params[6];
304 g_hud_params.fxTime = sp_ctof(params[7]);
305 g_hud_params.fadeinTime = sp_ctof(params[8]);
306 g_hud_params.fadeoutTime = sp_ctof(params[9]);
307 g_hud_params.r2 = static_cast<byte>(color2[0]);
308 g_hud_params.g2 = static_cast<byte>(color2[1]);
309 g_hud_params.b2 = static_cast<byte>(color2[2]);
310 g_hud_params.a2 = static_cast<byte>(color2[3]);
315 void UTIL_SendHudText(int client, const hud_text_parms &textparms, const char *pMessage)
321 #if SOURCE_ENGINE == SE_DOTA
322 CUserMsg_HudMsg *msg = (CUserMsg_HudMsg *)g_UserMsgs.StartProtobufMessage(g_HudMsgNum, players, 1, 0);
323 msg->set_channel(textparms.channel & 0xFF);
325 msg->set_x(textparms.x);
326 msg->set_y(textparms.y);
328 Color c1(textparms.r1, textparms.g1, textparms.b1, textparms.a1);
329 msg->set_color1(c1.GetRawColor());
331 Color c2(textparms.r2, textparms.g2, textparms.b2, textparms.a2);
332 msg->set_color2(c2.GetRawColor());
334 msg->set_effect(textparms.effect);
335 msg->set_fade_in_time(textparms.fadeinTime);
336 msg->set_fade_out_time(textparms.fadeoutTime);
337 msg->set_hold_time(textparms.holdTime);
338 msg->set_fx_time(textparms.fxTime);
339 msg->set_message(pMessage);
340 #elif SOURCE_ENGINE == SE_CSGO
341 CCSUsrMsg_HudMsg *msg = (CCSUsrMsg_HudMsg *)g_UserMsgs.StartProtobufMessage(g_HudMsgNum, players, 1, 0);
342 msg->set_channel(textparms.channel & 0xFF);
344 CMsgVector2D *pos = msg->mutable_pos();
345 pos->set_x(textparms.x);
346 pos->set_y(textparms.y);
348 CMsgRGBA *color1 = msg->mutable_clr1();
349 color1->set_r(textparms.r1);
350 color1->set_g(textparms.g1);
351 color1->set_b(textparms.b1);
352 color1->set_a(textparms.a1);
354 CMsgRGBA *color2 = msg->mutable_clr2();
355 color2->set_r(textparms.r2);
356 color2->set_g(textparms.g2);
357 color2->set_b(textparms.b2);
358 color2->set_a(textparms.a2);
360 msg->set_effect(textparms.effect);
361 msg->set_fade_in_time(textparms.fadeinTime);
362 msg->set_fade_out_time(textparms.fadeoutTime);
363 msg->set_hold_time(textparms.holdTime);
364 msg->set_fx_time(textparms.fxTime);
365 msg->set_text(pMessage);
367 bf_write *bf = g_UserMsgs.StartBitBufMessage(g_HudMsgNum, players, 1, 0);
368 bf->WriteByte(textparms.channel & 0xFF );
369 bf->WriteFloat(textparms.x);
370 bf->WriteFloat(textparms.y);
371 bf->WriteByte(textparms.r1);
372 bf->WriteByte(textparms.g1);
373 bf->WriteByte(textparms.b1);
374 bf->WriteByte(textparms.a1);
375 bf->WriteByte(textparms.r2);
376 bf->WriteByte(textparms.g2);
377 bf->WriteByte(textparms.b2);
378 bf->WriteByte(textparms.a2);
379 bf->WriteByte(textparms.effect);
380 bf->WriteFloat(textparms.fadeinTime);
381 bf->WriteFloat(textparms.fadeoutTime);
382 bf->WriteFloat(textparms.holdTime);
383 bf->WriteFloat(textparms.fxTime);
384 bf->WriteString(pMessage);
386 g_UserMsgs.EndMessage();
389 static cell_t ShowSyncHudText(IPluginContext *pContext, const cell_t *params)
395 char message_buffer[255-36];
397 if (!s_HudMsgHelpers.IsSupported())
402 if ((err = s_HudMsgHelpers.ReadHudSyncObj(params[2], pContext->GetIdentity(), &obj)) != HandleError_None)
404 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[2], err);
408 if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
410 return pContext->ThrowNativeError("Invalid client index %d", client);
412 else if (!pPlayer->IsInGame())
414 return pContext->ThrowNativeError("Client %d is not in-game", client);
417 g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
418 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
423 g_hud_params.channel = s_HudMsgHelpers.AutoSelectChannel(client, obj);
424 UTIL_SendHudText(client, g_hud_params, message_buffer);
429 static cell_t ClearSyncHud(IPluginContext *pContext, const cell_t *params)
437 if (!s_HudMsgHelpers.IsSupported())
442 if ((err = s_HudMsgHelpers.ReadHudSyncObj(params[2], pContext->GetIdentity(), &obj)) != HandleError_None)
444 return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[2], err);
448 if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
450 return pContext->ThrowNativeError("Invalid client index %d", client);
452 else if (!pPlayer->IsInGame())
454 return pContext->ThrowNativeError("Client %d is not in-game", client);
457 if ((channel = s_HudMsgHelpers.TryReuseLastChannel(client, obj)) == -1)
462 g_hud_params.channel = channel;
463 UTIL_SendHudText(client, g_hud_params, "");
465 return g_hud_params.channel;
468 static cell_t ShowHudText(IPluginContext *pContext, const cell_t *params)
472 char message_buffer[255-36];
474 if (!s_HudMsgHelpers.IsSupported())
480 if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
482 return pContext->ThrowNativeError("Invalid client index %d", client);
484 else if (!pPlayer->IsInGame())
486 return pContext->ThrowNativeError("Client %d is not in-game", client);
489 g_SourceMod.FormatString(message_buffer, sizeof(message_buffer), pContext, params, 3);
490 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
497 g_hud_params.channel = s_HudMsgHelpers.AutoSelectChannel(client);
501 g_hud_params.channel = params[2] % MAX_HUD_CHANNELS;
502 s_HudMsgHelpers.ManualSelectChannel(client, g_hud_params.channel);
505 UTIL_SendHudText(client, g_hud_params, message_buffer);
507 return g_hud_params.channel;
510 REGISTER_NATIVES(hudNatives)
512 {"ClearSyncHud", ClearSyncHud},
513 {"CreateHudSynchronizer", CreateHudSynchronizer},
514 {"SetHudTextParams", SetHudTextParams},
515 {"SetHudTextParamsEx", SetHudTextParamsEx},
516 {"ShowHudText", ShowHudText},
517 {"ShowSyncHudText", ShowSyncHudText},