I love the smell of UnrealEd crashing in the morning. – tarquin

Legacy:Moofed

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search

Moofed[edit]

I'm a newer member of the Unreal modding community. I've been a long time fan of the Unreal games (I had an Unreal hat at one time, but it has long since been lost), but only recently have had the time and skills to look at any unrealscript.

Carjack[edit]

Released! The results of the Carjack project, including a download of the mod, are available from http://spock.informatics.indiana.edu/~carjack

The performance in general is not that great because of the large amount of physics calculations and AI driver code from about 40 vehicles. Not recommended for Internet play. It would have been unplayable FPS-wise had we used an over-the-shoulder camera due to rendering an entire city's worth of static meshes. The top-down viewpoint avoided that problem nicely. But, it is fun with a couple friends on a LAN. Enjoy!


Carjack is a mod I am working on to complete the capstone project for my Informatics degree from Indiana University. It is an attempt to clone the multiplayer gameplay from Grand Theft Auto 2, while making use of the modern amenities found in UnrealEngine2. My reason for this project is GTA2 has always been a blast to play at LAN parties, but it has certain limitations (such as using DirectPlay 6.1 for its netcode and being limited to 6 players) that make having fun playing it more difficult.

A video showcasing the progress of the project as of mid-Feburary 2006 is available:

https://www.slashtmp.iu.edu/public/download.php?FILE=dlpierce/94788r7kgDF

Yes, I do know that Mod_Ideas/CarJack has the same name, but I didn't see that page until we had already started work. Plus "Carjack" is only a working title for now, it may change.

Civilians[edit]

Part of what makes GTA2 so neat is there are hordes of civilians wondering the streets that pose no threat to the player. I anticipate this feature to be one of the more difficult in developing the mod, and is why I am writing about it here. What I want to make happen is

  • Have civilian vehicles driving on city streets
    • These drivers should stop when something is in front of them, and when they come to a (red) traffic light.
    • They must drive on the streets, but will become spooked by gunshots and then drive erratically/aggressively or get out of the vehicle and run for their lives (effectively becoming a spooked pedestrian, see below).
    • A predetermined number of civilian vehicles will exist in the game at any one time. When one is destroyed, another is spawned at a random VehicleFactory location. Ideally, this will not be visible to the players. I am imagining a garage with doors that open up and the new civilian drives out. Only spawned civilians would be allowed out, no one allowed in.
  • Have civilian pedestrians wandering the sidewalks.
    • Pedestrians stay on the sidewalks unless spooked, at which point they run away from the player.
    • There is a chance the pedestrian will not be a total pushover and will whip out a pistol and start shooting back.
    • Killed pedestrians have a chance of dropping an item (weapon, health, whatever).

To do all this I think I will need three seperate bot paths, two for vehicles (one for each side of the road) and one for pedestrians, plus some extra pathnodes only available to bots (if I got that far) and spooked NPCs. Spooked NPCs would also have the vehicle pathnodes at their disposal. Functioning stop lights are also necessary to make a believable traffic simulation, but obviously add much more complexity to the problem.

Update: After much experimentation, I have decided that the NavigationPoint system is not suitable for what I want to do. The autoconnecting behavior ruins any attempt to make seperate paths from nodes in close proximity (such as the two lanes of a road).

Instead I have made a custom network of Actor nodes that each have an array of nodes that the vehicle can go to next (randomly selected). This has the advantage of allowing the mapper to precisely define the map's traffic behavior, and the disadvantages of not being automated like NavigationPoints are, and not having any lines displayed in UnrealEd. I can display the network inside the game using HUD.Draw3DLine, but UnrealEd has no HUDs as far as I can tell (or any way to change anything actually). I am thinking of making using a similar node network for civilian pedestrians, leaving the NavigationPoint network free to be dedicated to bots.

At first I was using MoveToward to make my vehicles move, but this again was insufficient. MoveToward dis not control the steering acurately enough to stay on the correct side of the road, instead the drivers would drunkenly drift over the centerline or onto the sidewalks. MoveToward also has no interface to control the vehicle's throttle, giving the all civilians a severe case of lead foot. This is my current driver controller:

</span><div class="hidden">class CarjackDriver extends CarjackNPC;
 
var int NumRandomJumps;
var Actor RandDest;
var Actor TempPoint;
var CarjackRoadNode DestRoadNode;
var float DriverThrottle, DriverSteering; //Sets respective vehicle variables via Tick in the vehicle's code
 
function CarjackRoadNode FindRandomRoadNode()
{
	local array<CarjackRoadNode> NodeList;
	local CarjackRoadNode Node;
	local int i;
 
	foreach AllActors(class'CarjackRoadNode', Node)
	{
		NodeList[i] = Node;
		i++;
	}
	return NodeList[Rand(NodeList.Length)];
}
 
function CarjackRoadNode FindNearestRoadNode()
{
	local CarjackRoadNode Node, ClosestNode;
	local float Dist, ClosestDist;
 
	ClosestDist = 100000.0;
 
	foreach AllActors(class'CarjackRoadNode', Node)
	{
		Dist = VSize(Node.Location - Pawn.Location);
		if (Dist < ClosestDist)
		{
			ClosestNode = Node;
			ClosestDist = Dist;
		}
	}
	return ClosestNode;
}
 
function CarjackRoadNode FindNextRoadNode(CarjackRoadNode CurrentNode)
{
	return CurrentNode.GetNextNode();
}
 
//Check for Pawns in the way.
function bool CheckObstruction()
{
	local vector HitLocation, HitNormal, ExtentSize;
 
	ExtentSize.X = CarjackVehicle(Pawn).VehicleWidth;
	ExtentSize.Y = CarjackVehicle(Pawn).VehicleWidth;
 
	if (Pawn(Trace(HitLocation, HitNormal, (vector(Pawn.Rotation) * 250) + Pawn.Location, Pawn.Location, true, ExtentSize)) != None)
	{
		return true;
	}
	return false;
}
 
auto state Driving
{
	function SetThrottle()
	{
		local Vehicle V;
 
		V = Vehicle(Pawn);
 
		if (VSize(V.Velocity) > DestRoadNode.SpeedLimit)
		{
			DriverThrottle = 0.25;
		}
		else
		{
			DriverThrottle = 0.90;
		}
	}
 
	function SetSteering()
	{
		local float RadiansDelta, RightOrLeft, ForwardOrBackward;
		local Vehicle V;
 
		V = Vehicle(Pawn);
 
		RadiansDelta = Acos(Normal(vector(V.Rotation)) dot Normal(DestRoadNode.Location - V.Location));
		RightOrLeft = ((vector(V.Rotation)) cross vect(0,0,1)) dot Normal(DestRoadNode.Location - V.Location);
		ForwardOrBackward = vector(V.Rotation) dot Normal(DestRoadNode.Location - V.Location);
 
		if (RightOrLeft < 0.0) // Turn Left
		{
			DriverSteering = FClamp(RadiansDelta, 0.0, 1.0) * -1;
		}
		else if (RightOrLeft > 0.0) // Turn Right
		{
			DriverSteering = FClamp(RadiansDelta, 0.0, 1.0);
		}
		else
		{
			DriverSteering = 0.0;
		}
	}
 
Begin:
	if (DestRoadNode == None)
	{
		DestRoadNode = FindNearestRoadNode();
	}
 
	if (CheckObstruction())
	{
		GoToState('Obstructed');
	}
 
	if (VSize(DestRoadNode.Location - Pawn.Location) < 200)
	{
		if (DestRoadNode.bStopTraffic)
		{
			GotoState('Stopped');
		}
		else
		{
			DestRoadNode = FindNextRoadNode(DestRoadNode);
		}
	}
 
	SetThrottle();
	SetSteering();
 
	Sleep(0.2);
	Goto('Begin');
}
 
state Stopped
{
	function SetThrottle()
	{
		DriverThrottle = 0;
	}
 
Begin:
	SetThrottle();
	if (!DestRoadNode.bStopTraffic)
	{
		GotoState('Driving');
	}
	Sleep(0.5);
	Goto('Begin');
}
 
state Obstructed
{
	function SetThrottle()
	{
		DriverThrottle = 0;
	}
 
Begin:
	SetThrottle();
	if (!CheckObstruction())
	{
		GotoState('Driving');
	}
	Sleep(0.5);
	Goto('Begin');
}

Thoughts please.

Discussion[edit]

Wormbo: Hi and welcome to the Wiki. :)

Jimboh: Hmm...civilians are surprisingly easy. All you have to do is create a pawn...then create an AIController without the monster states - add the model, and PRESTO! Instant Civilian! Of course then you'd have to create some botpaths for your civvies. I remember in Tanus' Syndicate 2003 MOD he had a tutorial on NPC's...the site is down, so if anyone has the tutorial saved, it would be most helpful...

Sweavo: Hi there, I posted that Mod Ideas/Civilians page. I'm interested in following progress and assisting in this mod. I'm thinking off-map factories too. See DM-Autoroute2 for a map that would really benefit from civilians. I anticipate the hardest part of this is realistic AI, combining the "milling about" behaviour with the "spooked" to make the civilians look like they have a back-story, . Once that bit's done, the most work would likely be coming up with meshes and textures for the pawns and vehicles. I have no clue when it comes to modelling. Maybe the unwheel project has spare vehicles that can be adapted.

SuperApe: Hi, Moofed. (Welcome :)) What Jimboh is saying is true. It can be easy, but I agree with Sweavo too, in that you'd probably want a different kind of AI. And I think different models, animations and skins are a good idea too. (animations without weapon-holding for example) I suggest, because most of what makes up a Bot and xPawn are geared for combat, borrow what you can from them (perhaps use them for testing purposes too) and then begin to implement your own custom stuff. You and Sweavo should take a look at the Maya PLE Character Model Tutorial, it should not be too hard to implement a custom civilian model and animation. And, check out NPC Support for ideas. Can't wait to see what you guys come up with. It sounds neat. :)

Moofed: Thanks for the warm welcome everyone! :cheesy: I should mention that there are two other people working on the mod, one who is concentrating on building a cityscape map, the other is a modeler and is making a first set of real world vehicles to play with, not to mention some staticmeshes for the map. I'm already using some of the skidmark code from UnWheel (with permission of course), so I might see about including some of their vehicles as well. They've been a great help for resolving scaling issues already. I'll try to get a basic pedestrian working tonight.

Tarquin: Hi, welcome. Interesting project!

Moofed: I thought this would be a simple task, but the FindRandomDest() function insists upon returning nothing but None. If I extend from MonsterController the function works, but as already stated. we want to extend from Controller. Help?

SuperApe: Sorry, FindRandomDest() is an EMPTY function. It's actually used in a few places, but it's completely useless in stock Controller classes. It must have been defined for subclass use. But, no big deal. Finding a random destination isn't much harder than picking a NavigationPoint that isn't taken.

function NavigationPoint FindRandomDest()
{
     local NavigationPoint N;
     local array<NavigationPoint> NP;
     local int i;
 
     NP.Insert(i,1);
     forEach AllActors( class'NavigationPoint', N )
          if ( !N.taken )
          {
               NP[i] = N;
               i++;
               NP.Insert(i,1);
          }
     return NP[ FRand() * i ];
}

Re-define as necessary. :) Moofed: Thanks! I saw

native(525) final function NavigationPoint FindRandomDest();

so I thought it couldn't be overridden and the source would not be available. Maybe it is overridden in yet more native code...

SuperApe: Well, whether there is some code to it now or not, I suppose you might as well try to override it for your custom purposes in the Pedestrian/Civilian controller. If you can't override it, perhaps you can use this code anyway in a similar function.

Draconx: This is what I use in my mod for original UT... assuming it still works (Why wouldn't it...) it is much more efficient than the above foreach AllActors method.

for (N = Level.NavigationPointList; N != None; N = N.NextNavigationPoint)

SuperApe: That's great! :) I can use that too. Thanks.