I'm working on a fairly simple little script (my first) to implement a couple of features which we'd like to see available on our BunnyTrack server. It's gone pretty well (thanks again to Sponge for guidance), and I've been able to cull much of what I need from other existing units.
But I have a few problems and questions which I hope more experienced UnrealScripters will be able to help me with. In each case, I'm getting information from the BTPlusPlus class.
1) I needed a way of checking whether, when a flag capture occurs, the player's new record was a) faster then the server record, or b) their first capture on a given map, or c) not their first cap on a given map. I've been able to do this by monitoring player connects, and when a connect is spotted, asking BTPlusPlus to give me their "BestTime" for the current map. Then, when a capture is observed (by listening in on MutatorBroadcastLocalizedMessage), I can check their new "BestTime" against the "BestTime" I stored when they first joined the server. That's fine. Long winded, but it works (a "0" previous BestTime means first cap for the map, a BestTime < Server.BestTime means a new record etc.).
The reason I have to go to the trouble of storing BestTimes when a player first connects, instead of being able to check these things when a flag cap takes places, is that by the time I can ask the BTPlusPlus class about BestTimes (in MutatorBroadcastLocalizedMessage), the old value has been replaced by the new one - a new faster time overwrites the previous one. So I can't use it to make any decisions about whether it was their first cap for the map, and so on.
But, I see an intriguing bit of code in FlagDisposer.uc on line 110
Code: Select all
Controller.SendEvent("btcap", aTPawn.PlayerReplicationInfo.PlayerID, NewTime, TimeStamp);
Code: Select all
//====================================
// SendEvent - Sends custom events to all registered actors
//====================================
function SendEvent(string EventName, optional coerce string Arg1, optional coerce string Arg2, optional coerce string Arg3, optional coerce string Arg4)
{
local Actor A;
local int i;
local string Event;
if (Level.Game.LocalLog != None)
Level.Game.LocalLog.LogSpecialEvent(EventName, Arg1, Arg2, Arg3, Arg4);
Event = EventName;
if(Arg1 != "")
Event = Event$chr(9)$Arg1;
if(Arg2 != "")
Event = Event$chr(9)$Arg2;
if(Arg3 != "")
Event = Event$chr(9)$Arg3;
if(Arg4 != "")
Event = Event$chr(9)$Arg4;
for(i=0;i<EventHandlersCount+1;i++)
{
if(EventHandlers[i] != None)
EventHandlers[i].GetItemName(Event);
}
}
But. To me, as a total newbie, this function looks like it's not doing anything more than calling the GetItemName function and not actually doing anything with the result?
I'm hoping I'm wrong about that, and that there is some way of using this as a callback system somehow, so if anyone can talk about that I'd be very happy to listen. It'd simplify things, basically.
2) I want players to be able to check the most recent server records. Adding this as a mutate command was pretty straightforward, I just modified the BLPlusPlus code a bit. But, some of the information I want to supply to any player that uses it is unavailable. The information I want to ask for is stored in the ServerRecords class, which is accessible as an object inside of the BTPlusPlus class as a variable called "SR".
The ServerRecords class has an array with 3000 slots. I've been hitting my head against this "variable is too large" error quite a bit when attempting to access arrays in other classes, but luckily ServerRecords has 3 getter functions called getCaptime, getTimestamp and getPlayerName. But... the other important item of information that I want from that thing is the map name! And there's no function for extracting that. Which seems a bizarre omission.
I realise ServerRecords was only designed to service BTPlusPlus, and BTPlusPlus apparently has no need to be able to look up the map names connected with a server record. But just for the sake of completion! The other 3 functions get the values stored in 3 fields of a struct that only has 4 fields. Why write 1-line getter functions for only 3 out of 4 of them? As the original coder, that kind of thing would drive me crazy, I'd have to do it just to round things off! Honestly, I thought I must have accidentally delete "getMapName" or something, but no, it's really not there.
But anyway. This is a problem. It's no use just telling the player "Ah, here are the most recent records. Here are the times, and the players... but you'll have to guess which maps these are for. Hahah!". I don't really know how I can get around this. I've had a couple of ideas, but I don't like them, so I could really do with some advice.
Bad idea 1: instead of using my own config file, I tell my class to store everything in the BTPlusPlus.ini file. I've no idea how this works at the moment, I just know that other mutators sometimes store their config variables in the UnrealTournament.ini file (for example). So, my thinking was, if I could make my class use the BTPlusPlus.ini file, that will also give me access to the list of server records stored in that file(?). Of course, this idea falls down (assuming it's technically feasible to begin with) because *my* copy of the server records wouldn't get updated when a player beat a server record or set a new one, so I'd have stale data. I suppose, after a cap, I could update my copy with the new values... but the idea of all of this overhead is not appealing.
Bad idea 2: recompile a custom version of BTPlusPlus. Which I'm loathe to do for a number of reasons. Firstly, because if a new version comes out later, I'd have to go through the process of making my own version all over again. Secondly it would mean extra downloads to visits of our server only. And we don't like downloads.
But that's it. That's all I can come up with. All for the want of a missing 1-line getter function. Tsk. But, if anyone else can suggest something better, I'd be really, really super grateful.
Well, this was a lot longer than I'd meant it to be. And probably a bit meandering, I blame sleep deprivation. Thanks for reading!