This week I was able to create AutoMove (a.k.a. AutoForward) functionality in Zscript.
It works similar to the AutoMove toggle key in Skyrim:
Press 'F' to automatically move forward until either
a) press 'F' again
or b) press a WASD key
Also, move at run speed when holding down the left Shift key.
I just hardcoded these keys in the code below, since I don't need a menu option.
I want to thank:
- m8f for the final piece. I wouldn't have movement without him!
- Nash for his movement mod. It provided the necessary Inventory structure.
- The GZ devs for this excellent game engine with powerful scripting capability.
Everyone has full freedom to do whatever they want with my code.
[success] create AutoMove functionality
Moderator: GZDoom Developers
Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.
Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.
Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
-
- Posts: 43
- Joined: Sun Nov 29, 2020 6:46 pm
[success] create AutoMove functionality
Last edited by fcas3t on Sat Dec 05, 2020 8:45 pm, edited 5 times in total.
-
- Posts: 43
- Joined: Sun Nov 29, 2020 6:46 pm
Re: How to create Automove (aka Autoforward) functionality?
edit: delete obsolete question and code
-
- Posts: 43
- Joined: Sun Nov 29, 2020 6:46 pm
Re: Need help creating Automove functionality
I've spent a number of hours this week trying to accomplish this goal. Unfortunately, after making some progress, I think I've hit a wall.
Even though a) the keyboard inputs are detected properly, b) my global-like 'thrust' var is being set properly, and c) the Tick override is applying it the way I thought would work, there just isn't any movement.
(As a last resort, I even tried moving Super.Tick() at the beginning of the function, but it made no difference.)
At the end of the code you'll see the 2 Printfs. The first one always reports 0 for the cmd.forwardmove, and the second always reports it being set properly with the h.thrust value. (And it's always the right intervals based on my button presses, though of course it's 2 printfs per tick, so the console fills fast. If you want to try it, I suggest pressing F twice in rapid succesion. Mix in presses of left Shift too for the running speed.)
These thrust values are what I found from Github web searches of the GZ repo. (For instance, see here, here and here.)
So my question now:
Is it even possible to induce player movement via Zscript?
If the answer is Yes, and you know how to do it, please respond here. I really would like this AutoMove feature; it would mean less W-keying for backtracking, looting after a fight, etc. Save some strain on my middle finger please
Otherwise, I guess it would mean having to modify the GZ source. That's a route I'd rather not go down.
Anyhow, here's my code. If you want to try it, just make the 2 text files and zip them up. (I'm sharing it this way because I benefitted from searchable code snippets on the forum in the process of getting as far as I did.)
mapinfo.txt
zscript.zc
Even though a) the keyboard inputs are detected properly, b) my global-like 'thrust' var is being set properly, and c) the Tick override is applying it the way I thought would work, there just isn't any movement.
(As a last resort, I even tried moving Super.Tick() at the beginning of the function, but it made no difference.)
At the end of the code you'll see the 2 Printfs. The first one always reports 0 for the cmd.forwardmove, and the second always reports it being set properly with the h.thrust value. (And it's always the right intervals based on my button presses, though of course it's 2 printfs per tick, so the console fills fast. If you want to try it, I suggest pressing F twice in rapid succesion. Mix in presses of left Shift too for the running speed.)
These thrust values are what I found from Github web searches of the GZ repo. (For instance, see here, here and here.)
So my question now:
Is it even possible to induce player movement via Zscript?
If the answer is Yes, and you know how to do it, please respond here. I really would like this AutoMove feature; it would mean less W-keying for backtracking, looting after a fight, etc. Save some strain on my middle finger please

Otherwise, I guess it would mean having to modify the GZ source. That's a route I'd rather not go down.
Anyhow, here's my code. If you want to try it, just make the 2 text files and zip them up. (I'm sharing it this way because I benefitted from searchable code snippets on the forum in the process of getting as far as I did.)
mapinfo.txt
Code: Select all
GameInfo
{
AddEventHandlers = "AutoForwardHandler"
}
Code: Select all
version 4.2
class AutoForwardHandler : EventHandler
{
int16 thrust;
override void OnRegister()
{
thrust = 0;
}
override void WorldTick()
{
if ( level.time == 0 )
{
thrust = 0;
}
}
override bool InputProcess( InputEvent e )
{
if ( e.Type == InputEvent.Type_KeyDown )
{
if ( e.KeyScan == 0x11 || e.KeyScan == 0x1F )
{
SendNetworkEvent( "AF_stop" );
}
else if ( e.KeyScan == 0x21 )
{
SendNetworkEvent( "AF_toggle" );
}
else if ( e.KeyScan == 0x2A )
{
SendNetworkEvent( "AF_shift_pressed" );
}
}
else if ( e.Type == InputEvent.Type_KeyUp && e.KeyScan == 0x2A )
{
SendNetworkEvent( "AF_shift_released" );
}
return false;
}
override void NetworkProcess( ConsoleEvent e )
{
if ( e.Name == "AF_stop" )
{
thrust = 0;
}
else if ( e.Name == "AF_toggle" ) // values from b_bot.h
{
thrust = thrust ? 0 : 0x1900;
}
else if ( e.Name == "AF_shift_pressed" && thrust == 0x1900 )
{
thrust = 0x3200;
}
else if ( e.Name == "AF_shift_released" && thrust == 0x3200 )
{
thrust = 0x1900;
}
}
override void PlayerEntered( PlayerEvent e )
{
players[ e.PlayerNumber ].mo.A_GiveInventory( "DoAutoForward", 1 );
}
}
class DoAutoForward : Inventory
{
AutoForwardHandler h;
override void Tick()
{
if ( owner && owner.player )
{
// since each level has its own handler
h = AutoForwardHandler( EventHandler.Find("AutoForwardHandler") );
if ( h.thrust )
{
Console.Printf( "cmd.fm before = 0x%X", owner.player.cmd.forwardmove );
owner.player.cmd.forwardmove = h.thrust;
Console.Printf( "h.thrust = 0x%X cmd.fm = 0x%X", h.thrust, owner.player.cmd.forwardmove );
}
}
Super.Tick();
}
}
-
-
- Posts: 1456
- Joined: Fri Dec 29, 2017 4:15 am
- Preferred Pronouns: He/Him
- Location: Siberia (UTC+7)
Re: Trying to create AutoMove functionality
Use PlayerPawn.ForwardThrust (double move, double angle).
-
-
- Posts: 1456
- Joined: Fri Dec 29, 2017 4:15 am
- Preferred Pronouns: He/Him
- Location: Siberia (UTC+7)
Re: Trying to create AutoMove functionality
The simpler, though hacky solution, will be this keyconf:
Just load this single file and assign the key in "Customize Controls" menu.
Code: Select all
alias startrun "+forward; +forward; rebind stoprun"
alias stoprun "openmenu mainmenu; closemenu; rebind startrun"
AddKeySection "Autorun" "Autorunkeys"
AddMenuKey "Autorun" startrun
You do not have the required permissions to view the files attached to this post.
-
- Posts: 43
- Joined: Sun Nov 29, 2020 6:46 pm
Re: Trying to create AutoMove functionality
THANK YOU!!! This was the missing piece. Now I have movement, and it works perfectly!m8f wrote:Use PlayerPawn.ForwardThrust (double move, double angle).
Here's the working code.
Note that you can change the AutoWalk and AutoRun speeds

After testing it out, I decided to stop AutoMove for any WASD key. It works more naturally this way (unlike Skyrim, which doesn't stop with the A or D keys for some reason).
mapinfo.txt
Code: Select all
GameInfo
{
AddEventHandlers = "AutoForwardHandler"
}
Code: Select all
version 4.2
class AutoForwardHandler : EventHandler
{
double speed;
const VEL_WALK = 1.0;
const VEL_RUN = 2.0;
override void OnRegister()
{
speed = 0.0;
}
override void WorldTick()
{
if ( level.time == 0 )
{
speed = 0.0;
}
}
override bool InputProcess( InputEvent e )
{
if ( e.Type == InputEvent.Type_KeyDown )
{
switch ( e.KeyScan )
{
case 0x11: // WASD
case 0x1E:
case 0x1F:
case 0x20:
SendNetworkEvent( "AF_stop" );
break;
case 0x21: // F
SendNetworkEvent( "AF_toggle" );
break;
case 0x2A:
SendNetworkEvent( "AF_shift_pressed" );
}
}
else if ( e.Type == InputEvent.Type_KeyUp && e.KeyScan == 0x2A )
{
SendNetworkEvent( "AF_shift_released" );
}
return false;
}
override void NetworkProcess( ConsoleEvent e )
{
if ( e.Name == "AF_stop" )
{
speed = 0.0;
}
else if ( e.Name == "AF_toggle" )
{
speed = ( speed == 0.0 ) ? VEL_WALK : 0.0;
}
else if ( e.Name == "AF_shift_pressed" && speed == VEL_WALK )
{
speed = VEL_RUN;
}
else if ( e.Name == "AF_shift_released" && speed == VEL_RUN )
{
speed = VEL_WALK;
}
}
override void PlayerEntered( PlayerEvent e )
{
players[ e.PlayerNumber ].mo.A_GiveInventory( "DoAutoForward", 1 );
}
}
class DoAutoForward : Inventory
{
AutoForwardHandler h;
override void Tick()
{
if ( Owner && Owner is "PlayerPawn" )
{
// since each level has its own handler
h = AutoForwardHandler( EventHandler.Find("AutoForwardHandler") );
if ( h.speed > 0.0 )
{
/* This works perfectly with mouselook. The mouse
controls the angle, so use the dummy value here.
*/
PlayerPawn( Owner ).ForwardThrust( h.speed, 1e37 );
}
}
Super.Tick();
}
}
-
- Posts: 880
- Joined: Tue May 07, 2019 12:24 pm
- Graphics Processor: nVidia with Vulkan support
Re: [success!] create AutoMove functionality
all this work, couldn't you just map forward and sprint to one button and make it a toggle?
-
- Posts: 43
- Joined: Sun Nov 29, 2020 6:46 pm
Re: [success] create AutoMove functionality
Important Update
Turns out the solution has a few deficiencies, but thankfully I've figured out the best possible solution.
The problem with yesterday's solution (for which I am grateful; I was elated to finally see movement!) is that it bypasses the adjustments made in PlayerPawn.MovePlayer() when the player is airborne, walking down stairs, and other special considerations. So when I was playing earlier today, I was getting jarring doses of acceleration during AutoMove when jumping or walking down stairs.
Taking a fresh look at the GZ code revealed the solution, which is to invoke the function I just mentioned after setting cmd.forwardmove. So, in a roundabout way, I now have the first version of the code working. And it works beautifully. Automatic movement is now just like manual in every way, since the mod does the same thing the game normally does.
I'm not going to post another version of the full code. Instead, here's a patch for the first version of the code above:
In other words, replace the Printfs section with this new code.
I also recommend making constants like I did in the second version of the code, plus the full WASD detection in the second version.
But I leave all of that as an exercise to anyone interested in using this code.
(And to acknowledge the other item in this thread, the custom keyboard binds that m8f graciously posted and Dan asked about, I don't know anything about it and have no interest. I prefer AutoMove to be a slower speed than manual movement, and only my code can do that.)
Turns out the solution has a few deficiencies, but thankfully I've figured out the best possible solution.
The problem with yesterday's solution (for which I am grateful; I was elated to finally see movement!) is that it bypasses the adjustments made in PlayerPawn.MovePlayer() when the player is airborne, walking down stairs, and other special considerations. So when I was playing earlier today, I was getting jarring doses of acceleration during AutoMove when jumping or walking down stairs.
Taking a fresh look at the GZ code revealed the solution, which is to invoke the function I just mentioned after setting cmd.forwardmove. So, in a roundabout way, I now have the first version of the code working. And it works beautifully. Automatic movement is now just like manual in every way, since the mod does the same thing the game normally does.
I'm not going to post another version of the full code. Instead, here's a patch for the first version of the code above:
Code: Select all
if ( h.thrust )
{
Owner.player.cmd.forwardmove = h.thrust;
PlayerPawn( Owner ).MovePlayer();
}
I also recommend making constants like I did in the second version of the code, plus the full WASD detection in the second version.
But I leave all of that as an exercise to anyone interested in using this code.
(And to acknowledge the other item in this thread, the custom keyboard binds that m8f graciously posted and Dan asked about, I don't know anything about it and have no interest. I prefer AutoMove to be a slower speed than manual movement, and only my code can do that.)