Tank Script - your sugestion wanted

Post your scripting questions / solutions here

Moderator: Moderators

Would you use a tank script ???

Poll ended at Wed Oct 23, 2002 4:20 am

Yes
4
67%
Maybe
1
17%
No
0
No votes
It seems like a pointless exercise
1
17%
 
Total votes: 6

Mirek
Colour Sergeant
Posts: 77
Joined: Mon Jul 08, 2002 2:12 am
Location: Melbourne, Australia
Contact:

Tank Script - your sugestion wanted

Post by Mirek »

Hi All,

I am currently writting a script to include tanks in SP games.
Based on the global/vehicles_thinkers.scr and similar to the way a truck with AI on it is added into the game.
I'm trying to build something that will control tank behaviour in a number of possible SP situation.

This is part of my reply in Jimmyjbo's post where I got the original idea from. Thanks Jimmyjbo :)
http://dynamic4.gamespy.com/~map/phpBB2 ... .php?t=421

My script is called tank_thinkers.scr and will live in the global directory of a map and accesed with a single thread from the map as the original is.


So far I've created four of what I call 'tank modes' -
1) Hunter - where the tank will shoot at the player or any friendlies in the game. When it acquires a target it stops and remain standing until the target is no longer alive or visible for a certain amount of time, it will then keep going on it's path.
2) Blitzcreig - same as above but the tank doesn't stop until it reaches the end on the path.
3) Passive - just drives the path with no attacking
4) Tank Battle - still working on this one but the name is pretty self explenatory. It's not for the player to drive the tank but rather have tanks fight each other around the player, to maybe include in an assualt map of some type.

It has the drive command built in so it starts moving with no extra commands necessary.
There are AI jumping out when the tanks explode.
Each tank can be looped so it travels the path over and over.
The tanks can be respawned after destraction making it posible to have waves of tanks that keep comming.
You can have as many tanks in the map as you like but at the moment each tank has to have it's own path to travel.
There are different skill levels you can apply which will change the amount of time a tank takes to reload or is stunned for.


I welcome any opinions or sugestions you may have on the subject.

I also need a couple of people to do testing, so if your into SP games and would like to help out, please email me.

Thanks all,
Mirek
Mapping !!! Who needs sleep anyway !?!?!?
jv_map
Site Admin
Posts: 6521
Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:

Well done

Post by jv_map »

Sounds like you did a great job! I don't yet need any tanks in the SP map I'm working on, but well done anyway.
jimmyjbo
Lance Corporal
Posts: 21
Joined: Fri Oct 04, 2002 7:56 pm

Post by jimmyjbo »

Hello Mirek

Of course I vote Yes in your post but many people i think they don't care so much about SP and a lot more about scripting :roll: . I don't find your work a pointless exercise at all. I strongly believe that when some of your mods will be ready and work, everybody is going to run and download it :wink: . You see, some people work for something and have knowledge about it and at the same time some others like to just click the button and take it ready or they don't care at all.

Well, people choose the side you are gona be. :D

Keep up the good work Mirek
Speak you later and thanks for your help
Mirek
Colour Sergeant
Posts: 77
Joined: Mon Jul 08, 2002 2:12 am
Location: Melbourne, Australia
Contact:

Post by Mirek »

Thanks for you're kind words guys :D

I'm sure some people will see this as pointless, to me, it's a learnning exercise in scripting, and hopefully it ends up a usefull set of scripts to somebody. If it saves someone an hour of scripting to include a couple of tanks and helps them build a map that much quicker then I'd be happy.


A word on the progress - for those intersted :)

I'm thinking of splitting the single script into a number single dedicated scripts. I think it will make it less confusing as I'm including a good number of different options for each mode.
Working on a new addition I call COVER - it will spawn a number of German AI behind the tank who will follow the tank and use it as cover. The tank will fire at the player while the AI remain behind until the tank is destroyed, they reach a destination or a certain distance to player, they then break off and attack the player.
Also including a reverse option in some modes to make the tank attack and retreat, which can be looped.

again, if you have any ideas please let me know.

Cheers,
Mirek
Mapping !!! Who needs sleep anyway !?!?!?
jv_map
Site Admin
Posts: 6521
Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:

Not sure if you already knew this...

Post by jv_map »

About the enemies who will follow the tank, try this in the script:

$enemy tether $tank

The enemy will now not stray more from the tank that his 'leash' value allows. Thus, he will not look for cover, concealment or crate nodes outside this radius from the tank. Perhaps you can use this.
Mirek
Colour Sergeant
Posts: 77
Joined: Mon Jul 08, 2002 2:12 am
Location: Melbourne, Australia
Contact:

Post by Mirek »

Thanks jv_map,

I haven't had much time with that script yet but I have tried a few commands in my perlimanary tests with no success. As soon as I got your post I tried tether but that didn't work either.
I'm not sure but I don't think the tank taps into the pathnode grid and thus commands like tether don't work - just a theory - , from expierience I know that unless you have pathnodes around the AI responds to nothing, thus the pathnodes must play an important role in how the AI interacts with it's environment.
Perhaps I have to turn the tank into a script_object or spawn script_origins and bind them to the tank for targets.

Once I just get the first line of AI to follow the tank then maybe the tether command will do it's thing for the next line of soldiers.

Thanks for the sugestion,
Mirek
Mapping !!! Who needs sleep anyway !?!?!?
jv_map
Site Admin
Posts: 6521
Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:

My follow script

Post by jv_map »

Here's an advanced follow script I used on my sp map. Except for
following you can also use it to send an AI to a static destination. The following piece of code can best be copied to a non-wordwrapping text editor.

Code: Select all

ai_moveto local.location local.movetype local.distance local.waittime local.onlywhenidle local.stopwhendone:
	local.name = self.targetname
	
	while(isAlive self && self.ai_move == 1)
		wait 0.5
		// don't interfere with other ai_move threads
		
	if !(isAlive self)
		end
	
	self.ai_move = 1
	
	// sanity checks
	if (local.location == NULL && local.location.classname != "info_pathnode")
	{
		println "	Error[ai_moveto]: location does not exist for " local.name ", ending movement thread"
		self.ai_move = 0
		end
	}
	if(local.distance == NIL || !(local.distance >= 0))
	{
		println "	Error[ai_moveto]: invalid distance (" local.distance ") for " local.name ", switched to 96"
		local.distance = 96
	}
	if(local.waittime == NIL || !(local.waittime >= 0))
	{
		println "	Error[ai_moveto]: invalid waittime (" local.waittime ") for " local.name ", switched to 0.5"
		local.waittime = 0.5
	}
	if(local.onlywhenidle == 1 && !(self.idle == 0 || self.idle == 1))
		// no idleness thread running
		local.tmp_idlethread = self thread ai_idle
	
	// init variables	
	self.stopmove = 0
	self.breakmove = 0
	self.pause = 0
	
	local.anim = ("anim/" + local.movetype + ".scr")
	
	if(local.stopwhendone != 0 && local.stopwhendone != NIL)
		self.stopmove = 1
		
	while(isAlive self && !(self.stopmove == 1 && vector_within self.origin local.location.origin local.distance) && self.breakmove == 0)
	{
		if(isAlive self && !(vector_within self.origin local.location.origin local.distance) && !(local.onlywhenidle == 1 && self.idle == 0) && self.pause == 0)
			self moveto local.anim local.location
		else
			self moveto local.anim NULL
		wait local.waittime
	}
	if(isAlive local.tmp_idlethread) local.tmp_idlethread delete
	if(isAlive self) self.ai_move = 0
end

ai_idle:
	// checks enemy idleness
	while(isAlive self)
	{
		if(self.enemy == NULL)
		{
			self.idle = 1
			while(isalive self && self.enemy == NULL)
				wait 1
		}
		else
		{
			self.idle = 0
			while(isalive self && self.enemy != NULL)
				wait 1
		}
		wait 1
	}
end
I'll explain it a bit.

Runtime parameters

The following tags can be set when starting the thread:

local.location: Sets a location for your AI to move to. This can be
any entity with an origin or a pathnode.
local.movetype: Sets the move animation to use.
Select "walk", "run", "crouch_walk", "crouch_run" or any other animation
in the anim directory.
local.distance: Set the distance to follow the location. An AI will
consider its destination reached when he's within this distance from it.
local.waittime: Number of seconds between each state check. If
you set it too high, the AI will respond very late. Setting it too low will
cause overuse of the CPU. 0.5 is a fine value.
local.onlywhenidle: Makes the AI only follow his destination when
he's not currently attacking someone. If you set it to 0, the AI will run
after the tank like crazy. If you set this to 0, you can best set
self.enableEnemy = 0 as well.
local.stopwhendone: Makes this thread end when the AI has
reached its destination. Not very useful for following script, so set it to 0.

Entity Variables

These tags are applied to the AI himself. These allow more real-time
control and can be set at any time.

self.stopmove: Set this to 1 to make the AI stop following the tank
as soon as he's reached it.
self.breakmove: Set this to 1 to make the AI instantly break his
current move and stop following his destination.
self.pause: Set this to 1 to temporarily stop the AI from following
his destination. When you set this to 0 again, the AI will resume his move.

Example

Code: Select all

$enemy thread ai_moveto $tank "run" 348 0.5 1 0
You are free to use this script in your tank script, but please mention you
used it in your readme file. If you're not planning to use it, feel free to
use it as inspiration.
Mirek
Colour Sergeant
Posts: 77
Joined: Mon Jul 08, 2002 2:12 am
Location: Melbourne, Australia
Contact:

Post by Mirek »

Thanks jv_map, :D

I tried your code out and it works great but again, not if the tank itself is the target. I tried turnning the tank into a script_object but it keeps blowing up :shock: whenever I try to respawn it - beats me why.
I've tried glueing, attaching and binding a script_origin to the tank but no success.

I intend to have the AI turned off ( global/disable_ai.scr ) while they follow the tank, And turned back on at the end of the path, tank death or the player gets too close, at which point they will be released from the script completelly.

Unfortunatelly I am working on a different part of the script at the moment so I can't do much about all that or really have agood look at your script.
When I get to work on that part of the script I will get a better chance to see how your code can help.

The main problem I am having at the moment is determaning when the tank's gun has finished it's aim movement onto it's target(player). What I need to do is stop the script while the gun tarret is turnning to aim before firing.

here is the basic firing script -

Code: Select all

while ( isalive self)
	{
		if (!(self.gun cansee $player 360) )
			{
			iprintln self " - can't see player, not firring"
			self.gun setAimTarget NULL
			wait .5
		}
		else
		{
		iprintln self " - can see player, aimming and firing"

		self.gun setAimTarget $player

		//wait 3

		self.gun anim fire
		
			wait 2
		}
	



	}
end
what I need to know is how to determine that the turret is aimming at the player after this line -

Code: Select all

		self.gun setAimTarget $player
I've tried various things including ' self.gun waittill' on many different animations, I've tried sighttrace, self.target and a few other things and nothing seems to work.

Any ideas??

Cheers,
Mirek
Mapping !!! Who needs sleep anyway !?!?!?
jv_map
Site Admin
Posts: 6521
Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:

That's a complicated thing

Post by jv_map »

What you want is quite difficult to do. Fortunately, I've had the same problem with a mg42 gun in my map, and I guess it will work all the same with a tank cannon. It contains a lot of maths to calculate the aiming offset. Well, just take a look.

Code: Select all

mg42_aim_at local.target:
	self setaimtarget local.target
	local.aimdonetime = 0
	local.allowed_offset = 5
	local.yawdone = 0
	local.pitchdone = 0
	while(isAlive local.target && local.aimdonetime < 2)
	{
		local.targetyaw = (vector_toangles (local.target.origin - self.origin))[1]
		local.targetpitch = 360 + (vector_toangles (local.target.origin - self.origin))[0]
		//println "Target -> yaw: " local.targetyaw " pitch: " local.targetpitch
		local.gunyaw = self.angles[1]
		local.gunpitch = self.angles[0]
		local.minyaw = local.gunyaw - local.allowed_offset
		local.maxyaw = local.gunyaw + local.allowed_offset
		local.minpitch = local.gunpitch - local.allowed_offset
		local.maxpitch = local.gunpitch + local.allowed_offset
		//println "Mg-42 -> yaw: " local.gunyaw " pitch: " local.gunpitch
		if(local.targetyaw >= local.minyaw && local.targetyaw <= local.maxyaw)
			local.yawdone = 1
		if(local.targetpitch >= local.minpitch && local.targetpitch <= local.maxpitch)
			local.pitchdone = 1
		if(local.yawdone == 1 && local.pitchdone == 1)
			local.aimdonetime++
		wait 0.25
	}
	if !(local.aimdonetime >= 2)
		end

	// shoot code goes here
end
This script waits till the cannon is aimed at the target with a max 10 degree offset (5 on one side, 5 on the other) for half a second (2 * 0.25).

I'm a bit afraid the pitch part of it won't work, as the tank won't rotate its entire turret up and down but only the gun.
If it doesn't work, try to replace this line

Code: Select all

if(local.yawdone == 1 && local.pitchdone == 1)
with this one

Code: Select all

if(local.yawdone == 1)
Mirek
Colour Sergeant
Posts: 77
Joined: Mon Jul 08, 2002 2:12 am
Location: Melbourne, Australia
Contact:

Post by Mirek »

Well done Mate!!!!!

If you where here I would kiss you. :P

I stuck the code in my fire loop, an it works perfecly. Just had to remove the last if statment and set the local.allowed_offset to 20, on 5 the gun would stop firing at closer distances. 20 was just right.

Now the gun fires when it points at the target instead of having to control it by time, which was sloppy. Together with a gun loading subroutine, which is controled by the difficulty level, I have the effect I wanted.

The first script is almost done now - making a quick map to go with it and got to do some testing.

Thanks Mate,
Mirek
Mapping !!! Who needs sleep anyway !?!?!?
jimmyjbo
Lance Corporal
Posts: 21
Joined: Fri Oct 04, 2002 7:56 pm

Post by jimmyjbo »

Hello there

I might know what you have to add after:

Code: Select all

self.gun setAimTarget $player
is:

Code: Select all

self.gun waittill ontarget
I suppose you need before, both the above lines this:

Code: Select all

self.gun = selfQueryTurretSlotEntity 0  // 0 is for cannon, 
//1 is for the mg
self.gun TurnSpeed 15 // 15 is the ideal speed i think

I hope it helps you

Speak to you later

-------------->JimmyJBo
Last edited by jimmyjbo on Sat Oct 12, 2002 6:11 pm, edited 1 time in total.
Mirek
Colour Sergeant
Posts: 77
Joined: Mon Jul 08, 2002 2:12 am
Location: Melbourne, Australia
Contact:

Post by Mirek »

Woo Hoo !!! That works !!!!!!!

Even better - a single line.

I'm sure I tried every posiblity for 'waittill' but must have missed that one. :D and how straight forward too - ontarget :roll:

Thanks JimmyJBO, you're a legend.

Cheers,
Mirek
Mapping !!! Who needs sleep anyway !?!?!?
jv_map
Site Admin
Posts: 6521
Joined: Tue Sep 03, 2002 2:53 pm
Location: The Netherlands
Contact:

Thanks too!

Post by jv_map »

Yeah great job Jimmy! I guess I can clean up my script right away quite a bit :).
jimmyjbo
Lance Corporal
Posts: 21
Joined: Fri Oct 04, 2002 7:56 pm

Is nice to know that it worked for you

Post by jimmyjbo »

Thanks guys,

Thats why we are here to help each other.

As for the:

Code: Select all

self.gun = selfQueryTurretSlotEntity 0  // 0 is for cannon, 
//1 is for the mg 
yes "1" is for the machine gun. I haven't try it yet but i'm sure i know how to do it in my head. :wink:

Is the same or close, like with the stuka7 firing on the player (m1l3b). You put the machine gun exactly in the position of the Tanks machine gun, you hide it , glue it and bind the origin on the tank. I'm not sure though because the tank has to be a script_model, and that change everything. The stuka works for me (little errors still) so maybe one of these days i'll try the same with the tank and tell you. I'll give it soon a better look.

Thats all for now

Keep up the good work guys

Speak to you later

--------------------->JimmyJBo
Slyk
Lieutenant Colonel
Posts: 361
Joined: Sun Jul 14, 2002 12:42 am
Location: Elizabethtown, PA

Post by Slyk »

Just wondering where all this work went in the last 2 1/2 months!?? As some of you may have gathered, I'm becoming a little pre-occupied with Tank scripts and such and hoping to apply them to my MP map(s) as independent, trigger driven mayhem machines! :twisted:

Actually hoping to use two with random paths that move, pause, and fire either at pre-scripted target locations or Allied soldiers. Along that line, I am guessing that somehow '$player' can be subplanted with 'allied' or some identifier like that in script lingo....which I'm slowly coming to understand by reading all this great stuff!

By the way, how'd you all get that Stuka going Jimmy?? Have a script to post for that?

Many Thanks and Kudos!
Post Reply