Anozireth/IonTrigger
Download IonTrigger Package
http://www.geocities.com/Anozireth/IonTrigger.html
Description
This package provides a pair of classes that allow the mapper to place a volume that will trigger the firing of an IonCannon. It allows the mapper to specify either a fixed targer or the triggering player as the target. It also allows the mapper to set the minimum time between firings and the maximum number of firings.
How to use
Simply place an IonTriggerVolume in the map where you want it, and an IonCannon that can see intended area of the target. Then configure the following settings:
- bTargetPlayer
- If set to true, it will attempt to target the player which triggered it. If set to false it will target the IonTarget
- IonTarget
- Optional : An Actor of the IonTriggerTarget class at the point to be targeted. Note that there are no configuration options for the IonTriggerTarget.
- maxFires
- The maximum number of times this volume can trigger a firing. 0 = infinite
- resetTime
- The minimum time between firings. Note that each individual cannon takes about 3 seconds to reload, so a value of less than 3 is not recommended, and may cause the cannon to not refire properly if a player is still staning in the volume when the timer resets.
Source Code
//----------------------------------------------------------- // IonTriggerVolume - A volume that can be used to trigger an IonCannon. // By Tom Nicholson, aka Anozireth // anozireth@yahoo.com //----------------------------------------------------------- class IonTriggerVolume extends Volume; var() IonTriggerTarget IonTarget; // designated target var() bool bTargetPlayer; // Targets triggering actor if true, otherwise targets IonTarget var() float resetTime; // Time between fires. This should be > 0 var() int maxFires; // Maximum number of times this volume can trigger a firing. 0 = infinite var bool bWaitingToFire; // can we fire right now? var int firingCount; // How many times we've triggered a firing event touch(Actor Other) { // Don't fire if not enough time has elapsed since the last firing if (bWaitingToFire) return; // Don't fire if we're over the max number of firings if ( (maxFires>0) && (firingCount >= maxFires)) return; if ( Pawn(Other) != none ) if ( Pawn(Other).IsPlayerPawn() ) FireCannon(Pawn(Other)); // if the touch was by a player, then FIRE! } function IonCannon CheckMark(Pawn TargetPawn, vector MarkLocation, bool bFire) { local IonCannon I; // iterate through all cannons in the map until we can find one that can hit our target foreach DynamicActors(class'IonCannon', I) { // Found a cannon, try to fire it and check if it succeeded. if ( I.CheckMark(Instigator,MarkLocation,bFire) ) { firingCount++; // Keep track of how many times we've triggered a firing return I; } } // didn't find a cannon that could hit the target return None; } function FireCannon(Pawn TargetPawn) { local vector vecTarget; // Location aimed at by cannon local vector vecNorm; // not really used, just required by trace local string s; // Trace straight down from the target. // Cannons don't seem to like shooting at points that aren't on the ground. if (bTargetPlayer || (IonTarget == none)) // Target the triggering player Trace(vecTarget,vecNorm,TargetPawn.Location+Vect(0,0,-10000), TargetPawn.Location, false); else // Target the map specified target Trace(vecTarget,vecNorm,IonTarget.Location+Vect(0,0,-10000), IonTarget.Location, false); // Try to actually find a cannon and fire it if (CheckMark(TargetPawn,vecTarget,true) == none) { // didn't fire for some reason, log error s = string(name) $ " Couldn't find a valid cannon to fire on Target at: " $ string(vecTarget); Log(s); } else { // successfully fired, so reset timer bWaitingToFire=true; SetTimer(resetTime,false); } } // Checks if any pawns are touching the volume when it is re-activated function CheckIfTouching() { local actor A; // Don't fire if we're over the max number of firings if ( (maxFires>0) && (firingCount >= maxFires)) return; foreach TouchingActors(class'Actor', A) { Log("Found a touching actor"); if ( Pawn(A) != none ) { Log("Found a touching Pawn"); if ( Pawn(A).IsPlayerPawn() ) { Log("Found a touching PlayerPawn, firing..."); FireCannon(Pawn(A)); // we found a player touching the volume, so FIRE! return; } } } } // Re-Activates cannon after time delay function Timer() { bWaitingToFire=false; CheckIfTouching(); } defaultproperties { maxFires=0 resetTime=30 bTargetPlayer=true bWaitingToFire=false bStatic=false }
The IonTriggerTarget class is nothing but placeable subclass of Actor → Info and there's not really any code for it.
Discussion
Anozireth: This is my first real contribution here, so I hope you guys like it! I'm up way past my bedtime tonight so I'll have to polish this off tomorrow evening
EntropicLqd: Nice. About the only change I would make to the code would be to move the checks for invalid parameters into either the PreBeingPlay() or PostBeingPlay() function. You might also want an option for an infinite amount of fires. Pretty cool though - good job well done .
Jimbo: Indeed! I've been after a script like this for some time. Thanks for your help! (check your email, Tom)
Anozireth: EntropicLqd - I forgot to mention it in the description (at first, I added it now) but it was already in the code, 0 = infinite firings I'll see if I can rework it to get those checks into one of those two functions you mentioned. Jimbo, I'll write you back on that email later today, for now I gotta get to work here. Thanks for the positive feed back guys, I'm glad you liked it!
Anozireth: I just noticed a small bug that would allow the volume to exceed its maxFires if a player was standing in it when the CheckIfTouching function was called. I've updated the code here and the download with the new package.
~~ You could simplify this by using a LookTarget instead of the custom target class.