Gah - a solution with more questions. – EntropicLqd
Legacy:VitalOverdose/BoostingVehicleFactory
Contents
- 1 Overview
- 2 function PostBeginPlay()
- 3 function Timer()
- 4 function VocalCountdown()
- 5 Simulated function VecBoost()
- 6 Function VehicleSpawned()
- 7 function Tick(float deltatime)
- 8 function vehicledestroyed(Vehicle V)
- 9 Event VehicleUnPossessed( Vehicle V )
- 10 Event VehiclePossessed( Vehicle V )
- 11 The Completed Script
- 12 RelatedTopics
- 13 Discussion
Overview
the boostingVecicle factory is a modified ASVehicle factory that adds an optional VitalOverdose/VecBooster to every vehicle it spawns. The auto boost is activated (on a timed delay) as soon as a player or bot enters the vehicle as a driver.Theres is a short delay between the driver entering and the actual boost taking place, this is to give the player time to position himself in the direction hes wishes to be boosted. The last 3 seconds of the boost has an optional vocal countdown. These can be switched off by simply removing the sounds in actor browser in unrealed at map creation time. The VecBoost process will happen every time a new driver gets in the vehicle depending on how many boosts the mapper has specified when they placed it in the map ( setting this property to -1 will result in Infinite boosts). the boost strength and direction can be altered be the mapper at map creation time. It is also possible to set the vehicle so that it will boost whoever enters the drivers seat no just a new driver.
There is a BotLock System used on the Vec for the boosting process (see VitalOverdose/VecBooster for details on why). This is automatic and the only settable property of the bot lock is 'BotCaptureTime'
BoostDelay - Time delay for the boost on driver entry. BotCaptureTime - For the VitalOverdose/BotLock system. bBoostsEmptyVecs - If the vec should still boost if the driver leaves or dies during the countdown to the boost. SameDriverRE_Boost - If the current driver can leave then re-enter the vec and cause another boost Voc_Booster - For the vocal countdown. Voc_one - For the vocal countdown. Voc_two - For the vocal countdown. Voc_three - For the vocal countdown. bDirectional - Property already present in ASVehicleFactory. If true the vec will use the direction the. BoostingVecFactory is facing to base the direction of the boost on. TagfxClass - An emitter actor to use as a trail for the boost effect. Simply leave blank to disable the trail.
Internal Variables (not available to the mapper).
Boosts - How many available boosts this vec has. LastDriver - Valid actor ref of the last driver. currentdriver - Valid actor ref of the current driver. RotRelation - which actor to base the direction of the boost on ...indirectly set by mapper. bPrimed - Boolean to indicate if the vec is on a countdown to boost. bBoosting - Boolean to indicate if the vec has been boosted. Used to track the time on the botlock + trail Fx. VocalCounter - The vocal counter. spawnedtagFX - valid ref to the emitter making the fx trail. bCounting -
This Script is made possible by the way that the as vehicle factory keeps track of how many vehicles is spawned and whether it should be spawning a new one or not. When it does spawn a new vehicle the vehicles valid actor ref it recored by the factory and saved in the internal property called child. Also the vehicle itself takes a record of who spawned
function PostBeginPlay()
function PostBeginPlay() { local Gameinfo FoundGameInfo; // blank variable of type 'Gameinfo' to store ref foreach DynamicActors(Class'Engine.Gameinfo', FoundGameInfo) // iterates though all dynamic actors that are 'gameinfos' { // and stores a ref to them in FoundGameInfo FoundGameInfo.bAllowVehicles = True; // Sets the value FoundGameInfo.bAllowVehicles to true } RotRelation = Self; if (voc_booster!=none) { VocalCounter=3; } enable ('tick'); super.postbeginplay(); // copys any function related code from parent class }
function Timer()
this is the hardest function to modify in this class as is already used for the delay on the spawning of the vehicle in the first place. So any extra code has to operate with out messing with the existing functions
function Timer() { if ( bCounting) VocalCountdown(); else if ((bPrimed)&&(bUseBoostvec==true) && (boosts!=-1)) VecBoost(); else if ((Bboosting) && ( ONSVehicle(child).bDriverCannotLeaveVehicle )) ONSVehicle(child).bDriverCannotLeaveVehicle = false; if ( spawnedtagFX != None) spawnedtagFX.Destroyed(); Super.Timer(); }
function VocalCountdown()
this function is real only here to make things easyer to follow in the timer function. The timer function calls this function once and then the next 3 timer calls are controled from the end of this function if vocal counting is required.
function VocalCountdown() { VocalCounter -= 1; if (VocalCounter == 0) { child.playsound(Voc_booster); bcounting=false; bprimed=true; } else if (VocalCounter == 1) child.playsound(Voc_one); else if (VocalCounter == 2) child.playsound(Voc_two); else if (VocalCounter == 3) child.playsound(Voc_three); if (vocalcounter != -1) SetTimer (1,false); }
Simulated function VecBoost()
This is a modified version of the ONSVehicleBooster , it boosts the vehicle and spawns the Emitter fx. It then set the right flags in the boolean properties to indicate the new Virtual state of the vec. As we dont want to have to mess about with the vehicle code I'm keeping a 'VirtualRecord' of its state: either Primed ,Counting or Boosting so that decisions can be made based on what condition the vehicle is in at any one point in time.
Simulated function VecBoost() { local Vector PointBoostForce; boosts -= 1; if ( bDirectional == True) RotRelation = child; if ((child.driver != None) && ( child.IsHumanControlled()==false)) ONSVehicle(child).bDriverCannotLeaveVehicle = true; child.KAddImpulse( ActualBoostForce >> RotRelation.Rotation, PointBoostForce >> RotRelation.Rotation ) ; bPrimed = false; bBoosting = true; if (TagfxClass!=None) { spawnedtagFX=spawn(TagfxClass,child,,child.location,child.rotation); if (spawnedtagFX != None ) spawnedtagFX.setbase(child); } if ((child.driver != None) && ( child.IsHumanControlled()==false)) settimer(BotCaptureTime,false); }
Function VehicleSpawned()
this function is allready part of ASVhicle factory. it gets called from the function SpawnVehicle right after the vecfactory checks if the spawn whent ok. Here its being over written just to check the overall amount of boosts the vehicle has left. The new code is put in before the .super function and dosent contain any returns so it wont interfere with the way this function normaly works.
function VehicleSpawned() { if ( bUseBoostvec== true ) { boosts = 1; boosts += RepeatBoosts; } super.VehicleSpawned(); }
function Tick(float deltatime)
Here Tick() is over written to do most of the checking om the fx and the control over the botLock system. This leaves the timer function less cluttered and easyer to work with. Tick get run far more frequently that the timer (imn most cases) and it best not to have anything to complicated going on there as this is a strain on the cpu. There is a fair amount of code been added to tick in this case but i dont think its getting close to what would be considered to much
function Tick(float deltatime) { if ( child != none ) { if ((bBoosting) && (vocalcounter!= -1) && (Voc_Booster!=none)) vocalcountdown(); if ((child.Driver == none ) && (currentdriver!=None)) { lastdriver = currentdriver; currentdriver = none; if ( bPrimed == true) bPrimed = false; if ( bboosting == true) { bboosting = false; if ( spawnedtagfx!= none) spawnedtagFX.Destroy(); } } if ((bBoosting)&& (onsvehicle(child).bVehicleOnGround)) { bBoosting = false; if ( spawnedtagfx!= none) spawnedtagFX.Destroy(); if (onsvehicle(child).bDriverCannotLeaveVehicle == true) onsvehicle(child).bDriverCannotLeaveVehicle = false; } } super.tick(deltatime); }
function vehicledestroyed(Vehicle V)
This function is already present in asvehiclefactory and is called by the vehicle when it gets destroyed to tell the factory it needs to spawn another vehicle. Some code has been added to basically reset the timers and the virtual state of the vehicle (ie.primed,boosting etc).
function vehicledestroyed(Vehicle V) { lastdriver = currentdriver; currentdriver = none; bboosting = false; bPrimed = false; if (spawnedtagfx != none) spawnedtagFX.Destroy(); Super.VehicleDestroyed(v); }
Event VehicleUnPossessed( Vehicle V )
To save the stress on the cpu the trail fx are switched off if the driver leaves the vec while boosting. This also acts as a good visual indicator that someone has jumpped out that can be seen for some distance. The extra code here mainly deals with the seting of the right flags for the virtual state of the vec.
event VehicleUnPossessed( Vehicle V ) { lastdriver = currentdriver; currentdriver = none; if ( bBoosting == true) { bBoosting = false; if (spawnedtagFX!= none) spawnedtagFX.Destroyed(); if (bBoostsEmptyVecs != true) { if (vocalcounter != -1) vocalcounter = -1; } } else if ( bPrimed == true ) { if ( bBoostsEmptyVecs != true ) { bprimed = false; if( VocalCounter > -1) VocalCounter = -1; } } Super.VehicleUnPossessed(V); }
Event VehiclePossessed( Vehicle V )
This is the function that really make this mod possible in the first place. The vehicle will report back to the factory that spawned it as soon as someone eneters it. This means that the vehicle code dosent have to be alltered at all as the vehicle factory can quite simply call kaddimpulse using either the valid ref stored in the property child or the new one gained through this function (just called V). One the function has called boost it just sets a few flags fort the veirtual status of the vec.
event VehiclePossessed( Vehicle V ) { currentdriver=v.Driver; if ((bUseBoostvec==true) && (boosts != -1)) { if (voc_booster!=none) { VocalCounter=4; if ((voc_booster !=None) && (boostdelay >3)) { boostdelay-=3; bCounting = true; } bPrimed=True; } } Super.VehiclePossessed(V); }
The Completed Script
Here is the completed Script for now;-
class BoostingVehicleFactory extends ASVehicleFactory placeable; var() bool bUseBoostvec; var() vector ActualBoostForce; var() int RepeatBoosts; var() int BoostDelay; var() int BotCaptureTime; var() bool bBoostsEmptyVecs; var() bool SameDriverRE_Boost; var() sound Voc_Booster; var() sound Voc_one; var() sound Voc_two; var() sound Voc_three; var int Boosts; var pawn LastDriver; var pawn currentdriver; var actor RotRelation; var bool bPrimed; var bool bBoosting; var int VocalCounter; var emitter spawnedtagFX; var() class<emitter> TagfxClass< SEMI > var bool bCounting; function PostBeginPlay() { local Gameinfo FoundGameInfo; // blank variable of type 'Gameinfo' to store ref foreach DynamicActors(Class'Engine.Gameinfo', FoundGameInfo) // iterates though all dynamic actors that are 'gameinfos' { // and stores a ref to them in FoundGameInfo FoundGameInfo.bAllowVehicles = True; // Sets the value FoundGameInfo.bAllowVehicles to true } RotRelation = Self; if (voc_booster!=none) VocalCounter=3; enable ('tick'); super.postbeginplay(); // copys any function related code from parent class } function Timer() { if ( bCounting) VocalCountdown(); else if ((bPrimed)&&(bUseBoostvec==true) && (boosts!=-1)) VecBoost(); else if ((Bboosting) && ( ONSVehicle(child).bDriverCannotLeaveVehicle )) { ONSVehicle(child).bDriverCannotLeaveVehicle = false; if ( spawnedtagFX!=None) spawnedtagFX.Destroyed(); } super.timer(); } function VocalCountdown() { VocalCounter -= 1; if (VocalCounter == 0) { child.playsound(Voc_booster); bcounting=false; bprimed=true; } else if (VocalCounter == 1) child.playsound(Voc_one); else if (VocalCounter == 2) child.playsound(Voc_two); else if (VocalCounter == 3) child.playsound(Voc_three); if (vocalcounter != -1) SetTimer (1,false); } Simulated function VecBoost() { local Vector PointBoostForce; boosts -= 1; if ( bDirectional == True) RotRelation = child; if ((child.driver != None) && ( child.IsHumanControlled()==false)) ONSVehicle(child).bDriverCannotLeaveVehicle = true; child.KAddImpulse( ActualBoostForce >> RotRelation.Rotation, PointBoostForce >> RotRelation.Rotation ) ; bPrimed = false; bBoosting = true; if (TagfxClass!=None) { spawnedtagFX=spawn(TagfxClass,child,,child.location,child.rotation); if (spawnedtagFX != None ) spawnedtagFX.setbase(child); } if ((child.driver != None) && ( child.IsHumanControlled()==false)) settimer(BotCaptureTime,false); } function VehicleSpawned() { if ( bUseBoostvec== true ) { boosts = 1; boosts += RepeatBoosts; } super.VehicleSpawned(); } function Tick(float deltatime) { if ( child != none ) { if ((bBoosting) && (vocalcounter!= -1) && (Voc_Booster!=none)) vocalcountdown(); if ((child.Driver == none ) && (currentdriver!=None)) { lastdriver = currentdriver; currentdriver = none; if ( bPrimed == true) bPrimed = false; if ( bboosting == true) { bboosting = false; if ( spawnedtagfx!= none) spawnedtagFX.Destroy(); } } if ((bBoosting)&& (onsvehicle(child).bVehicleOnGround)) { bBoosting = false; if ( spawnedtagfx!= none) spawnedtagFX.Destroy(); if (onsvehicle(child).bDriverCannotLeaveVehicle == true) onsvehicle(child).bDriverCannotLeaveVehicle = false; } } super.tick(deltatime); } function vehicledestroyed(Vehicle V) { lastdriver = currentdriver; currentdriver = none; bboosting = false; bPrimed = false; if (spawnedtagfx != none) spawnedtagFX.Destroy(); Super.VehicleDestroyed(v); } event VehicleUnPossessed( Vehicle V ) { lastdriver = currentdriver; currentdriver = none; if ( bBoosting == true) { bBoosting = false; if (spawnedtagFX!= none) spawnedtagFX.Destroyed(); if ((bBoostsEmptyVecs != true)&& (vocalcounter != -1)) vocalcounter = -1; } else if (( bPrimed == true )&&( bBoostsEmptyVecs != true )) { bprimed = false; if( VocalCounter > -1) VocalCounter = -1; } super.VehicleUnPossessed(V); } event VehiclePossessed( Vehicle V ) { CurrentDriver = V.Driver; if (((bUseBoostvec == true) && (boosts != -1))&& if (voc_booster != none)) { VocalCounter = 4; if ((voc_booster != None) && (boostdelay > 3)) { boostdelay -= 3; bCounting = true; } bPrimed = True; } super.VehiclePossessed(V); }