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

Refactor perk definition system #85

Open
Phil25 opened this issue Dec 18, 2023 · 0 comments
Open

Refactor perk definition system #85

Phil25 opened this issue Dec 18, 2023 · 0 comments
Labels
request :: general New feature or request
Milestone

Comments

@Phil25
Copy link
Owner

Phil25 commented Dec 18, 2023

Overview

Perks define the call method and now the init method which correspond to the function names in code. With the upcoming programmatic preconditions (#71), there will be a third such function, and probably even more upcoming. This can be restructured into a single very generic function which accepts a enum of an action call, to which perk implementation will respond accordingly. This should also be exposed via API.

I will skip over a lot of thoughts I had about this refactor, mostly because I don't want to bother formalizing them, but also because this is a huge undertaking and many things will need to be investigated during implementation. For now, I needed a place to store the PoC below, so, if anyone interested happens to read it, hopefully it will clear some things up at least.

Proof of Concept

Include file

enum RTDPerkCall
{
	RTDPerkCall_Init,
	RTDPerkCall_Apply,
	RTDPerkCall_Remove,
	RTDPerkCall_IsValidForClient,
	RTDPerkCall_GetSettingType,
	RTDPerkCall_VerifySettingValue,
}

enum RTDSettingType
{
	RTDSettingType_Unknown,
	RTDSettingType_Any,
	RTDSettingType_Integer,
	RTDSettingType_Float,
	RTDSettingType_String
}

enum RTDSettingVerification
{
	RTDSettingVerification_OK,
	RTDSettingVerification_Warning,
	RTDSettingVerification_Fatal
}

methodmap RTDPerkBase
{
	public void Apply(const int client)
	{
		char sCaller[32];
		GetCallerName(sCaller, sizeof(sCaller));
		LogStackTrace("Perk \"%s\" has no Apply method defined", sCaller);
	}

	public void Remove(const int client)
	{
		char sCaller[32];
		GetCallerName(sCaller, sizeof(sCaller));
		LogStackTrace("Perk \"%s\" has no Remove method defined", sCaller);
	}

	public bool IsValidForClient(const int client, const TFClassType eClass)
	{
		return true;
	}

	public RTDSettingType GetSettingType(const char[] sSetting)
	{
		return RTDSettingType_Any;
	}

	public bool VerifySettingValue(const char[] sSetting, const char[] sValue, char[] sError, const int iErrorLen)
	{
		return true;
	}
}

#define RTD2_DECLARE_PERK_TYPE(%1) \
	int %1(RTDPerkCall ePerkCall, const int client, const TFClassType eClass, char[] sFeedback, const int iFeedbackLen, const char[] sString1="", const char[] sString2="") \
	{ \
		switch (ePerkCall) \
		{ \
		case RTDPerkCall_Apply: view_as<%1_>(0).Apply(client); \
		case RTDPerkCall_Remove: view_as<%1_>(0).Remove(client); \
		case RTDPerkCall_IsValidForClient: return view_as<%1_>(0).IsValidForClient(client, eClass); \
		case RTDPerkCall_GetSettingType: return view_as<int>(view_as<%1_>(0).GetSettingType(sString1)); \
		case RTDPerkCall_VerifySettingValue: return view_as<%1_>(0).VerifySettingValue(sString1, sString2, sFeedback, iFeedbackLen); \
		} \
		return 0; \
	} \
	methodmap %1_ < RTDPerkBase

Perk implementation

RTD2_DECLARE_PERK_TYPE(MyCustomPerk)
{
	public void Apply(const int client)
	{
		PrintToServer("Applying MyCustomPerk on %d", client);
	}

	public void Remove(const int client)
	{
		PrintToServer("Removing MyCustomPerk from %d", client);
	}

	public bool IsValidForClient(const int client, const TFClassType eClass)
	{
		return eClass == TFClass_Scout;
	}

	public RTDSettingType GetSettingType(const char[] sSetting)
	{
		if (StrEqual(sSetting, "amount"))
		{
			return RTDSettingType_Integer;
		}

		return RTDSettingType_Unknown;
	}

	public bool VerifySettingValue(const char[] sSetting, const char[] sValue, char[] sError, const int iErrorLen)
	{
		if (StrEqual(sSetting, "amount") && !(1 <= StringToInt(sValue) <= 3))
		{
			Format(sError, iErrorLen, "amount should be either 1, 2 or 3 (is: %s)", sValue);
			return false;
		}

		return true;
	}
}

Calls from RTD source

char sFeedback[128];
MyCustomPerk(RTDPerkCall_Apply, 4, TFClass_DemoMan, sFeedback, sizeof(sFeedback));
MyCustomPerk(RTDPerkCall_Remove, 5, TFClass_DemoMan, sFeedback, sizeof(sFeedback));
MyCustomPerk(RTDPerkCall_IsValidForClient, 5, TFClass_DemoMan, sFeedback, sizeof(sFeedback));
MyCustomPerk(RTDPerkCall_GetSettingType, 5, TFClass_DemoMan, sFeedback, sizeof(sFeedback), "amount");
MyCustomPerk(RTDPerkCall_VerifySettingValue, 5, TFClass_DemoMan, sFeedback, sizeof(sFeedback), "amount", "3");
PrintToServer("Feedback: %s", sFeedback);
@Phil25 Phil25 added this to the 3.0.0 milestone Dec 18, 2023
@Phil25 Phil25 added the request :: general New feature or request label Dec 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request :: general New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant