Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add message natives #523

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open

Conversation

OciXCrom
Copy link
Contributor

@OciXCrom OciXCrom commented Aug 26, 2018

The goal of this PR is to make the usage of message_begin functions a lot easier, especially the SVC_TEMPENTITY ones.

Instead of having to do all of this just to create a single beam:

new iStartPos[3], iEndPos[3];
get_user_origin(id, iStartPos);
get_user_origin(id, iEndPos, 3);

message_begin(MSG_ALL, SVC_TEMPENTITY);
write_byte(TE_BEAMPOINTS);
write_coord(iStartPos[0]);
write_coord(iStartPos[1]);
write_coord(iStartPos[2]);
write_coord(iEndPos[0]);
write_coord(iEndPos[1]);
write_coord(iEndPos[2]);
write_short(g_iSprite);
write_byte(0);
write_byte(30);
write_byte(10);
write_byte(10);
write_byte(0);
write_byte(0);
write_byte(0);
write_byte(255);
write_byte(75);
write_byte(0);
message_end();

With using the new natives, we can do it as simple as this:

new iStartPos[3], iEndPos[3];
get_user_origin(id, iStartPos);
get_user_origin(id, iEndPos, 3);

te_create_beam_between_points(iStartPos, iEndPos, g_iSprite)

This saves a lot of time that you would spend searching for the write_ arguments, experimenting with the numbers and having to write all 20 arguments 1 by 1 and having a huge chance of messing some of them up.

Only the mandatory arguments in the natives are required (e.g. starting position, sprite index, etc) and all other ones have a default value and are optional.

All of the natives share 2 same arguments - receiver and bool:reliable - both optional and the second one is always the last argument in the natives. The first one controls who will see the message and the second one controls whether or not to use the reliable channel. With this being said, if receiver is set to 0 and reliable is true, the native will use MSG_ALL as the message destination.

I also spent some time creating a video that previews all of the te_ functions to make it easier for users to understand how they work and what they look like - https://youtu.be/szW-bSMPuyQ

In addition, I found some mistakes while testing in the message_const.inc file that I fixed, e.g. the TE_DLIGHT parameter had a non-existant brightness argument that will crash the server if used (I found this out the hard way).

For anyone willing to test things out, my fantastically coded plugin that I used for testing this PR can be found here - https://pastebin.com/6z5rhc3d

A list of all added natives and can be found in the generated documentation here - http://amxx-bg.info/api/msgstocks/__functions (this is a stock version of the same functions for people that want to use them in 1.8.2)

I skipped TE_LIGHTNING and TE_FIZZ because I couldn't find a working example.
I skipped TE_TEXTMESSAGE as well because of obvious reasons.

* connected, an error will be thrown.
*/

native fade_user_screen(id, Float:duration = 1.0, Float:fadetime = 0.5, ScreenFadeFlags:flags = ScreenFade_FadeIn, r = 0, g = 0, b = 255, a = 75, bool:reliable = true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why default b is 255?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa Why not? It's better than having no color at all.

* @error If "id" is non-zero and the client isn't
* connected, an error will be thrown.
*/
native shake_user_screen(id, Float:amplitude = 3.0, Float:duration = 3.0, Float:frequency = 1.0, bool:reliable = true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for these default values?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa It produces a simple and short shake, setting them to 1.0 is barely noticeable.

* @error If "id" is non-zero and the client isn't
* connected, an error will be thrown.
*/
native set_user_fov(id, fov = 0, bool:reliable = true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why default fov is 0?

Copy link
Contributor Author

@OciXCrom OciXCrom Aug 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa Because it resets the fov back to normal? Default values should do that in cases like this, so if someone writes just set_user_fov(id), it will reset the user's fov to default.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OciXCrom then maybe we need something like reset_user_fov?
And also why user, but not player or client? Function description says: "Changes the client's field...".
There is also a mention of sniper scope, but that's not true for Half-Life.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa Take a look at the natives in the fun module - most of them have the reset value as default. For example, set_user_gravity has its gravity param set to 1.0 by default, so people can simply write set_user_gravity(id) in order to reset it. There's no need for people to research what the reset value for each native is before using it - let it be in the default value so they will know right away.

Copy link
Contributor Author

@OciXCrom OciXCrom Aug 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa I chose user for the same reason - respecting the fun module. It too has user in the native names and client in the description.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't the others mod, but in CS, the default value is 90.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Arkshine 0 seems to have the same effect as 90.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Arkshine I changed it to 90 since this is the value that players receive on spawn.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OciXCrom is it 90 for all the games on GoldSrc? As I can see from the SetFOV client handler code the value 0 sets FOV to the default value, I hope this behavior is the same across the games. So it is better to stick with 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa Okay, I switched it back to 0 again, if that's what the code says. There's no visible difference in CS between 0 and 90, so it shouldn't be a problem.

* @error If "receiver" is non-zero and the client isn't
* connected, an error will be thrown.
*/
native te_create_beam_between_points(startpos[3], endpos[3], sprite, startframe = 0, framerate = 30, life = 10, width = 10, noise = 0, r = 0, g = 0, b = 255, a = 75, speed = 0, receiver = 0, bool:reliable = true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't understand your preferences for default values, same below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa I don't see what the problem is. I set the duration to 1 second in all natives, chose a blue color for most of them and kept the other parameters similar in al the natives (e.g. width is 10 everywhere). As you can see from the video, the beams have a perfect set of parameters for displaying the default sprite as most people would use it. I can't just put 0 in all of them, there's no point of having them optional if I do that.

Copy link
Contributor

@WPMGPRoSToTeMa WPMGPRoSToTeMa Aug 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OciXCrom I think it is better to remove default values and add examples to description.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa No, one of the goals of these natives is to prevent the usage of all ~15 arguments. Most of the times you won't need all of them, so having default values that have the most common settings is a huge help. Take set_hudmessage for example - it has totally random default values.

if(!check_msg_receiver(amx, index))
return 0;

// Values outside the range 0-12 will throw an error
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So... why it isn't thrown here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa I don't think it has to. Since all other natives accept values from 0 to 255, this one being the only one limited from 0 to 12 will probably get forgotten by users, so better use clamp to limit it automatically.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OciXCrom there is another way - we can allow to put RGB and then choose the nearest color to it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa That would be cool if it would work correctly. Can you show an example?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OciXCrom I think it is better to just add a tagged enum for color param, it is more explicit and safe.

Copy link
Contributor Author

@OciXCrom OciXCrom Aug 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa Good idea, I added them. However I didn't notice any visible difference between 6, 8, 9, 10 and 11, so I named all of them TracerColor_Pink%num%.

Copy link
Contributor

@WPMGPRoSToTeMa WPMGPRoSToTeMa Aug 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OciXCrom here the list of colors:

0 - FFFFFF
1 - FF0000
2 - 00FF00
3 - 0000FF
4 - cvar-based
5 - FFA711
6 - FF825A
7 - 373C90
8 - FF825A
9 - FF8C5A
10 - C8825A
11 - FF7846
12 - invalid

You can convert them to color names using this (for example).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa Are you sure this list is correct? The 12th color definitely isn't #000000.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OciXCrom answered here #523 (comment).

Copy link
Contributor

@WPMGPRoSToTeMa WPMGPRoSToTeMa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't delete this lol. (@Arkshine can you delete it?)

@rsKliPPy
Copy link
Contributor

Regarding naming:
Only enumerations that actually represent flags should be named <something>Flags. The naming usually implies that you can do bitwise operations on them.
Enumerations that represent "types" or similar that you can choose one of should be singular. TracerColors > TraceColor. You can see that in cstrike_const.inc (with an ancient exception of CsTeams, which is awful).

Suggestions:

  • StatusIconFlags > StatusIconDisplay
  • TrainControlFlags > TrainControlSpeed
  • BreakModelFlags > BreakModelType
  • TracerColors > TracerColor

@OciXCrom
Copy link
Contributor Author

@rsKliPPy You're right. I updated the enum names.

@Arkshine
Copy link
Member

Arkshine commented Aug 30, 2018

If you plan to make a lot of changes in a PR, you should

  • Discuss beforehand
  • Split the PR in smaller PRs if possible.
  • Avoid adding all your new changes in one commit. Make smaller and logical commits.
  • Fix separately any original bugs found in another PR.

Random thoughts to be discussed:

  • About te_ natives. This doesn't feel right to have them as natives. The only reason you would want to keep them is to error on invalid player's index. Looking at message_begin, even though the engine will skip if the player is not connected, it will crash if the index is incorrect. For some reasons, this native doesn't error on invalid player. If this native is fixed, I would likely put all those te_ natives into stocks instead.
  • Same for the others natives, this kind of shortcut to just wrap things should be likely stocks.
  • Should we use emessage?
  • About set_user_fov. This is not the proper way to do that. The message is associated to m_iFOV, m_iClientFOV and pev->fov. Those should be set as well. Also, you have to care if a mod do something different. For example, CS sends also a HLTV message [1]. A CS version might be needed, I don't know. Also, since using class members, it might be a good idea to avoid to put such stuff into the core.
  • About hide_hud_elements, same as above. It's associated to m_iHideHUD and m_iHideClientHUD. ReGameDLL added some fix as well [2] Same remark as above.
  • About shake_user_screen, it could be more interesting to base the code on UTIL_ScreenShake [3], maybe.
  • About send_geiger_signal, I don't know if it's really useful to send the message alone. It's also associated to m_flgeigerDelay, m_flgeigerRange, and m_igeigerRangePrev. And to trigger the message, you just need to set a value m_igeigerRange != 1000 [4]. This is the same behavior for fov and hidehud btw where the game already checks if a message needs to be sent. Though the geiger message is just about sending a short sound (from 30ms to 300ms max), so it would be kind of silly to redo the logic to send several message when it's already available. Don't know.
  • About cs_set_hud_icon: Are you saying you can provide an interval without providing the associated icon? If not active, only the first byte should be sent.
  • About cs_reload_sound, maybe more logic could be added like does CBasePlayer::ReloadSound [5].
  • About cs_draw_progress_bar, you have the m_progressStart and 'm_progressEnd' members associated. You should also care for spectators. CS has already two functions for that [6]
  • About the style, please put a space after if, for, etc. Also, put the native header above the function and finally put brackets even if one line for consistency.
    __

1 CS code example with SetFOV

Details
   if (m_iFOV != m_iClientFOV)
   {
	// cache FOV change at end of function, so weapon updates can see that FOV has changed
	pev->fov = m_iFOV;

	MESSAGE_BEGIN(MSG_ONE, gmsgSetFOV, nullptr, pev);
		WRITE_BYTE(m_iFOV);
	MESSAGE_END();

	MESSAGE_BEGIN(MSG_SPEC, gmsgHLTV);
		WRITE_BYTE(ENTINDEX(edict()));
		WRITE_BYTE(m_iFOV);
	MESSAGE_END();
   }

__

2 CS code example with HideWeapon

Details
	if (m_iHideHUD != m_iClientHideHUD)
	{
		MESSAGE_BEGIN(MSG_ONE, gmsgHideWeapon, nullptr, pev);
			WRITE_BYTE(m_iHideHUD);
		MESSAGE_END();

#ifdef REGAMEDLL_FIXES
		if (m_iHideHUD && !(m_iHideHUD & HIDEHUD_OBSERVER_CROSSHAIR))
		{
			if (m_iClientHideHUD < 0)
				m_iClientHideHUD = 0;

			int hudChanged = m_iClientHideHUD ^ m_iHideHUD;
			if (hudChanged & (HIDEHUD_FLASHLIGHT | HIDEHUD_HEALTH | HIDEHUD_TIMER | HIDEHUD_MONEY))
			{
				MESSAGE_BEGIN(MSG_ONE, gmsgCrosshair, nullptr, pev);
					WRITE_BYTE(0);
				MESSAGE_END();
			}
		}
#endif

		m_iClientHideHUD = m_iHideHUD;
	}

__

3 UTIL_ScreenShake`

Details
void UTIL_ScreenShake(const Vector &center, float amplitude, float frequency, float duration, float radius)
{
	int i;
	float localAmplitude;
	ScreenShake shake;

	shake.duration = FixedUnsigned16(duration, (1<<12));
	shake.frequency = FixedUnsigned16(frequency, (1<<8));

	for (i = 1; i <= gpGlobals->maxClients; i++)
	{
		CBaseEntity *pPlayer = UTIL_PlayerByIndex(i);
		if (!pPlayer || !(pPlayer->pev->flags & FL_ONGROUND))
			continue;

		localAmplitude = 0;
		if (radius > 0)
		{
			Vector delta = center - pPlayer->pev->origin;
			float distance = delta.Length();

			if (distance < radius)
				localAmplitude = amplitude;
		}
		else
			localAmplitude = amplitude;

		if (localAmplitude)
		{
			shake.amplitude = FixedUnsigned16(localAmplitude, 1<<12);

			MESSAGE_BEGIN(MSG_ONE, gmsgShake, nullptr, pPlayer->edict());
				WRITE_SHORT(shake.amplitude);
				WRITE_SHORT(shake.duration);
				WRITE_SHORT(shake.frequency);
			MESSAGE_END();
		}
	}
}

__

4 UpdateGeigerCounter`

Details
#define GEIGERDELAY 0.25

void CBasePlayer :: UpdateGeigerCounter( void )
{
	BYTE range;

	// delay per update ie: don't flood net with these msgs
	if (gpGlobals->time < m_flgeigerDelay)
		return;

	m_flgeigerDelay = gpGlobals->time + GEIGERDELAY;
		
	// send range to radition source to client

	range = (BYTE) (m_flgeigerRange / 4);

	if (range != m_igeigerRangePrev)
	{
		m_igeigerRangePrev = range;

		MESSAGE_BEGIN( MSG_ONE, gmsgGeigerRange, NULL, pev );
			WRITE_BYTE( range );
		MESSAGE_END();
	}

	// reset counter and semaphore
	if (!RANDOM_LONG(0,3))
		m_flgeigerRange = 1000;

}

__

5 ReloadSound`

Details
void CBasePlayerWeapon::ReloadSound()
{
	CBasePlayer *pPlayer = nullptr;
	while ((pPlayer = UTIL_FindEntityByClassname(pPlayer, "player")))
	{
		if (pPlayer->IsDormant())
			break;

		if (pPlayer == m_pPlayer)
			continue;

		float distance = (m_pPlayer->pev->origin - pPlayer->pev->origin).Length();
		if (distance <= MAX_DIST_RELOAD_SOUND)
		{
			MESSAGE_BEGIN(MSG_ONE, gmsgReloadSound, nullptr, pPlayer->pev);
				WRITE_BYTE(int((1.0f - (distance / MAX_DIST_RELOAD_SOUND)) * 255.0f));
			if (!Q_strcmp(STRING(pev->classname), "weapon_m3") || !Q_strcmp(STRING(pev->classname), "weapon_xm1014"))
				WRITE_BYTE(0);
			else
				WRITE_BYTE(1);
			MESSAGE_END();
		}
	}
}

__

6 SetProgressBarTimeandSetProgressBarTime2`

Details
void CBasePlayer::SetProgressBarTime(int time)
{
	if (time)
	{
		m_progressStart = gpGlobals->time;
		m_progressEnd = time + gpGlobals->time;
	}
	else
	{
		m_progressStart = 0;
		m_progressEnd = 0;
	}

	MESSAGE_BEGIN(MSG_ONE, gmsgBarTime, nullptr, pev);
		WRITE_SHORT(time);
	MESSAGE_END();

	int playerIndex = entindex();
	CBaseEntity *pEntity = nullptr;

	while ((pEntity = UTIL_FindEntityByClassname(pEntity, "player")))
	{
		if (FNullEnt(pEntity->edict()))
			break;

		CBasePlayer *pPlayer = GetClassPtr<CCSPlayer>((CBasePlayer *)pEntity->pev);

		if (pPlayer->GetObserverMode() == OBS_IN_EYE && pPlayer->pev->iuser2 == playerIndex)
		{
			MESSAGE_BEGIN(MSG_ONE, gmsgBarTime, nullptr, pPlayer->pev);
				WRITE_SHORT(time);
			MESSAGE_END();
		}
	}
}

void CBasePlayer::SetProgressBarTime2(int time, float timeElapsed)
{
	if (time)
	{
		m_progressStart = gpGlobals->time - timeElapsed;
		m_progressEnd = time + gpGlobals->time - timeElapsed;
	}
	else
	{
		timeElapsed = 0;
		m_progressStart = 0;
		m_progressEnd = 0;
	}

	short iTimeElapsed = (timeElapsed * 100.0 / (m_progressEnd - m_progressStart));

	MESSAGE_BEGIN(MSG_ONE, gmsgBarTime2, nullptr, pev);
		WRITE_SHORT(time);
		WRITE_SHORT(iTimeElapsed);
	MESSAGE_END();

	int playerIndex = entindex();
	CBaseEntity *pEntity = nullptr;

	while ((pEntity = UTIL_FindEntityByClassname(pEntity, "player")))
	{
		if (FNullEnt(pEntity->edict()))
			break;

		CBasePlayer *pPlayer = GetClassPtr<CCSPlayer>((CBasePlayer *)pEntity->pev);

		if (pPlayer->GetObserverMode() == OBS_IN_EYE && pPlayer->pev->iuser2 == playerIndex)
		{
			MESSAGE_BEGIN(MSG_ONE, gmsgBarTime2, nullptr, pPlayer->pev);
				WRITE_SHORT(time);
				WRITE_SHORT(iTimeElapsed);
			MESSAGE_END();
		}
	}
}

TracerColor_Red,
TracerColor_Green,
TracerColor_Blue,
TracerColor_Yellow,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it black?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa Nope, unless it's uncolored - https://i.imgur.com/1rqQ1r7.jpg
But the 12th color definitely isn't black as well - https://i.imgur.com/3rbtdlx.jpg

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OciXCrom yeah, 12th color is buggy and invalid, it'll be 000080 on Windows client and 000000 on Linux client (what about Mac? lol). 4th color is based on tracerred, tracergreen, tracerblue and traceralpha cvars.

Copy link
Contributor Author

@OciXCrom OciXCrom Aug 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WPMGPRoSToTeMa Thanks for this information, I updated the documentation.

PS: who even uses Mac, lol.

@WPMGPRoSToTeMa
Copy link
Contributor

@Arkshine anchors don't work.

@OciXCrom
Copy link
Contributor Author

OciXCrom commented Aug 30, 2018

@Arkshine I first started making these as stocks but then I decided to remake them as natives. If I'm not mistaken, natives are called faster than stocks, right? If you want to have them as stocks instead, I have the stock version uploaded here, but I think we should stick to natives instead. I'll look at the other things you suggested tomorrow and I'll try to make them. I'm not that great at C++ but I'll see what I can do. I thought that MESSAGE_BEGIN will change all other things associated. For emessage, we can also include another optional parameter at the end of every native (e.g. bool:hookable).

@Arkshine
Copy link
Member

I'm not asking, we need to discuss it before. I don't have the universal answer to everything. The PR has too many changes, we need to figure out first what to keep, what to trash, what to change, etc.

@rsKliPPy
Copy link
Contributor

rsKliPPy commented Aug 30, 2018

The performance should be the least of your concern when deciding stock vs native, especially when it's something as insignificant as this which you won't (and can't) execute too much of. The primary concern is whether you want it to be compiled into plugins (stock) or have the implementation separate so it can be changed at any time without compilation (native).

I honestly think these deserve to be stock functions as well. These are after all little utility functions that are unlikely to ever change if we get them right the first time, and that shouldn't be hard to do with this.

@OciXCrom
Copy link
Contributor Author

@Arkshine @rsKliPPy Okay then. I can convert them to stocks if you believe there won't be any performance improvements if they are natives. I'll wait for the discussion before I do that.

Copy link
Contributor

@WPMGPRoSToTeMa WPMGPRoSToTeMa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to add a comment for each color with its RGB representation.

TracerColor_Coral3,
TracerColor_Coral4,
TracerColor_Coral5,
TracerColor_Invalid
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just remove it.

TracerColor_Pink4,
TracerColor_Pink5,
TracerColor_DarkBlue
TracerColor_Coral2,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove it, because it is just a duplicate of 6 (TracerColor_Coral).

@@ -1164,15 +1164,15 @@ enum TracerColor
TracerColor_Red,
TracerColor_Green,
TracerColor_Blue,
TracerColor_Yellow,
TracerColor_User,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can add a comment with its default color.

TracerColor_Coral2,
TracerColor_Coral3,
TracerColor_Coral4,
TracerColor_Coral5,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how to properly name them, color databases that I found can't distinguish them.

@ClaudiuHKS
Copy link
Contributor

Hard work man, how much time did it take?
This will definitely reduce the size of the future plugins.. and increase the execution speed..

@OciXCrom
Copy link
Contributor Author

OciXCrom commented Sep 3, 2018

@ClaudiuHKS It took about 10 days. The weather was bad on my vacation so I had nothing smarter to do. I don't know about the improved size and speed if we decide to make them as stocks instead.

@wopox1337
Copy link
Contributor

bump

@seypaa
Copy link

seypaa commented Jun 5, 2020

Still waiting

@wopox1337
Copy link
Contributor

Why still not merged? @Arkshine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants