Coding this UnrealED imported mech

  • Two Factor Authentication is now available on BeyondUnreal Forums. To configure it, visit your Profile and look for the "Two Step Verification" option on the left side. We can send codes via email (may be slower) or you can set up any TOTP Authenticator app on your phone (Authy, Google Authenticator, etc) to deliver codes. It is highly recommended that you configure this to keep your account safe.

CIpen

New Member
May 12, 2004
53
0
0
43
OKay! The mech I've been working on has gotten out of the lab and into UnrealED. You can get the zip of the mesh and animation at the bottom of this post.

Now, all that really needs to be done (besides a reduction on the mech's polys/more animations) is the coding. Other than the programming classes that I've had I really haven't done much as far as programming goes. But this scripting for Unreal looks very very simple. Nothing like manually creating lists with pointers in C++. It seems as if someone needs to decide what is needed and what isn't needed to build just about anything in unreal. But bare with me, I'm just going on what I see here in the code...

Thoughts so far on the Mech class:
Will subclass (not directly) from Vehicle
Most likely will end up useing this for the walking, I've found this in ONSMineProjectile.uc and in ONSMobileAssaultStation.uc - if (Physics != PHYS_Walking){}

Thoughts? Ideas?
I'm sorta a noob programmer but owell ;)
 

Attachments

  • Mech_Feet.zip
    406.1 KB · Views: 35

Mr Evi1

New Member
Mar 22, 2002
336
0
0
UK
come.to
This code might be useful to you. I've used it, and variations of it to make vehicles with two, four andsix legs so far :)
Code:
//=============================================================================
// WoEWalkerCraft - Vehicle with multiple legs. Based on ONSHoverCraft code.
// [url]http://come.to/MrEvil[/url]
//=============================================================================
class WoEWalkerCraft extends ONSVehicle
	abstract;

var()	array<vector>			ThrusterOffsets;
var()	float				HoverSoftness;
var()	float				HoverPenScale;
var()	float				HoverCheckDist;

var()	float				UprightStiffness;
var()	float				UprightDamping;

var()	float				MaxThrustForce;
var()	float				LongDamping;

var()	float				MaxStrafeForce;
var()	float				LatDamping;

var()	float				MaxRiseForce;
var()	float				UpDamping;

var()	float				TurnTorqueFactor;
var()	float				TurnTorqueMax;
var()	float				MaxYawRate;

var()	float				LegCheckDist;

// Internal
var	float				TargetHeading;
var	float				TargetPitch;
var     bool				bHeadingInitialized;

var	float				OutputThrust;
var	float				OutputStrafe;

var	Pawn				OldDriver;

// Replicated
struct native HoverCraftState
{
	var vector			ChassisPosition;
	var Quat			ChassisQuaternion;
	var vector			ChassisLinVel;
	var vector			ChassisAngVel;

	var byte			ServerThrust;
	var byte			ServerStrafe;
	var int				ServerViewPitch;
	var int				ServerViewYaw;
};

var		HoverCraftState		HoverState, OldHoverState;
var		KRigidBodyState		ChassisState;
var		bool			bNewHoverState;

var	vector				WForce, WTorque;

var byte FudgeByte; //It seems that structs won't replicate properly on their own, so replicate this too.

replication
{
	reliable if(Role == ROLE_Authority)
		HoverState, FudgeByte;
}

simulated event bool KUpdateState(out KRigidBodyState newState)
{
	// This should never get called on the server - but just in case!
	if(Role == ROLE_Authority || !bNewHoverState)
		return false;

	newState = ChassisState;
	bNewHoverState = false;

	return true;
}

simulated function PostNetBeginPlay()
{
	local vector RotX, RotY, RotZ;
	local KarmaParams kp;
	local KRepulsor rep;
	local int i;

	GetAxes(Rotation,RotX,RotY,RotZ);

	// Spawn and assign 'repulsors' to hold bike off the ground
	kp = KarmaParams(KParams);
	kp.Repulsors.Length = ThrusterOffsets.Length;

	for(i=0;i<ThrusterOffsets.Length;i++)
	{
		rep = spawn(class'KRepulsor', self,, Location + ThrusterOffsets[i].X * RotX + ThrusterOffsets[i].Y * RotY + ThrusterOffsets[i].Z * RotZ);
		rep.SetBase(self);
		rep.bHidden = true;
		kp.Repulsors[i] = rep;
	}

	Super.PostNetBeginPlay();
}

function Died(Controller Killer, class<DamageType> damageType, vector HitLocation)
{
	local KarmaParams kp;
	local int i;

	//Destroy repulsors
	kp = KarmaParams(KParams);
	for(i=0;i<kp.Repulsors.Length;i++)
		kp.Repulsors[i].Destroy();

	kp.Repulsors.Length = 0;

	Super.Died(Killer, damageType, HitLocation);
}

simulated event SVehicleUpdateParams()
{
	local KarmaParams kp;
	local int i;

	Super.SVehicleUpdateParams();

	kp = KarmaParams(KParams);

	for(i=0;i<kp.Repulsors.Length;i++)
	{
		kp.Repulsors[i].CheckDist = HoverCheckDist;
		kp.Repulsors[i].PenScale = HoverPenScale;
		kp.Repulsors[i].Softness = HoverSoftness;
	}

	KSetStayUprightParams(UprightStiffness, UprightDamping);
}

simulated function SpecialCalcFirstPersonView(PlayerController PC, out actor ViewActor, out vector CameraLocation, out rotator CameraRotation )
{
	ViewActor = self;

	CameraLocation = Location + (FPCamPos >> Rotation);
}

//Returns true if one or more legs is close enough to the ground to be considered able to walk.
simulated function bool IsOnGround()
{
	local int i;
	local vector StartTrace, EndTrace;
	local KarmaParams KP;

	//Do some quick traces first, down from the thruster locations towards the ground.
	for(i = 0; i < ThrusterOffsets.Length; i++)
	{
		StartTrace = Location;
		StartTrace += ThrusterOffsets[i] >> Rotation;

		EndTrace = StartTrace;
		EndTrace += (vect(0, 0, -1) >> Rotation) * HoverCheckDist * LegCheckDist;

		if(!FastTrace(EndTrace, StartTrace))
			return true;
	}

	//If the traces fail, see if the thrusters are actually in contact.
	//TODO: Shouldn't this check be done before the traces? Which order would be faster?
	KP = KarmaParams(KParams);

	for(i = 0; i < KP.Repulsors.Length; i++)
	{
		if(KP.Repulsors[i].bRepulsorInContact)
			return true;
	}

	return false;
}

//From here on is the stuff that was in ONSHoverCraft.cpp

function float HeadingAngle(Vector dir)
{
	local float angle;

	angle = Acos(dir.X);

	if(dir.Y < 0.0)
		angle *= -1.0;

	return angle;
}

function float FindDeltaAngle(float a1, float a2)
{
	local float delta;

	delta = a2 - a1;

	if(delta > PI)
		delta = delta - (PI * 2.0);
	else if(delta < -PI)
		delta = delta + (PI * 2.0);

	return delta;
}

function float UnwindHeading(float a)
{
	while(a > PI)
		a -= (PI * 2.0);

	while(a < -PI)
		a += (PI * 2.0);

	return a;
}

//Calculate forces for thrust/turning etc. and apply them.
//TODO: Tidy this up (reduce number of variables etc).
simulated function UpdateVehicle(float DeltaTime)
{
	local KarmaParams KP;
	local vector DirX, DirY, DirZ;
	local Vector Forward, Right, Up;
	local KRigidBodyState rbState;
	local vector AngVel;
	local float TurnAngVel, RollAngVel, PitchAngVel;
	local float ForwardVelMag, RightVelMag;
	local vector Force, Torque;
	local rotator LookRot;
	local vector LookDir;
	local vector PlaneLookDir;
	local float CurrentHeading, DesiredHeading;
	local float DeltaTargetHeading, MaxDeltaHeading;
	local float DeltaHeading, TurnTorqueMag;

	// Dont go adding forces if vehicle is asleep.
	if(!KIsAwake())
		return;

	KP = KarmaParams(KParams);

	if(KP == None)
		return;

	WForce = vect(0, 0, 0);
	WTorque = vect(0, 0, 0);

	if(Controller != None)
	{
		//Calc up (z), right(y) and forward (x) vectors
		GetAxes(Rotation, DirX, DirY, DirZ);

		if(!IsOnGround())
			return;

		Forward = DirX;
		Right = DirY;
		Up = DirZ;

		// Get body angular velocity
		KGetRigidBodyState(rbState);
		AngVel = KRBVecToVector(rbState.AngVel);
		TurnAngVel = AngVel dot Up;
		RollAngVel = AngVel dot DirX;
		PitchAngVel = AngVel dot DirY;

		ForwardVelMag = Velocity dot Forward;
		RightVelMag = Velocity dot Right;

		// Thrust
		Force += (OutputThrust * MaxThrustForce * Forward);

		Force -= ( (1.0 - Abs(OutputThrust)) * LongDamping * ForwardVelMag * Forward);

		// Strafe
		Force += (-OutputStrafe * MaxStrafeForce * Right);

		Force -= ( (1.0 - Abs(OutputStrafe)) * LatDamping * RightVelMag * Right);

		LookRot.Pitch = DriverViewPitch;
		LookRot.Yaw = DriverViewYaw;
		LookDir = vector(LookRot);

		// We try to turn the HoverCraft to match the way the camera is facing.

		//// YAW ////

		// Project Look dir into z-plane
		PlaneLookDir = LookDir;
		PlaneLookDir.Z = 0.0;
		PlaneLookDir = Normal(PlaneLookDir);

		Forward.Z = 0.0;
		Forward = Normal(Forward);

		CurrentHeading = HeadingAngle(Forward);
		DesiredHeading = HeadingAngle(PlaneLookDir);

		if(!bHeadingInitialized)
		{
			TargetHeading = CurrentHeading;
			bHeadingInitialized = true;
		}

		// Move 'target heading' towards 'desired heading' as fast as MaxYawRate allows.
		DeltaTargetHeading = FindDeltaAngle(TargetHeading, DesiredHeading);
		MaxDeltaHeading = DeltaTime * MaxYawRate;
		DeltaTargetHeading = FClamp(DeltaTargetHeading, -MaxDeltaHeading, MaxDeltaHeading);
		TargetHeading = UnwindHeading(TargetHeading + DeltaTargetHeading);
		
		// Then put a 'spring' on the copter to target heading.
		DeltaHeading = FindDeltaAngle(CurrentHeading, TargetHeading);
		TurnTorqueMag = (DeltaHeading / PI) * TurnTorqueFactor;
		TurnTorqueMag = FClamp(TurnTorqueMag, -TurnTorqueMax, TurnTorqueMax);
		Torque += (TurnTorqueMag * Up);

		// Apply force/torque to body.
		WForce = Force;
		WTorque = Torque;
	}
}

simulated function KApplyForce(out vector Force, out vector Torque)
{
	Super.KApplyForce(Force, Torque);

	Force += WForce;
	Torque += WTorque;
}

simulated function Tick(float DeltaTime)
{
	Super.Tick(DeltaTime);

	// If the server, process input and pack updated car info into struct.
	if(Role == ROLE_Authority)
	{
		if(bDriving)
		{
			OutputThrust = Throttle;
			OutputStrafe = Steering;

			KWake(); // keep vehicle alive while driving
		}

		PackState();
	}
}

function PackState()
{
	local KRigidBodyState RBState;
	local rotator ViewRot;

	if(!KIsAwake())
		return;

	KGetRigidBodyState(RBState);

	HoverState.ChassisPosition.X = RBState.Position.X;
	HoverState.ChassisPosition.Y = RBState.Position.Y;
	HoverState.ChassisPosition.Z = RBState.Position.Z;

	HoverState.ChassisQuaternion = RBState.Quaternion;

	HoverState.ChassisLinVel.X = 10.0 * RBState.LinVel.X;
	HoverState.ChassisLinVel.Y = 10.0 * RBState.LinVel.Y;
	HoverState.ChassisLinVel.Z = 10.0 * RBState.LinVel.Z;

	HoverState.ChassisAngVel.X = 1000.0 * RBState.AngVel.X;
	HoverState.ChassisAngVel.Y = 1000.0 * RBState.AngVel.Y;
	HoverState.ChassisAngVel.Z = 1000.0 * RBState.AngVel.Z;

	HoverState.ServerThrust = FloatToRangeByte(OutputThrust);
	HoverState.ServerStrafe = FloatToRangeByte(OutputStrafe);

	if(Controller != None)
	{
		if(IsHumanControlled())
		{			
			DriverViewPitch = Controller.Rotation.Pitch;
			DriverViewYaw = Controller.Rotation.Yaw;
		}
		else
		{
			ViewRot = rotator(Controller.FocalPoint - Location);
			DriverViewPitch = ViewRot.Pitch;
			DriverViewYaw = ViewRot.Yaw;
		}
	}
	else
	{
		DriverViewPitch = Rotation.Pitch;
		DriverViewYaw = Rotation.Yaw;
	}

	HoverState.ServerViewPitch = DriverViewPitch;
	HoverState.ServerViewYaw = DriverViewYaw;

	FudgeByte++;
}

// Deal with new infotmation about the arriving from the server
simulated function PostNetReceive()
{
	Super.PostNetReceive();

	if (Driver != OldDriver)
	{
		SVehicleUpdateParams();
		OldDriver = Driver;
	}

	if( OldHoverState.ChassisPosition == HoverState.ChassisPosition &&
		OldHoverState.ChassisQuaternion.X == HoverState.ChassisQuaternion.X &&
		OldHoverState.ChassisQuaternion.Y == HoverState.ChassisQuaternion.Y &&
		OldHoverState.ChassisQuaternion.Z == HoverState.ChassisQuaternion.Z &&
		OldHoverState.ChassisQuaternion.W == HoverState.ChassisQuaternion.W &&
		OldHoverState.ChassisLinVel == HoverState.ChassisLinVel &&
		OldHoverState.ChassisAngVel == HoverState.ChassisAngVel &&
		OldHoverState.ServerThrust == HoverState.ServerThrust &&
		OldHoverState.ServerStrafe == HoverState.ServerStrafe &&
		OldHoverState.ServerViewPitch == HoverState.ServerViewPitch &&
		OldHoverState.ServerViewYaw == HoverState.ServerViewYaw )
		return;

	ChassisState.Position.X = HoverState.ChassisPosition.X;
	ChassisState.Position.Y = HoverState.ChassisPosition.Y;
	ChassisState.Position.Z = HoverState.ChassisPosition.Z;

	ChassisState.Quaternion = HoverState.ChassisQuaternion;

	ChassisState.LinVel.X = 0.1f * HoverState.ChassisLinVel.X;
	ChassisState.LinVel.Y = 0.1f * HoverState.ChassisLinVel.Y;
	ChassisState.LinVel.Z = 0.1f * HoverState.ChassisLinVel.Z;

	ChassisState.AngVel.X = 0.001f * HoverState.ChassisAngVel.X;
	ChassisState.AngVel.Y = 0.001f * HoverState.ChassisAngVel.Y;
	ChassisState.AngVel.Z = 0.001f * HoverState.ChassisAngVel.Z;

	bNewHoverState = true;

	// Set OldHoverState to HoverState
	OldHoverState.ChassisPosition = HoverState.ChassisPosition;
	OldHoverState.ChassisQuaternion = HoverState.ChassisQuaternion;
	OldHoverState.ChassisLinVel = HoverState.ChassisLinVel;
	OldHoverState.ChassisAngVel = HoverState.ChassisAngVel;
	OldHoverState.ServerThrust = HoverState.ServerThrust;
	OldHoverState.ServerStrafe = HoverState.ServerStrafe;
	OldHoverState.ServerViewPitch = HoverState.ServerViewPitch;
	OldHoverState.ServerViewYaw = HoverState.ServerViewYaw;

	OutputThrust = RangeByteToFloat(HoverState.ServerThrust);
	OutputStrafe = RangeByteToFloat(HoverState.ServerStrafe);
	DriverViewPitch = HoverState.ServerViewPitch;
	DriverViewYaw = HoverState.ServerViewYaw;
}

//I hope this is correct, it's a guess at what the function used in the native code does.
simulated function byte FloatToRangeByte(float f)
{
	f= FClamp(f, 0, 1);
	f = Round(f * 255);

	return byte(f);
}

//The opposite of the above function.
simulated function float RangeByteToFloat(byte b)
{
	local float f;

	f = b;
	f /= 255;

	return f;
}

defaultproperties
{
	bNetNotify=true

	bZeroPCRotOnEntry=False
	bFollowLookDir=True
	bPCRelativeFPRotation=true
	LegCheckDist=1.5
}
For a bipedal vehicle you might like to attach the KRepulsors to the feet bones instead of having them at a fixed relative location. This makes the vehicle feel more like it's walking.

The parameters for the KRepulsors need a lot of tweaking for each vehicle to make sure it sits at the right height and doesn't sink into the ground too much when walking up slopes.

Note that the lower parts of the legs should be set to not block karma in the animation browser, to avoid constant scraping along the ground.
 

CIpen

New Member
May 12, 2004
53
0
0
43
I'm still wondering about this code for the mineprojectiles:

Code:
    Begin:
        SetPhysics(PHYS_Walking);
        if (bClosedDown)
        {
    		PlayAnim('StartUp');
    		bClosedDown = false;
    		sleep(0.25);
        }

Mr_Evi1 I'm checking your code out now.

Thanks for your input!! :) :eek: :) :crazydance:
 

CIpen

New Member
May 12, 2004
53
0
0
43
NM! I GOT SOMETHING TO AT LEAST COMPILE!! :eek: :D
 
Last edited:

CIpen

New Member
May 12, 2004
53
0
0
43
:eek: :eek: :eek: :lol: :D :boom: :clap: :eek2: :cheers:

LOOKS LIKE CRAP BUT I GOT IT INTO THE GAME!!!
 

Attachments

  • Shot00000.jpg
    Shot00000.jpg
    124.4 KB · Views: 137

CIpen

New Member
May 12, 2004
53
0
0
43
"//From here on is the stuff that was in ONSHoverCraft.cpp"

Maybe I've missed something, but were did you get ONSHoverCraft.cpp?
 

Mr Evi1

New Member
Mar 22, 2002
336
0
0
UK
come.to
CIpen said:
"//From here on is the stuff that was in ONSHoverCraft.cpp"

Maybe I've missed something, but were did you get ONSHoverCraft.cpp?
You can get the Onslaught native code from Psyonix's site. It was also distributed with the 3186 source, but they seem to have forgotten to put it in with the 3204 source.
 

CIpen

New Member
May 12, 2004
53
0
0
43
Okay, it took all day to figure out that my collision was sticking into the ground and not letting the mech to move at all. The good side to it was in looking for an anwser I replaced much of the updatevehicle() with stuff from the ONSTreadcraft.cpp so it would move more like a tank and so I can make the upper part turn.

The next thing will be to find a way to play the walk animation when the mech is moving. I'm thinking it would be best to put the playanim(walk) in the vehicleupdate(). That way it will play when force is being applied.

What do you think?
 

CIpen

New Member
May 12, 2004
53
0
0
43
Code:
simulated function UpdateVehicle(float DeltaTime)
{
	local KarmaParams KP;
	local vector DirX, DirY, DirZ;
	local Vector Forward, Right, Up;
	local KRigidBodyState rbState;
	local vector AngVel;
	local float TurnAngVel, RollAngVel, PitchAngVel;
	local float ForwardVelMag, RightVelMag;
	local vector Force, Torque;
	local float UseForwardDamp, VelMag, UseTurn, UseLatDamp;

	// Dont go adding forces if vehicle is asleep.
	if(!KIsAwake())
		return;

	KP = KarmaParams(KParams);

	if(KP == None)
		return;

	WForce = vect(0, 0, 0);
	WTorque = vect(0, 0, 0);

	if(Controller != None)
	{
		//Calc up (z), right(y) and forward (x) vectors
		GetAxes(Rotation, DirX, DirY, DirZ);

		if(!IsOnGround())
			return;

		Forward = DirX;
		Right = DirY;
		Up = DirZ;

		// Get body angular velocity
		KGetRigidBodyState(rbState);
		AngVel = KRBVecToVector(rbState.AngVel);
		TurnAngVel = AngVel dot Up;
		RollAngVel = AngVel dot DirX;
		PitchAngVel = AngVel dot DirY;

		ForwardVelMag = Velocity dot Forward;
		RightVelMag = Velocity dot Right;

	// Thrust
	Force += (OutputThrust * MaxThrustForce * Forward);

	// Pitching torque
	Torque += (PitchTorqueFactor * OutputThrust * Right);

	// Pitch damping
	VelMag = angVel dot Right;
	Torque += (-1.0f * VelMag * PitchDampFactor * Right);

	// Forward damping
	ForwardVelMag = Velocity dot Forward;
        UseForwardDamp = ForwardDampFactor;
	Force += (-1.0f * ForwardVelMag * UseForwardDamp * Forward);

	// Forward damping from turning
	Force += (-1.0f * Abs(OutputTurn) * ForwardVelMag * TurnDampFactor * Forward);

	// Invert steering when we are going backwards

	if( OutputThrust < InvertSteeringThrottleThreshold )
		UseTurn = -1.0f * OutputTurn;
	else
		UseTurn = OutputTurn;

	// Lateral damping
	VelMag = Velocity dot Right;
	UseLatDamp = LateralDampFactor;
	Force += (-1.0f * VelMag * UseLatDamp * Right);

	// Turn damping
	VelMag = angVel dot Up;
	Torque += (-1.0f * SteerDampFactor * VelMag * Up);

	// Steer Torque
	Torque += (-1.0f * MaxSteerTorque * UseTurn * Up);

	// Banking Torque
	Torque += (BankTorqueFactor * UseTurn * Forward);

	// Bank (roll) Damping

	Torque += (-1.0f * VelMag * BankDampFactor * Forward);


		// Apply force/torque to body.
		WForce = Force;
		WTorque = Torque;
	}
}
 

CIpen

New Member
May 12, 2004
53
0
0
43
Have you attached repulsors to bones? I think I will use KConstraint and not KRepulsors because KConstraint has this:var(KarmaConstraint) name KConstraintBone1;
 

Mr Evi1

New Member
Mar 22, 2002
336
0
0
UK
come.to
I did try attaching repulsors to bones when I was testing that wierd looking mech I posted in your thread on the INA forums. It's easy and it works fine (although I haven't tested it online). It's just a single line of code changed:
Code:
var()	array<name>			ThrusterBones;

simulated function PostNetBeginPlay()
{
	local vector RotX, RotY, RotZ;
	local KarmaParams kp;
	local KRepulsor rep;
	local int i;

	GetAxes(Rotation,RotX,RotY,RotZ);

	// Spawn and assign 'repulsors' to hold bike off the ground
	kp = KarmaParams(KParams);
	kp.Repulsors.Length = ThrusterOffsets.Length;

	for(i=0;i<ThrusterOffsets.Length;i++)
	{
		rep = spawn(class'KRepulsor', self,, Location + ThrusterOffsets[i].X * RotX + ThrusterOffsets[i].Y * RotY + ThrusterOffsets[i].Z * RotZ);
		//rep.SetBase(self);
		AttachToBone(rep, ThrusterBones[i]);
		rep.bHidden = true;
		kp.Repulsors[i] = rep;
	}

	Super.PostNetBeginPlay();
}
 

Mr Evi1

New Member
Mar 22, 2002
336
0
0
UK
come.to
You will probably have to adjust the offsets of the repulsors since they will be a lot lower down when attached to the feet rather than the centre of the vehicle.
 

CIpen

New Member
May 12, 2004
53
0
0
43
Yes, my repulsors are close to the ground, but it's not changing anything. Infact, AttachToBone() isn't doing anything that I can see.

I'm thinking that the repulsors should stay attached to the bones in the animation and stop it from penetration.


5 repulsors for each foot (one for each toe bone)
1 repulsor for the chassis
 

Attachments

  • Shot00013.jpg
    Shot00013.jpg
    300.6 KB · Views: 83
Last edited:

Mr Evi1

New Member
Mar 22, 2002
336
0
0
UK
come.to
Are there any errors in the log? There may be some reason it's failing to attach, such as spaces in the bone names.
 

CIpen

New Member
May 12, 2004
53
0
0
43
Mr_Evi1 said:
Are there any errors in the log? There may be some reason it's failing to attach, such as spaces in the bone names.

Nothing...

Hey, could you set rep.bHidden = false, recompile, go back into the game and take a screenshot with ur mech animated?
 

Mr Evi1

New Member
Mar 22, 2002
336
0
0
UK
come.to
CIpen said:
Nothing...

Hey, could you set rep.bHidden = false, recompile, go back into the game and take a screenshot with ur mech animated?
That's the first thing I tried after seeing your screenshot, except I did it by typing 'set krepulsor bhidden false' at the console ;) They appeared attached to the bones as I expected. Even without seeing that it's obvious that they are attached to the bones by the way the vehicle sways as it animates.
Shot00189.jpg
 

CIpen

New Member
May 12, 2004
53
0
0
43
DOH! ThrusterBones(0)="joint163" not ThrusterBones(0)='joint163'

:man:
 

CIpen

New Member
May 12, 2004
53
0
0
43
Well, I was reading on your site and found out what WoE stood for. It interested me a lot because I have models you could use or would make good base models to build from.

Though it was worth it just to ask :stupid:
 

Attachments

  • examples.jpg
    examples.jpg
    155.4 KB · Views: 89

Mr Evi1

New Member
Mar 22, 2002
336
0
0
UK
come.to
CIpen said:
Well, I was reading on your site and found out what WoE stood for. It interested me a lot because I have models you could use or would make good base models to build from.

Though it was worth it just to ask :stupid:
I'm always on the lookout for good models for various things, it depends what you have. I don't need another car, since I already have one, but there are other vehicles and weapons/pseudo-weapons/pickups that could do with models.