Skip to content

Instantly share code, notes, and snippets.

@MajorCooke
Last active January 25, 2023 00:35
Show Gist options
  • Save MajorCooke/16061917040f31a1c469b677fae39c37 to your computer and use it in GitHub Desktop.
Save MajorCooke/16061917040f31a1c469b677fae39c37 to your computer and use it in GitHub Desktop.
(Untested) Example XP service class, created at start of each map.
// Toxic Frog:
// To utilize, simply copy/paste the BonsaiXPRecord class into the main files of Bonsai XP. Then copy the
// code within the event and merge it with the main event handler you already have established. The fewer
// the handlers, the better performance is.
Class BonsaiXPRecord
{
Class<Actor> mo;
int XP;
}
Class BonsaiXPEvent : EventHandler
{
// A Map<k,v> could be used here but it would force the requirements to be
// GZDoom 4.10+ only.
private Array<BonsaiXPRecord> Records;
private Array<Class<Actor> > Classes; // For faster indexing.
// Call this when WorldThingDied occurs.
private void GiveXP(Actor mo, Actor to)
{
if (!mo || !to) return;
// Do your thing here.
}
// Handles setting up of customizable XP settings. Right now this only handles
// the classes directly. More work will need to be done if parent checking
// is to be done.
override void WorldLoaded(WorldEvent e)
{
SetupXPRecords();
}
private void SetupXPService()
{
Records.Clear();
Classes.Clear();
// Find all services with the name 'BonsaiXPService' in it, and
// iterate through each one.
let it = ServiceIterator.Find("BonsaiXPService");
Service XPServ;
while (XPServ = it.Next())
{
int i = 0; // Reset for each service class.
String ret = "";
Array<String> st;
while (true)
{
ret = XPServ.GetString("GetXP", "", i++);
// Nothing else to process. Next service class!
if (ret.Length() < 1)
break;
// Remove spaces and tabs
st.Clear();
ret.Replace(" ", "");
ret.Replace(" ", "");
// Split based on token characters.
ret.Split(st, ",");
// Invalid format, so skip it.
if (st.Size() < 1)
{
Console.Printf("%s: Invalid format. Comma needed between actor name & XP");
continue;
}
// Check if it's a valid actor class.
Class<Actor> cls = st[0];
if (!cls)
continue;
// Now construct the record.
BonsaiXPRecord rec;
// Find it first if it already exists.
int ind = Classes.Find(cls);
if (ind < Classes.Size())
rec = Records[ind];
else
{
rec = new('BonsaiXPRecord');
rec.mo = cls;
}
rec.XP = st[1].ToInt();
Classes.Push(cls.GetClassName());
}
}
}
}
// If it has the name 'BonsaiXPService' and it inherits from Service, the iterator
// will find it.
Class PlaceHolder_BonsaiXPService : Service
{
// You could just rely on the GetInt variant if the plan is to keep it simple.
// However this way strikes me as more user friendly, and this is all only
// called once, upon entering a new map. Syntax is as follows:
// <Actor Name>, <XP Amount>
static const String mon[] =
{
"TM_Skeleton, 1",
"TM_Zombie, 1",
"TM_Spider, 1"
};
// Do not modify anything below here.
private clearscope String ProcessCmdStr(String req, String str, int i, double d, Object o) const
{
if (req ~== "GetXP")
{
if (i >= 0 && i < mon.Size())
return mon[i];
}
return "";
}
override String GetString(String request, String stringArg, int intArg, double doubleArg, Object objectArg)
{ return ProcessCmdStr(request, stringArg, intArg, doubleArg, objectArg); }
override String GetStringUI(String request, String stringArg, int intArg, double doubleArg, Object objectArg)
{ return ProcessCmdStr(request, stringArg, intArg, doubleArg, objectArg); }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment