Starting some scripting, looking for some commands
Starting some scripting, looking for some commands
I've written scripts before, and I've even written in UnrealScript before. But I've never done any scripts in UT99 before, so I don't really know how this game handles a lot of its, well, everything.
So I'm looking for some help getting started.
I already know the basics of writing code, but I don't know what existing functions I can call, nor what existing methods I have to conform to.
When looking through the documentation and tutorials I have found through this site, I have been unable to find anything that gets into the real meat of scripting for Unreal; just basic beginner stuff of writing code in general and compiling. Nothing that can explain to me how to do anything specific. I'm hoping someone here can fill in the gaps, or at least show me how to find out these things on my own.
Right now what I'm looking to do is to modify a mutator someone made to add in some features that I am looking for. Conceptually, this isn't hard, but I have no clue what functions I need to call.
The first thing I need to do is cause the mutator to spawn some bots (under certain conditions) and then remove those bots (under certain conditions). I know this is possible because I can see other mutators that do it, but I can't see the code they used.
The next thing I need to do is display some text on the HUD. Not the message that goes to the log, but text displayed prominently in the center of the screen, like when you make a double-kill.
I'm also curious if it is possible to have code that responds to player input and displays text before the player is spawned into the game, in those first few seconds when a match "exists" and everyone is in spectator mode and no one has spawned yet. If so I would like to add the capacity for players to preemptively set how they spawn in connection with this mutator.
And the last thing I would want to do is call a function or two if the player remains dead for too long.
I could guess how to set this stuff up, but code doesn't work on guesses or people describing the gist of what they want; code needs to be exact.
I feel really silly asking for this stuff, because anyone who could tell me how to do any of this could also just write the code themselves easier than it could be explained. But unless I can find some examples of what I am looking for and/or a complete and searchable documentation on the scripting API, then the only resource I have is to ask.
So I'm looking for some help getting started.
I already know the basics of writing code, but I don't know what existing functions I can call, nor what existing methods I have to conform to.
When looking through the documentation and tutorials I have found through this site, I have been unable to find anything that gets into the real meat of scripting for Unreal; just basic beginner stuff of writing code in general and compiling. Nothing that can explain to me how to do anything specific. I'm hoping someone here can fill in the gaps, or at least show me how to find out these things on my own.
Right now what I'm looking to do is to modify a mutator someone made to add in some features that I am looking for. Conceptually, this isn't hard, but I have no clue what functions I need to call.
The first thing I need to do is cause the mutator to spawn some bots (under certain conditions) and then remove those bots (under certain conditions). I know this is possible because I can see other mutators that do it, but I can't see the code they used.
The next thing I need to do is display some text on the HUD. Not the message that goes to the log, but text displayed prominently in the center of the screen, like when you make a double-kill.
I'm also curious if it is possible to have code that responds to player input and displays text before the player is spawned into the game, in those first few seconds when a match "exists" and everyone is in spectator mode and no one has spawned yet. If so I would like to add the capacity for players to preemptively set how they spawn in connection with this mutator.
And the last thing I would want to do is call a function or two if the player remains dead for too long.
I could guess how to set this stuff up, but code doesn't work on guesses or people describing the gist of what they want; code needs to be exact.
I feel really silly asking for this stuff, because anyone who could tell me how to do any of this could also just write the code themselves easier than it could be explained. But unless I can find some examples of what I am looking for and/or a complete and searchable documentation on the scripting API, then the only resource I have is to ask.
Re: Starting some scripting, looking for some commands
I recommend you to join the Discord server and ask for help in the #uscript room.
Just to mention, yes - all these things are possible.
Just to mention, yes - all these things are possible.
Re: Starting some scripting, looking for some commands
Not quite sure what you mean when you say you can't see the code - the code of the mutator you link to can be exported by UEd or UTPT - here it isMarscaleb wrote: The first thing I need to do is cause the mutator to spawn some bots (under certain conditions) and then remove those bots (under certain conditions). I know this is possible because I can see other mutators that do it, but I can't see the code they used.
Code: Select all
class MyBots extends Mutator;
var int BotNum;
var bool bInit;
var bool bBotsKicked;
function PostBeginPlay()
{
if (!bInit)
{
bInit = true;
BotNum = DeathMatchPlus(Level.Game).MinPlayers - 1;
SetTimer(5, true);
bBotsKicked = false;
}
}
function Timer()
{
local int i;
if (Level.Game.NumPlayers == 1 && DeathMatchPlus(Level.Game).NumBots == 0 && bBotsKicked && BotNum > 0)
{
for (i=0; i<BotNum; i++)
{
Level.Game.ForceAddBot();
}
bBotsKicked = false;
}
}
function ModifyPlayer( Pawn Other )
{
Super.ModifyPlayer( Other );
if (Level.Game.NumPlayers > 1)
{
if (DeathMatchPlus(Level.Game).NumBots > 0)
{
KickBots();
bBotsKicked = true;
}
}
}
function KickBots()
{
local int i, j;
j = DeathMatchPlus(Level.Game).NumBots;
for (i=0; i<j; i++)
{
RemoveBot();
}
}
function bool RemoveBot()
{
local Bot DumbBot;
local Pawn P, OtherPawn;
local actor A;
for (P = Level.PawnList; P != None; P = P.NextPawn)
{
if (Bot(P) != None) // get Bot with least score
if (DumbBot == None || P.PlayerReplicationInfo.Score < DumbBot.PlayerReplicationInfo.Score)
DumbBot = Bot(P);
}
if (DumbBot != None)
{
DumbBot.Destroy();
DeathMatchPlus(Level.Game).MinPlayers -= 1;
return true;
}
return false;
}
-
- Inhuman
- Posts: 958
- Joined: Wed Mar 31, 2010 9:02 pm
- Personal rank: I am quite rank.
- Location: MrLoathsome fell out of the world!
Re: Starting some scripting, looking for some commands
This would be the best way to handle what you want to do. With a separate mutator to manage the number of bots in theOjitroC wrote:If this gives you what you want, why not run this mutator alongside the SpecStart mutator?
match.
The way I had to write the SpecStart, pretty much excludes doing any of that sort of thing with the SpecStart source.
Attempt some various configs with some of those other mutators, and see if you can get things working the way you want.
In the event that you cant, writing a new mutator to manage bots that accounts for SpecStart running is the way to go.
If you want/need the number of bots added to factor in how many players are playing AND how many are still in SpecStart
spectating mode, I attempted to write it in a way that other mutators could check that. (*Not tested...)
I don't think you will need to make your new mutator dependent upon Specstart either. (No need in EditPackages for this check.)
Your check would look something like this:
Code: Select all
if (TournamentPlayer(A).SSCheck != None) (* Player A is still in SpecStart mode... Do whatever... *)
it is taking for SpecStart to get fully initialized and get the SSCheck actor spawned and attached to the new players as they join.
To avoid your mutator falsely detecting that the player has joined the game BEFORE SpecStart has actually even kicked in and spawned
the players SSCheck actor.
Can't state an exact number for the length of that delay, as it will vary depending upon the values you are using in the SpecStart config
to get the thing to work with your gametype.
Also, look at using commands ClientMessage and BroadcastMessage in your mutators ModifyPlayer code for sending custom text strings.
blarg
- sektor2111
- Godlike
- Posts: 6411
- Joined: Sun May 09, 2010 6:15 pm
- Location: On the roof.
Re: Starting some scripting, looking for some commands
I'm confused.Marscaleb wrote:I've written scripts before, and I've even written in UnrealScript before. But I've never done any scripts in UT99 before, ...
This -vv-
Code: Select all
if (TournamentPlayer(A).SSCheck != None)
The topic's personal opinion:
If you cannot write a simple thing - a mutator for scoring something or such a simple feature, this task requires some advanced knowledge and some small experience with UScript... This takes time, looking at mutators, learning, compiling, testing, else result is None. Actually you cannot start coding with advanced things unless you want to have a default failure...
Just my two cents.
-
- Inhuman
- Posts: 958
- Joined: Wed Mar 31, 2010 9:02 pm
- Personal rank: I am quite rank.
- Location: MrLoathsome fell out of the world!
Re: Starting some scripting, looking for some commands
Well that example is sort of psuedo-code.sektor2111 wrote:I'm confused.
This -vv-TournamentPlayer probably doesn't include any sort of "SSCheck" property or variable if I well recall... Or I might be wrong...Code: Select all
if (TournamentPlayer(A).SSCheck != None)
Been about 10 months now since I actually messed with any UScript...
Obviously TournamentPlayer has no SSCheck property or value by default.
Point is that when a player has joined the server and is in SpecStart v3.0 spectating mode, they will have an SSCheck actor
assigned/attached to them when they enter the server. When they actually leave the spectating mode(s) and join the game, the SSCheck
actor assigned to that player will be destroyed.
In the event that something like my above check does not work, you could have your custom mutator do a foreach actors check
on class SpecStart.SSCheck and then determine which players are still in SpecStart mode by checking SSCheck.Owner. (I think... )
This method would of course require you to have SpecStart v3.0 as an EditPackage.
I do agree with sektor2111 suggestion that you should examine the default scripts some, looking specifically at the gametype sources that
handle the adding/removing of both bots and players into the matches.
Would also recommend exporting and looking at the source scripts for the various other mutators out there that are doing similar things.
The SpecStart v3.0 source is probably NOT a good thing to be looking at while reviewing code to prepare yourself for making your first
mutator. Not saying it is all "advanced' or anything like that, its just that I had to do a lot of unconventional and convoluted things
to make it work the way it does with all the games and gametypes it does. And there are no comments at all.
THAT BEING SAID....
It might even be possible to have the SpecStart mutator itself modify the game settings for Min/MaxPlayers and add or remove a bot, but
that would require some actual testing to be sure. (Probably a lot...)
You would want to remove your bot or bot(s) at the point in the SSCheck class right before it destroys itself and the player actually joins the match.
Would probably also need to add some code to have it add the bot or bot(s) back into the game when players leave the server.
Note, this is all just guessing off the top of my head. I would have to try some things out and see what happens to be sure.
Quite possible that would not work at all...
Most likely you would have to add a bunch of checks for gametype, if it is a team game, etc etc. Would need to be carefully done
to avoid breaking things. If you do attempt to make your own custom version of SpecStart, change the name of the class to avoid
any future mismatch nightmares.
Good luck. Keep us posted on any progress, or if you come up with any specific questions.
blarg
Re: Starting some scripting, looking for some commands
The reason I can't use that mutator alongside this one is because it doesn't work in the way I need; I used it as an example because it does something that I do need. It does spawn and remove bots, but just not under the terms and conditions I will need.
Thank you all for the information; I'll take a look at this hopefully tonight, and hopefully the next time I have a question it will be something more specific.
Thank you all for the information; I'll take a look at this hopefully tonight, and hopefully the next time I have a question it will be something more specific.
Re: Starting some scripting, looking for some commands
Okay, a couple specific questions I have.
#1
Looking at the MyBots mutator, we have this code for when it removes a bot from play:
The Destroy command actually removes the bot from play. But what is the MinPlayers -= 1 for?
If I am reading this code right, that is a variable for the actual gametype, the one set by the server. (It certainly isn't a variable created within the script.) So I am left to wonder why this is being called.
I would venture a guess that this is a necessary cleanup after using Destroy to remove the bot, but I do not understand why. Does Level.Game.ForceAddBot() increase that counter, but there is no ForceRemoveBot function that handles the other end of it?
#2
When exactly is "PostBeginPlay()" called? I was going to guess that it is after the match has begun (players spawned and whatnot) but looking at some mutators suggests this is called at the beginning of a match BEFORE anyone is spawned, when everyone is still flying around in spectator mode.
Also I see everyone adding an "initialized" check to this function to make sure it doesn't get called twice. What conditions are calling that function multiple times? And I've seen one that also calls the Super.PostBeginPlay(), but the other mutators I've looked at do not. Is there anything in the Super.PostBeginPlay that does anything?
#3
What conditions call the function"ModifyPlayer(Pawn Other)"? Apparently it at least gets called when someone joins a game, but I don't know if/when other times it may be called.
#4
So I'm guessing the function "SetTimer(5, true);" calls the function "Timer()" after a set amount of time. (Correct me if I'm wrong.) What is the "true" flag for? I would guess the "5" is the time interval in seconds, and looking at some other mutators that call this function, I would assume it takes a float value but Unreal Script doesn't care if you say "5" or "5.0". (Correct me if I'm wrong.)
#5
What function will draw text on the HUD? (Not just send text the the log.) I don't have any mutators that do this, and don't know where to go looking to find the code.
#6
What function(s) will generate a random number, and what format/range will it come out as?
#1
Looking at the MyBots mutator, we have this code for when it removes a bot from play:
Code: Select all
if (DumbBot != None)
{
DumbBot.Destroy();
DeathMatchPlus(Level.Game).MinPlayers -= 1;
return true;
}
If I am reading this code right, that is a variable for the actual gametype, the one set by the server. (It certainly isn't a variable created within the script.) So I am left to wonder why this is being called.
I would venture a guess that this is a necessary cleanup after using Destroy to remove the bot, but I do not understand why. Does Level.Game.ForceAddBot() increase that counter, but there is no ForceRemoveBot function that handles the other end of it?
#2
When exactly is "PostBeginPlay()" called? I was going to guess that it is after the match has begun (players spawned and whatnot) but looking at some mutators suggests this is called at the beginning of a match BEFORE anyone is spawned, when everyone is still flying around in spectator mode.
Also I see everyone adding an "initialized" check to this function to make sure it doesn't get called twice. What conditions are calling that function multiple times? And I've seen one that also calls the Super.PostBeginPlay(), but the other mutators I've looked at do not. Is there anything in the Super.PostBeginPlay that does anything?
#3
What conditions call the function"ModifyPlayer(Pawn Other)"? Apparently it at least gets called when someone joins a game, but I don't know if/when other times it may be called.
#4
So I'm guessing the function "SetTimer(5, true);" calls the function "Timer()" after a set amount of time. (Correct me if I'm wrong.) What is the "true" flag for? I would guess the "5" is the time interval in seconds, and looking at some other mutators that call this function, I would assume it takes a float value but Unreal Script doesn't care if you say "5" or "5.0". (Correct me if I'm wrong.)
#5
What function will draw text on the HUD? (Not just send text the the log.) I don't have any mutators that do this, and don't know where to go looking to find the code.
#6
What function(s) will generate a random number, and what format/range will it come out as?
Re: Starting some scripting, looking for some commands
I recommend some reading here: wiki.beyondunreal: What happens when an Actor is spawned.Marscaleb wrote:When exactly is "PostBeginPlay()" called?
Just walk up in the object hierarchy tree to see what parent objects do in that function.Marscaleb wrote:Is there anything in the Super.PostBeginPlay that does anything?
I recommend downloading or extracting all script sources from UT. (For a better understanding I created a directory tree corresponding to the object hierarchy and put the UC script files there (see pic): I use a text search program to find all occurrences of a function or variable.)
Again see Wiki.Marscaleb wrote:"SetTimer(5, true);" [...] What is the "true" flag for?
Ahem, wiki with keywords rand and frand? ;o)Marscaleb wrote:What function(s) will generate a random number
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
- sektor2111
- Godlike
- Posts: 6411
- Joined: Sun May 09, 2010 6:15 pm
- Location: On the roof.
Re: Starting some scripting, looking for some commands
EXPORT BOTPACK and everything and just read the damn codes. Right here mutator is decreasing number of MinPlayers value for NOT SPAWNING another Bot when actually mutator has removed one - LOGIC. The best of logic would be to check if MinPlayers is not being set to 0 by a genius admin or such for preventing going under 0 value...Marscaleb wrote:The Destroy command actually removes the bot from play. But what is the MinPlayers -= 1 for?
It's automated - USE LOG LINES for tests inside functions but not after any return found - if exist.Marscaleb wrote:When exactly is "PostBeginPlay()" called?
Code: Select all
log("This is something called.");
No, is not, is coder's fart used to do multiple calls to nothing...Marscaleb wrote:Super.PostBeginPlay that does anything?
Read Engine - GameInfo.uc - AGAIN export stupid scripts from Editor. This will have a call when match is being started and/or a player respawns post killed.Marscaleb wrote:What conditions call the function"ModifyPlayer(Pawn Other)"?
Again - USE LOG lines for tests and figuring things - guessing doesn't help at all.Marscaleb wrote:So I'm guessing the function "SetTimer(5, true);" calls the function "Timer()" after a set amount of time. (Correct me if I'm wrong.) What is the "true" flag for? I would guess the "5" is the time interval in seconds, and looking at some other mutators that call this function, I would assume it takes a float value but Unreal Script doesn't care if you say "5" or "5.0". (Correct me if I'm wrong.)
Postrender ? See Mutator.uc from Engine, HUD, ChallengeHUD, etc. - again Export all scripts...Marscaleb wrote:What function will draw text on the HUD? (Not just send text the the log.) I don't have any mutators that do this, and don't know where to go looking to find the code.
Export Scripts and look into Object.uc - probably you need RandRange or Rand or FRand.Marscaleb wrote:What function(s) will generate a random number, and what format/range will it come out as?
Aside for clarifications Wiki is in charge - if plonkers did not ruin it.
Re: Starting some scripting, looking for some commands
Thank you for the information! Working on stuff now...
Two more quick questions.
Is there a function that gets called when the match actually starts (ie when the players spawn and the game clock actually starts counting down)?
And two... I've added a message function to PostBeginPlay but I never see this thing called more than once. Does it? Can it? All the mutators I see add init variables to make sure it doesn't get called twice, but I don't see that happening...
Two more quick questions.
Is there a function that gets called when the match actually starts (ie when the players spawn and the game clock actually starts counting down)?
And two... I've added a message function to PostBeginPlay but I never see this thing called more than once. Does it? Can it? All the mutators I see add init variables to make sure it doesn't get called twice, but I don't see that happening...
- sektor2111
- Godlike
- Posts: 6411
- Joined: Sun May 09, 2010 6:15 pm
- Location: On the roof.
Re: Starting some scripting, looking for some commands
There is a solution which I learned by myself in how to capture game-start in mutators. It is used Modifyplayer. In that moment when game starts, variable from "DMplus" bstartmatch or such is true, when that thing is true you can setup your own variable bMatchIsStarted = True if is False in ModifyPlayer as first line - of course you have to declare your variable first.Marscaleb wrote:Is there a function that gets called when the match actually starts (ie when the players spawn and the game clock actually starts counting down)?
Code: Select all
class Something expands mutator;
var bool bMatchIsStarted;
....
PostBeginPlay is called once automated. Whatever you need to have a repeated execution it will need other calls, more or less scheduled: Tick, Timer, State code.Marscaleb wrote: I've added a message function to PostBeginPlay but I never see this thing called more than once. Does it? Can it? All the mutators I see add init variables to make sure it doesn't get called twice, but I don't see that happening...
Keep in mind that some mutators can force a second call to an outsider tool and that's why the most of coders were made sure to prevent a duplicate execution - in some mods this might not be a good thing. Your mutator probably is not calling itself but can be stupidly called by others from chain and you need to guard your code somehow. To light you up, mutator which you described does a call to DeathMatchplus forcing a "push" code which is not done by DeathMatchplus itself in that moment. This way works Bot too if you check some CTF DOM AS etc codes. So to speak you might have a function in mutator never called but, you can call it using a Server Actor unseen, this is how UScript works - as a good point from me.
Re: Starting some scripting, looking for some commands
PostBeginPlay() is an init function in a way. Such an init function - not only PostBeginPlay() - can be called multiple times, by error, dumbness or whatever. If that function does not change the system's state if it is called multiple times, a check for multiple calls is not needed. Example:Marscaleb wrote:I've added a message function to PostBeginPlay but I never see this thing called more than once. Does it? Can it?
Code: Select all
Function Init() {
MyValue = 3; // call this n times - nothing changes
}
Code: Select all
Function Init() {
Spawn(Class'InitHelper'); // after each call one instance more will exist
MyValue = MyValue * 2; // double your money on each call
}
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Re: Starting some scripting, looking for some commands
Dang. ModifyPlayer isn't accessible through Actor, so I can't go that route to add such functionality to the SSCheck class in this mutator.sektor2111 wrote:There is a solution which I learned by myself in how to capture game-start in mutators. It is used Modifyplayer. In that moment when game starts, variable from "DMplus" bstartmatch or such is true, when that thing is true you can setup your own variable bMatchIsStarted = True if is False in ModifyPlayer as first line - of course you have to declare your variable first.Marscaleb wrote:Is there a function that gets called when the match actually starts (ie when the players spawn and the game clock actually starts counting down)?
Edit: Oh wait, this class is already running some inits that get called when the match starts. Never mind.
- sektor2111
- Godlike
- Posts: 6411
- Joined: Sun May 09, 2010 6:15 pm
- Location: On the roof.
Re: Starting some scripting, looking for some commands
ModifyPlayer is resident in Mutator not Actor.
Also Modifyplayer can be used itself to do checks because it works when player spawns... that's why here you can attach an actor to player and making sure to not already have one owned, unless you want a stacking actors loading Level and doing funky things... and ModifyPlayer doesn't need to get multiple calls forced, it is called automatically when it needs...
Also Modifyplayer can be used itself to do checks because it works when player spawns... that's why here you can attach an actor to player and making sure to not already have one owned, unless you want a stacking actors loading Level and doing funky things... and ModifyPlayer doesn't need to get multiple calls forced, it is called automatically when it needs...