|
|
(7 intermediate revisions by 4 users not shown) |
Line 1: |
Line 1: |
| Do not edit the area above the separator line, please. | | Do not edit the area above the separator line, please. |
| ---- | | ---- |
− | [[Legacy:Actor]]
| + | UIComp_DrawImage custom subclasses: |
− | [[Actor]]
| + | {{#dpl: |
− | [[UE3:Actor (UT3)]]
| + | |category=Subclasses of UIComp_DrawImage{{!}}Subclasses of UIComp_DrawImage (UE3)}{{!}}Subclasses of UIComp_DrawImage (UT3) |
− | [[Project:Sandbox]]
| + | |category=Custom classes{{!}}Custom UE3-specific classes{{!}}Custom UT3-specific classes |
− | | + | |namespace={{#if:UE3|{{!}}UE3}}{{!}}User |
− | <uscript>
| + | |format=,[[%PAGE%|%TITLE%]],, |
− | // Extended to add support for weapon idle animations
| + | |inlinetext=,  |
− | //////////////////////////////////////////////////////
| + | |shownamespace=false |
− | simulated state Active
| + | |replaceintitle=/ (?!\()/,_ |
− | { | + | |resultsheader=\n;Known custom subclasses:: |
− | simulated function BeginState(name PreviousStateName)
| + | |oneresultheader=\n;Known custom subclass:: |
− | {
| + | |noresultsheader=<nowiki></nowiki> |
− | local int i;
| + | |allowcachedresults=true |
− | | + | }} |
− | // Cache a reference to the AI controller
| + | |
− | if (Role == ROLE_Authority)
| + | |
− | {
| + | |
− | CacheAIController();
| + | |
− | }
| + | |
− | | + | |
− | if ( SendToIdleState() )
| + | |
− | {
| + | |
− | if ( GetZoomedState() == ZST_Zoomed )
| + | |
− | {
| + | |
− | PushState('Zoomed');
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | OnAnimEnd(none, 0.f, 0.f);
| + | |
− | if ( UTBot(Instigator.Controller) != None )
| + | |
− | {
| + | |
− | if ( PendingFire(0) )
| + | |
− | {
| + | |
− | StillFiring(0);
| + | |
− | }
| + | |
− | else if ( PendingFire(1) )
| + | |
− | {
| + | |
− | StillFiring(1);
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | // Check to see if we need to go down
| + | |
− | if( bWeaponPutDown )
| + | |
− | {
| + | |
− | `LogInv("Weapon put down requested during transition, put it down now");
| + | |
− | PutDownWeapon();
| + | |
− | }
| + | |
− | else if ( !HasAnyAmmo() )
| + | |
− | {
| + | |
− | WeaponEmpty();
| + | |
− | }
| + | |
− | else if ( bAutoFire )
| + | |
− | {
| + | |
− | // if either of the fire modes are pending, perform them
| + | |
− | for( i=0; i<GetPendingFireLength(); i++ )
| + | |
− | {
| + | |
− | if ( PendingFire(i) )
| + | |
− | {
| + | |
− | BeginFire(i);
| + | |
− | break;
| + | |
− | }
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | if (InvManager != none && InvManager.LastAttemptedSwitchToWeapon != none)
| + | |
− | {
| + | |
− | if (InvManager.LastAttemptedSwitchToWeapon != self)
| + | |
− | {
| + | |
− | InvManager.LastAttemptedSwitchToWeapon.ClientWeaponSet(true);
| + | |
− | }
| + | |
− | InvManager.LastAttemptedSwitchToWeapon = none;
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | /**
| + | |
− | * Override BeginFire to verify that the pawn isn't busy (performing other blocking animations, etc.) as well
| + | |
− | * as handle starting the prefire sequence if this weapon has a prefire animation.
| + | |
− | */
| + | |
− | simulated function BeginFire(byte FireModeNum)
| + | |
− | {
| + | |
− | // verify that our owning pawn isn't busy before calling Super.BeginFire(), which is where PendingFire is set
| + | |
− | if ( !IsFiringAllowed(FireModeNum) )
| + | |
− | {
| + | |
− | return;
| + | |
− | }
| + | |
− | | + | |
− | // `log(`location @ `showvar(IsTimerActive(nameof(DelayedFire)),DelayedFire Active));
| + | |
− | | + | |
− | // if this weapon uses a prefire animation
| + | |
− | if ( FireModeNum < PrefireDelay.Length && PreFireDelay[FireModeNum] > 0 )
| + | |
− | {
| + | |
− | PrefireCachedStartTrace = InstantFireStartTrace();
| + | |
− | if ( FireModeNum == 0 )
| + | |
− | {
| + | |
− | // if there is already a timer for this, it means that the user is spamming the fire button
| + | |
− | // and we are still performing the prefire sequence from the first time the user pressed the
| + | |
− | // fire button
| + | |
− | if ( IsTimerActive(nameof(DelayedFire)) )
| + | |
− | {
| + | |
− | return;
| + | |
− | }
| + | |
− | | + | |
− | // do the actual firing of the weapon after the prefire sequence has been completed.
| + | |
− | SetTimer(PreFireDelay[FireModeNum], false, nameof(DelayedFire));
| + | |
− | }
| + | |
− | else if ( FireModeNum == 1 )
| + | |
− | {
| + | |
− | // if there is already a timer for this, it means that the user is spamming the fire button
| + | |
− | // and we are still performing the prefire sequence from the first time the user pressed the
| + | |
− | // fire button
| + | |
− | if ( IsTimerActive(nameof(DelayedAltFire)) )
| + | |
− | {
| + | |
− | return;
| + | |
− | }
| + | |
− | | + | |
− | // do the actual firing of the weapon after the prefire sequence has been completed.
| + | |
− | SetTimer(PreFireDelay[FireModeNum], false, nameof(DelayedAltFire));
| + | |
− | }
| + | |
− | else
| + | |
− | {
| + | |
− | `log("Unhandled fire mode in" @ Name $ "." $ GetFuncName() @ "-" @ FireModeNum);
| + | |
− | ScriptTrace();
| + | |
− | }
| + | |
− | | + | |
− | // ensure our weapon mode is custom so that CustomFire() is called right now. CustomFire() will do the prefire stuff
| + | |
− | WeaponFireTypes[FireModeNum] = EWFT_Custom;
| + | |
− | }
| + | |
− | | + | |
− | Super.BeginFire(FireModeNum);
| + | |
− | }
| + | |
− | | + | |
− | /**
| + | |
− | * Called when an animation ends.
| + | |
− | *
| + | |
− | * Always return to the weapon idle animation after our last played custom animation is finished, if it has one.
| + | |
− | */
| + | |
− | simulated event OnAnimEnd( optional AnimNodeSequence SeqNode, optional float PlayedTime, optional float ExcessTime )
| + | |
− | {
| + | |
− | // we do NOTHING, very much on purpose, so that UT will stop triggering our idle animation while we're in the middle
| + | |
− | // of doing something else.
| + | |
− | }
| + | |
− | | + | |
− | /**
| + | |
− | * Starts a random idle animation.
| + | |
− | */
| + | |
− | simulated function PlayWeaponIdleAnim( optional bool bLocalOnly )
| + | |
− | {
| + | |
− | Global.PlayWeaponIdleAnim(bLocalOnly);
| + | |
− | }
| + | |
− | | + | |
− | | + | |
− | /**
| + | |
− | * Called when zooming starts.
| + | |
− | *
| + | |
− | * @param WeaponOwner value of Instigator.Controller, the player that is holding this weapon.w
| + | |
− | */
| + | |
− | simulated function StartZoom(UTPlayerController WeaponOwner)
| + | |
− | {
| + | |
− | `wtrace_enter(Self,`showvar(WeaponOwner));
| + | |
− | | + | |
− | // calling Global.StartZoom() will result in the PlayWeaponIdleAnimation() function being called. Since we are transitioning into
| + | |
− | // a zoomed state, we want the idle animation that is played to be the one setup for the zoom mode. Therefore, PushState() prior
| + | |
− | // to calling Global.StartZoom() so that Zoomed.PlayWeaponIdleAnim() is called rather than our version.
| + | |
− | PushState('Zoomed');
| + | |
− | Global.StartZoom(WeaponOwner);
| + | |
− | | + | |
− | // and just to be on the safe side.
| + | |
− | PlayWeaponIdleAnim();
| + | |
− | | + | |
− | `wtrace_exit(Self);
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | simulated state WeaponEquipping
| + | |
− | { | + | |
− | /**
| + | |
− | * Overridden to trigger our weapon equip animation and hide the carry attachment.
| + | |
− | */
| + | |
− | simulated event BeginState(Name PreviousStateName)
| + | |
− | {
| + | |
− | Super.BeginState(PreviousStateName);
| + | |
− | | + | |
− | if ( !bDisplayAmmoAttachment )
| + | |
− | {
| + | |
− | ToggleCarryAttachment(false);
| + | |
− | }
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | simulated state WeaponFiring
| + | |
− | {
| + | |
− | ignores SwitchAmmoTypes;
| + | |
− | /**
| + | |
− | * Timer event, call is set up in Weapon::TimeWeaponFiring().
| + | |
− | * The weapon is given a chance to evaluate if another shot should be fired.
| + | |
− | * This event defines the weapon's rate of fire.
| + | |
− | */
| + | |
− | simulated function RefireCheckTimer()
| + | |
− | {
| + | |
− | if ( IsTimerActive(nameof(DelayedFire)) || IsTimerActive(nameof(DelayedAltFire)) )
| + | |
− | {
| + | |
− | return;
| + | |
− | }
| + | |
− | Super.RefireCheckTimer();
| + | |
− | }
| + | |
− | | + | |
− | simulated event BeginState(name PreviousStateName)
| + | |
− | {
| + | |
− | // this call will result in WeaponFired() being called, which spawns our effects.
| + | |
− | // After returning from this function, the CheckRefire timer function will be active.
| + | |
− | Super.BeginState(PreviousStateName);
| + | |
− | }
| + | |
− | | + | |
− | simulated event EndState(name NextStateName)
| + | |
− | {
| + | |
− | local int Idx;
| + | |
− | | + | |
− | if ( NextStateName == 'Active' )
| + | |
− | {
| + | |
− | for ( Idx = 0; Idx < GetPendingFireLength(); Idx++ )
| + | |
− | {
| + | |
− | ClearPendingFire(Idx);
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | Super.EndState(NextStateName);
| + | |
− | }
| + | |
− | | + | |
− | simulated function StartZoom(UTPlayerController WeaponOwner)
| + | |
− | {
| + | |
− | // don't allow the player to switch zooming modes while reloading
| + | |
− | }
| + | |
− | | + | |
− | simulated function EndZoom(UTPlayerController WeaponOwner)
| + | |
− | {
| + | |
− | // don't allow the player to switch zooming modes while reloading
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | /** Override BeginFire so that it will enter the firing state right away. */
| + | |
− | simulated function BeginFire(byte FireModeNum)
| + | |
− | {
| + | |
− | | + | |
− | // verify that our owning pawn isn't busy before calling Super.BeginFire(), which is where PendingFire is set
| + | |
− | if ( !IsFiringAllowed(FireModeNum) )
| + | |
− | {
| + | |
− | return;
| + | |
− | }
| + | |
− | //`log(`location @ `showvar(IsTimerActive(nameof(DelayedFire)),DelayedFire Active));
| + | |
− | | + | |
− | Super.BeginFire(FireModeNum);
| + | |
− | | + | |
− | } | + | |
− | | + | |
− | | + | |
− | /**
| + | |
− | * This function is only called if our weapon has a prefire delay. CustomFire() is called to start the weapon's animations and
| + | |
− | * play the firing sound. Meanwhile, a timer is ticking away (started by BeginFire()) for either DelayedFire() or DelayedAltFire()
| + | |
− | * which, when executed, takes care of actually consuming the ammo and applying dmg to the target.
| + | |
− | */
| + | |
− | simulated function CustomFire()
| + | |
− | {
| + | |
− | local int i;
| + | |
− | local float FireRateScale;
| + | |
− | local DepthPawn DP;
| + | |
− | local float FireAnimRate; // scaled by owner's remaining stamina.
| + | |
− | | + | |
− | //`log(`location @ `showvar(FireInterval[i]) @ `showvar(IsTimerActive(nameof(DelayedFire)),TimedFireActive));
| + | |
− | //ScriptTrace();
| + | |
− | DP = GetDP(true);
| + | |
− | | + | |
− | // do nothing here - this means that our weapon had a prefire delay and the actual
| + | |
− | // firing will be handled in DelayedFire/DelayedAltFire
| + | |
− | | + | |
− | // or weapons w/o prefire delay play their anims at speed 0! (ie. not at all!)
| + | |
− | FireAnimRate = 1.0f;
| + | |
− | FireRateScale = GetScaledFireSpeed();
| + | |
− | | + | |
− | if ( bReqStamina )
| + | |
− | {
| + | |
− | // Change the animation playback speed.
| + | |
− | FireAnimRate = FClamp(FireRateScale,0.5,2.0);
| + | |
− | | + | |
− | // Change the min. time between refires.
| + | |
− | for ( i = 0; i < FireInterval.Length; i++ )
| + | |
− | {
| + | |
− | FireInterval[i] = FClamp(
| + | |
− | default.FireInterval[i] * (1.0f / FireRateScale),
| + | |
− | default.FireInterval[i]*0.5,
| + | |
− | default.FireInterval[i]*2
| + | |
− | );
| + | |
− | }
| + | |
− | | + | |
− | // Change the delay between the initial fire call and when damage is done.
| + | |
− | PreFireDelay[CurrentFireMode] = FClamp(
| + | |
− | default.PreFireDelay[CurrentFireMode] * (1.0f / FireRateScale),
| + | |
− | default.PreFireDelay[CurrentFireMode] * 0.5,
| + | |
− | default.PreFireDelay[CurrentFireMode] * 2
| + | |
− | );
| + | |
− | DP.WeaponStamina = Max(DP.WeaponStamina - StamCon, 0);
| + | |
− | }
| + | |
− | | + | |
− | PlayPrefire(FireAnimRate);
| + | |
− | | + | |
− | /*
| + | |
− | `log("FireAnim Playback rate is : "@FireAnimRate);
| + | |
− | `log("Fire Interval is : "@Fireinterval[0]);
| + | |
− | `log("Owner stamina is : "@P.SprintStamina);
| + | |
− | */
| + | |
− | | + | |
− | LastFireTime = WorldInfo.TimeSeconds;
| + | |
− | }
| + | |
− | | + | |
− | /** | + | |
− | * Begins the weapon's prefire animation and sound.
| + | |
− | *
| + | |
− | * @param AnimRate scales the speed of the animation
| + | |
− | */
| + | |
− | simulated function PlayPrefire( float AnimRate )
| + | |
− | {
| + | |
− | //`log(`location);
| + | |
− | // Sharks need their fire anims blended to the fullbody slot -- probably need to move this to PlayFireEffects
| + | |
− | if ( WorldInfo.NetMode != NM_DedicatedServer )
| + | |
− | {
| + | |
− | <snip a bunch of code that calls custom functions for running game-specific animations>
| + | |
− | PlayPreFiringSound();
| + | |
− | ShakeView();
| + | |
− | }
| + | |
− | | + | |
− | }
| + | |
− | | + | |
− | /** | + | |
− | * For tracehit weapons with no prefire delay, handles firing the weapon.
| + | |
− | */
| + | |
− | simulated function InstantFire()
| + | |
− | {
| + | |
− | //`log(`location);
| + | |
− | CustomFire();
| + | |
− | PerformInstantFire();
| + | |
− | }
| + | |
− | | + | |
− | /**
| + | |
− | * For weapons using projectiles, which have no prefire delay - fires the weapon.
| + | |
− | */
| + | |
− | simulated function Projectile ProjectileFire()
| + | |
− | {
| + | |
− | //`log(`location);
| + | |
− | CustomFire();
| + | |
− | return Super.ProjectileFire();
| + | |
− | | + | |
− | }
| + | |
− | | + | |
− | simulated function Delayed_CustomFire( byte FireModeNum );
| + | |
− | | + | |
− | /**
| + | |
− | * Called on a timer (set in BeginFire()), this is called only for weapons which have a prefire delay.
| + | |
− | */
| + | |
− | simulated function DelayedFire()
| + | |
− | {
| + | |
− | DelayedWeaponFire(0);
| + | |
− | }
| + | |
− | | + | |
− | /**
| + | |
− | * Called on a timer (set in BeginFire()), this is called only for weapons which have a prefire delay.
| + | |
− | */
| + | |
− | simulated function DelayedAltFire()
| + | |
− | {
| + | |
− | DelayedWeaponFire(1);
| + | |
− | }
| + | |
− | | + | |
− | simulated function DelayedWeaponFire( byte FireModeNum )
| + | |
− | {
| + | |
− | //`log(`location);
| + | |
− | // restore our WeaponFireType, since we switched it to EWFT_Custom in BeginFire()
| + | |
− | WeaponFireTypes[FireModeNum] = default.WeaponFireTypes[FireModeNum];
| + | |
− | if ( WeaponFireTypes[FireModeNum] == EWFT_InstantHit )
| + | |
− | {
| + | |
− | // our own version of InstantFire() is only called for weapons that do not have a prefire
| + | |
− | // delay, so go directly to our parent class/state version
| + | |
− | PerformInstantFire();
| + | |
− | }
| + | |
− | else if ( WeaponFireTypes[FireModeNum] == EWFT_Projectile )
| + | |
− | {
| + | |
− | // our own version of ProjectileFire() is only called for weapons that do not have a prefire
| + | |
− | // delay, so go directly to our parent class/state version
| + | |
− | Super.ProjectileFire();
| + | |
− | }
| + | |
− | else if ( WeaponFireTypes[FireModeNum] == EWFT_Custom )
| + | |
− | {
| + | |
− | Delayed_CustomFire(FireModeNum);
| + | |
− | }
| + | |
− | | + | |
− | PrefireCachedStartTrace = vect(0,0,0);
| + | |
− | }
| + | |
− | | + | |
− | /**
| + | |
− | * Utility function to allow me to inject some debugging code prior to passing control to our parent classes.
| + | |
− | */
| + | |
− | protected simulated function PerformInstantFire()
| + | |
− | {
| + | |
− | Super.InstantFire();
| + | |
− | }
| + | |
− | | + | |
− | </uscript> | + | |
− | | + | |
− | Testing UScript highlighter...
| + | |
− | <uscript> | + | |
− | class X extends Y within Z
| + | |
− | implements(I)
| + | |
− | nottransient;
| + | |
− | | + | |
− | `include(SomeFile.uci)
| + | |
− | | + | |
− | | + | |
− | var(Group) interp struct Type {
| + | |
− | var() bool bCorrect;
| + | |
− | var array<class<Actor> > ActorClasses;
| + | |
− | } VarName;
| + | |
− | | + | |
− | reliable client function CheckType(optional class<Actor> ActorClass)
| + | |
− | {
| + | |
− | local int i;
| + | |
− | | + | |
− | for (i = 0; i < VarName.ActorClasses.Length; ++i) {
| + | |
− | if (ActorClass == None || ClassIsChildOf(VarName.ActorClasses[i], ActorClass)) {
| + | |
− | VarName.ActorClasses[i].static.StaticSaveConfig();
| + | |
− | continue;
| + | |
− | }
| + | |
− | VarName.ActorClasses.Remove(i--, 1);
| + | |
− | }
| + | |
− | VarName.bCorrect = True;
| + | |
− | } | + | |
− | | + | |
− | static function byte GetHash(int Value)
| + | |
− | {
| + | |
− | switch (Value) {
| + | |
− | case -1:
| + | |
− | return 0;
| + | |
− | case 0xCAFE:
| + | |
− | return 1
| + | |
− | default:
| + | |
− | return (Value >= 0 && Value < 10) ? class'Hasher'.default.Hash[Value] : (Value & 0xff);
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | defaultproperties
| + | |
− | {
| + | |
− | VarName.Empty
| + | |
− | VarName[0] = {(
| + | |
− | bCorrect = True,
| + | |
− | ActorClasses.Add(class'ReplicationInfo')
| + | |
− | )}
| + | |
− | }
| + | |
− | </uscript>
| + | |
Do not edit the area above the separator line, please.