Legacy:KShip

From Unreal Wiki, The Unreal Engine Documentation Site
Revision as of 20:41, 16 April 2010 by LiKeMiKeS (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Well this is basically my code for a space ship, thanks a lot to Daid for lending me his replication code (which turned out to come from KCar but i thank him non the less, great guy he is :D)

I currently use a different, more client oriented replication system, but this one here is a lot better, i havent incorporated my ship to it yet because i have some other problems that come with it that i have to solve, but since the "core" ship here is simple, ill use the better replication for you guys :)

(Btw i deal with all the entering/leaving of the vehicle in a parent class, this is really irrelevant to physics and is easy to do, so i left it out just so there will be less and easier to read code)

<uscript> var float Roll, CThrust, TempThrust, OldThrust; // Throttle and Steering are already declared in KVehicle, so all we need is roll, CThrust, TempThrust, OldThrust will be explained soon // BTW note that i use Throttle for Pitch alteration because it is already bound by other vehicles to the forward/backward key // ok i have also incorporated a system that allows for various thrust managments, //if you simply want to move forward full speed only while you press the the thrust button, you would use TempThrust. //when you release the thrust button you though you should always set TempThrust to -1 // if you want to have a constant speed, assign it to CThrust, so every time you release the thrust button (the one that changes TempThrust) // you would automatically start going at that speed (good for stuff like dogifghting and matching speeds) // and lastly i added an afterburner effect, ill include it here for you guys to see although it isnt hard to do. // also what i did with it was that when you afterburn and you run out of energy, while you still hold the afterburn key // you would keep going at your max possible speed, and once you release it you would start going at your constant wanted speed (CThrust) // Thats why i have 2 vars, bAfterburn is for after burning (holding key and having enough E), bBurn is for only holding the afterburn key with no regard to its depletion var bool bAfterburn, bBurn; // note that you should set both of those to true when you want to afterburn var() float ForwardTrust, TurnRate, AfterBurnThrust; // This is basically how fast our ship turns/moves var float CurRoll, CurSteering, CurThrottle, UnitAccRate; // This is used for acceleration // CThrust is used for ships that can assign a specific throttle value, like 75% of max speed or whatever... // UnitAccRate is how much each value increases per second var vector ExtraForce, ExtraTorque; // Used for Karama forces pileup

// Ship replication vars and functions, thanks daid! struct StructShipState { var KRBVec ChassisPosition; var Quat ChassisQuaternion; var KRBVec ChassisLinVel; var KRBVec ChassisAngVel;

var float ServerSteering; var float ServerThrottle; var float ServerRoll;

var bool ServerbAfterburn; var bool ServerbBurn;

var bool bNewState; // Set to true whenever a new state is received and should be processed };

var KRigidBodyState ChassisState;

var StructShipState ShipState; // This is replicated to the ship, and processed to update all the parts. var bool bNewShipState; // Indicated there is new data processed, and chassis RBState should be updated.

var float NextNetUpdateTime; // Next time we should force an update of vehicles state. var() float MaxNetUpdateInterval;

var int AVar;//Just for replication, else the ShipState doesn't get replicated

Replication { unreliable if(Role == ROLE_Authority) ShipState, AVar; }

simulated event VehicleStateReceived() { if(!ShipState.bNewState) return;

// Get root chassis info ChassisState.Position = ShipState.ChassisPosition; ChassisState.Quaternion = ShipState.ChassisQuaternion; ChassisState.LinVel = ShipState.ChassisLinVel; ChassisState.AngVel = ShipState.ChassisAngVel;

// Update control inputs Steering = ShipState.ServerSteering; Throttle = ShipState.ServerThrottle; Roll = ShipState.ServerRoll;

// Afterburner bAfterburn = ShipState.ServerbAfterburn; bBurn = ShipState.ServerbBurn;

// Update flags ShipState.bNewState = false; bNewShipState = true; }

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

// Apply received data as new position of ship chassis. newState = ChassisState; bNewShipState = false;

return true; }

function PackState() { local vector chassisPos, chassisLinVel, chassisAngVel; local vector oldPos, oldLinVel; local KRigidBodyState ChassisState;

// Get chassis state. KGetRigidBodyState(ChassisState);

chassisPos = KRBVecToVector(ChassisState.Position); chassisLinVel = KRBVecToVector(ChassisState.LinVel); chassisAngVel = KRBVecToVector(ChassisState.AngVel);

// Last position we sent oldPos = KRBVectoVector(ShipState.ChassisPosition); oldLinVel = KRBVectoVector(ShipState.ChassisLinVel);

// See if state has changed enough, or enough time has passed, that we // should send out another update by updating the state struct. if( !KIsAwake() ) { return; // Never send updates if physics is at rest }

if( VSize(oldPos - chassisPos) > 5 || VSize(oldLinVel - chassisLinVel) > 1 || Abs(ShipState.ServerThrottle - Throttle) > 0.1 || Abs(ShipState.ServerSteering - Steering) > 0.1 || Abs(ShipState.ServerRoll - Roll) > 0.1 || bAfterburn != ShipState.ServerbAfterburn || bBurn != ShipState.ServerbBurn || Level.TimeSeconds > NextNetUpdateTime ) { NextNetUpdateTime = Level.TimeSeconds + MaxNetUpdateInterval; } else { return; }

ShipState.ChassisPosition = ChassisState.Position; ShipState.ChassisQuaternion = ChassisState.Quaternion; ShipState.ChassisLinVel = ChassisState.LinVel; ShipState.ChassisAngVel = ChassisState.AngVel;

// Player Input ShipState.ServerSteering = Steering; ShipState.ServerThrottle = Throttle; ShipState.ServerRoll = Roll;

// AfterBurner ShipState.ServerbAfterburn = bAfterburn; ShipState.ServerbBurn = bBurn;

// This flag lets the client know this data is new. ShipState.bNewState = true; //Make sure ShipState gets replicated AVar++; if (AVar > 10) AVar=0; }

simulated function Tick(float DeltaTime) { Super.Tick(DeltaTime); if(!KIsAwake() && Controller!=None) KWake(); if(Role == ROLE_Authority && Level.NetMode != NM_StandAlone) PackState(); UpdateAcceleration(DeltaTime); UpdateExtraForce(DeltaTime); } simulated function UpdateAcceleration(float Delta) { CurSteering = CurSteering + Steering * UnitAccRate * Delta; CurThrottle = CurThrottle + Throttle * UnitAccRate * Delta; CurRoll = CurRoll + Roll * UnitAccRate * Delta; if(Steering==0) CurSteering=0; if(Throttle==0) CurThrottle=0; if(Roll==0) CurRoll=0;

if(Abs(CurSteering)>Abs(Steering)) CurSteering=Steering; if(Abs(CurThrottle)>Abs(Throttle)) CurThrottle=Throttle; if(Abs(CurRoll)>Abs(Roll)) CurRoll=Roll;

if(bAfterBurn) { ReduceAfterBurnEnergy(); // just made this up, put it here incase you have something like this if(GetAfterburnEnergy()<=0) // Another fictional function... { bAfterBurn=False; } else { CThrust=AfterBurnThrust; } } if(bBurn && !bAfterBurn && CThrust!=1) { CThrust=1; } else if(!bBurn && !bAfterBurn && CThrust!=OldThrust) { CThrust=OldThrust; }

if(TempThrust!=-1 && !bAfterBurn) { if(Abs(CurThrust-TempThrust)<0.01) CurThrust=TempThrust; if(CurThrust>TempThrust) CurThrust = CurThrust - UnitAccRate * Delta / 4; // I made linear acceleration 4 times slower than rotation, you can do whatever you want though else if(CurThrust<TempThrust) CurThrust = CurThrust + UnitAccRate * Delta / 4; } else if(CurThrust!=CThrust && !bAfterBurn) { if(Abs(CurThrust-CThrust)<0.01) CurThrust=CThrust; else if(CurThrust>CThrust) CurThrust = CurThrust - UnitAccRate * Delta / 4; else if(CurThrust<CThrust) CurThrust = CurThrust + UnitAccRate * Delta / 4; } else if(CurThrust!=CThrust && bAfterBurn) { if(Abs(CurThrust-CThrust)<0.01) CurThrust=CThrust; else if(CurThrust>CThrust) CurThrust = CurThrust - UnitAccRate * Delta / 2.2; // Acceleration with afterburner a lot faster else if(CurThrust<CThrust) CurThrust = CurThrust + UnitAccRate * Delta / 2.2; } }

simulated function UpdateExtraForce(float Delta) { local vector worldForward, worldDown, worldLeft;

worldForward = vect(1, 0, 0) >> Rotation; worldDown = vect(0, 0, -1) >> Rotation; worldLeft = vect(0, -1, 0) >> Rotation;

ExtraForce = ExtraForce + worldForward * ForwardThrust * Delta * CurThrust; // Speed ExtraTorque = ExtraTorque + worldDown * TurnRate * Delta * CurSteering; // Yaw ExtraTorque = ExtraTorque + worldLeft * TurnRate * Delta * CurThrottle; // Pitch ExtraTorque = ExtraTorque + worldForward * TurnRate * Delta * -CurRoll; // Roll }

simulated event KApplyForce(out vector Force, out vector Torque) { // This actually does the applying of the piled up force Force = ExtraForce; Torque = ExtraTorque; ExtraForce = vect(0,0,0); ExtraTorque = vect(0,0,0); }

DefaultProperties {

    // Create Karma collision Params for ourselves, you can change whatever you want here
    Begin Object Class=KarmaParamsRBFull Name=KParams0
        KLinearDamping=2.000;
        KAngularDamping=2.000;
        KStartEnabled=True
        bHighDetailOnly=False
        bClientOnly=False
        bKDoubleTickRate=False
        KFriction=1.600000
        KActorGravScale = 0.0;

KMass=2;

        Name="KParams0"
    End Object
    KParams=KarmaParamsRBFull'<MyPackage>.<MyShipClass>.KParams0'
    // And just some other variables:
    TurnRate=8
    ForwardThrust=5000
    UnitAccRate=2.0
    AfterBurnThrust=1.20 // basically means that afterburner goes at 120% of regular maximum speed

} </uscript>

and that should be it, i hope i didnt miss anything...

Spark: KParams=KarmaParamsRBFull'<MyPackage>.<MyShipClass>.KParams0' <– Is this supposed to be a trap? ;) Took me a while to figure out that my ship didn't fly because this wasn't set to KParams0 and thus wasn't enabled at all. :)

Sir_Brizz: Zep, did you end up getting your Quaternion working for the indicator? I have a few ideas that work if you want to know what they are.

ProjectX: I'm a n00b to coding, but is it possible to take this code, and change it to create a "hovering vehicles" class, that basicly, wont go a certan height above ground, but, from high jumps, etc., go lower to the ground? I also saw that there was 3 types of thrust, is it possible to bind a key that will cycle through the flying types (for more precise flying, eg. for dog matches and realism)?

NickR: Does anyone have a working example of a flying vehicle?

Foxpaw: I do, but my mod is still quite a ways from release. The code above allegedly is working code for a flying vehicle, though I've never tested it.

LiKeMiKeS: I've tried many times compiling this KShip script and have ended up with an error for the ShipState 'struct' & 'var' references obscuring each other and haven't been able to figure out a clean fix so it will compile - without creating another unneeded var instance or reference. I'm still learning the nuances of uscript, so it's difficult to debug atm.