Help with UTWeapon Function CanAttack

Hello guys, it’s me again :smiley:

I want to be able to show a kind of “press LMB to silent kill” icon for my knife weapon whenever the player gets close to the enemy while holding the weapon knife. I know how to draw icon to screen using Canvas Draw Icon, however I am having problem on detecting if player is in the correct distance from enemy.

My knife is a simple instant hit weapon with infinite ammo, and with a weapon range of 39, so the player needs to be close enough to the enemy pawn to be able to hit it. And in the Take Damage Event of the enemy pawn all the animation is played on both the player mesh and enemy pawn mesh, which makes the Execution Knife Sequence to synchronize between player and enemy.

There is the function CanAttack in UTWeapon Class:


function bool CanAttack(Actor Other)


Which is responsible to detect if the player holding weapon is in range for attacking the enemy, so I have changed this function a bit, by adding a new variable to my knife weapon class:


var bool KnifeKillRange;


Down there in the function is this statement:


    // check that target is within range
    Dist = VSize(Instigator.Location - Other.Location);
    if (Dist > MaxRange())
    {
        return false;
    }

So then I just added this new statement which is related to weapon range instead of MaxRange:


    //chech if the target is within weapon range////////////////////////////////////////////////////////////////
    if ( Dist <= WeaponRange )
    {
        return true;
        KnifeKillRange = true;    
    }

    if ( Dist > WeaponRange )
    {
        return false;
        KnifeKillRange = false;
    }    
    //chech if the target is within weapon range////////////////////////////////////////////////////////////////

And for testing, as I did not find any mention to Tick Event on UTWeapon, so just for having a imediate feedback, I added this function in the fireammunition function to check if the player is in the correct distance and log the result for me:


simulated function FireAmmunition()
{
      if (KnifeKillRange == true)
      {
        `Log("Press LMB to Silent Kill");    
      }

      if (KnifeKillRange == false)
      {
        `Log("You are not in range for Silent Kill");
      }      

      super.FireAmmunition();
}

The code compiled correctly, without any errors or warnings, however, the problem is that the check distance is not working, because my variable KnifeKillRange always is set to false.

The only log message I receive is “You are not in range for Silent Kill”.

Any help?

Cheers :smiley:

call the bool before you returns so they can set. swap them around

in your ifs just ask if(KnifeKillRange) < that will check is it true. if (!KnifeKillRange) < this will check is it false.

Thanks bro for the info!

UDKULtimate I don’t wanna ■■■■ you off or demorilize you, but I think you would be better making your own code than extending of UT, idk do what you want you are free, for me best UDK is clean UDK without UT,

to help you in your problem i’d place a lot of logs like this

`log(“FROM UTClass(the name class) function getting called”);

where (the name class) the name of the class you are calling from, not the brackets something like this `log(“FROM UTVehicle function getting called”);

Hey dude, never mind :cool:

I like to hear any kind of comments, I always take things easy, and untill today I never had any bad arguments with anyone over the internet, instead, all people I contact them through forums, they always end up by having a good friendship with me.

About your comment about using UT Code, man, I think you are overestimating me :smiley:

I am not that professional on script, instead, I am still amateur, and more of the things I do on script, I do them by trial and error, and I try to learn things on demand. I don’t have much time to get an entire book of unreal scripting and study, Instead of that, I study what I need to learn whenever I want to do something in my game.

I extended the UT Classes because, as I said, for a beginner it is the best place to start off and because of my game is indeed based on Unreal Tournament (however in 3rd person). And extending UT Classes was the best way for me learning how unreal script works.

Anyway thanks for the comments and until this weekend I will finish this knife kill script with this new icon feature.

Thanks for all!

my hint is for you to program in multiplayer so you master the UnrealScript like a boss, if you want i teach you do you have discord?

Hello guys,

After a lot of headaches, I tried to change a bit the way to get distance between player and enemy. I tried all the ways using the UTWeapon function canattack, however it did not work.

As always, I never give up :smiley:

What I want is simply to show up an icon whenever the player is close enough to the enemy pawn to inform the player that he can now perform a knife kill.

I am doing this in parts, first part I need is to find a way to detect the distance between the player and the enemy pawn.

Now I am trying to use a custom function inside UTPawn to check distance between the player (using UTPlayer Controller, which I assume is controlled by the player.

This is the function I wrote inside my custom enemy pawn, which is extended from UTPawn (i have made it inside the tick event because I need that this check must be done always, at each frame):


simulated function Tick(float DeltaTime)
{
    // local variables
    local float TempTotalDistance;

    //this variable will be used to access player controller
    local Playercontroller localplayer;    

       ForEach LocalPlayerControllers(class'PlayerController', localPlayer)
       {

        TempTotalDistance = VSize2D(UTPlayerController(localplayer).Location - Location);  

       }

       if (TempTotalDistance <= 50)
       {
       `Log("Perform a Knife Kill");
       }

       if (TempTotalDistance &gt; 50)
       {
       `Log("You are not in range for a knife kill");
       }

}

The problem which is driving me nuts, again, is that no matter how close or how far I am from the enemy Pawn, I only receive the log message “You are not in range for a knife kill”

Any tips?

Thanks in advance

:smiley:

you might want to check the local player’s Pawn instead of the playercontroller

WOW man, you are genious!!!

I just changed to this:


TempTotalDistance = VSize2D(UTPlayerController(localplayer).**Pawn**.Location - Location);

Now it is detecting perfect the distance and making the log message correctly.

So now I can go to next step which is to draw the icon on screen.

THANKS BRO!!!

:smiley:

Hello folks!

I need another help :smiley:

I need that my enemy pawn detects wether the player is using the weapon, in this case, the knife weapon (which is extended from UTWeapon and has the Inventory Group index as 6


simulated event Tick(float DeltaTime)
{
    // local variables
    local byte knifeEquipped;

    local Playercontroller localplayer;    

       ForEach LocalPlayerControllers(class'PlayerController', localPlayer)
       {

**        knifeEquipped = UTPlayerController(localplayer).Pawn.Weapon(PawnOwner.InvManager.PendingWeapon).InventoryGroup;**

       }

       if (knifeEquipped == 6)
       {
       `Log("KNIFE EQUIPPED");
       }

       else
       {
       `Log("YOU ARE NOT USING A KNIFE");
       }
}

However this is not working, it gives me the error message on compiling scripts: Error, type mismatch in ‘=’

Is there another way for the Pawn detect which weapon the player is using?

Cheers.

UTPlayerController(localplayer).Pawn.Weapon(PawnOwner.InvManager.PendingWeapon).InventoryGroup;
you missing something there? what kind of cast is Pawn.Weapon(whatever).whatever ?

also why are you casting into a ‘byte’ type instead of the actual knife weapon class?

also why are you even putting this code into each and every enemy in the first place?

Hello man, thanks again for the patience and trying to help me!

I am trying more by trial and error, by getting some pieces of code from UTInventoryManager, and UTWeapon and see what happens :smiley:

This code I placed on my EnemyPawn, I just wanted to make the enemy pawn (which is extended from UTPawn) detect that the Pawn associated to the Local PlayerController (the player itself) is using a weapon that has the InventoryGroup number of 6, in my case is my custom Knife Class.

I used byte ecause the InventoryGroup variable on the UTWeapon Class is a byte variable.

However if you can correct my mistakes on this code, I would be very gratefull my friend.

Thanks

:slight_smile:

Hello guys.

Finally, after a weekend of searching, studying, and breaking my head :D:D:D:D I am almost close to finish this feature, the knife kill icon.

I created a small flash/scaleform icon animation for indicating the player the right moment to press the knife kill button.

I added this code for load a flash movie GFX inside the UTGFxHudWrapper.uc class:


//function to show knifekill icon animation////////////////////////////////////////////////////

//custom var for knifekill icon animation
var UTGFxTweenableMoviePlayer KnifeKillIconHUD;

exec function KnifeKillIconAnimStart()
{
  if ( KnifeKillIconHUD == none )
       KnifeKillIconHUD = new(PlayerOwner) class'UTGFxTweenableMoviePlayer';

  KnifeKillIconHUD.MovieInfo = SwfMovie'gameplay_icons.udk_knifekill';
  KnifeKillIconHUD.bDisplayWithHudOff = true;
  KnifeKillIconHUD.bEnableGammaCorrection = false;
  KnifeKillIconHUD.LocalPlayerOwnerIndex = class'Engine'.static.GetEngine().GamePlayers.Find(LocalPlayer(PlayerOwner.Player));
  KnifeKillIconHUD.SetTimingMode(TM_Real);
  KnifeKillIconHUD.Start();
  KnifeKillIconHUD.SetViewScaleMode(SM_NoScale);
  KnifeKillIconHUD.SetAlignment(Align_Center);
  KnifeKillIconHUD.Advance(0);
}

exec function KnifeKillIconAnimEnd()
{
  KnifeKillIconHUD.Close();
}
//function to show knifekill icon animation////////////////////////////////////////////////////

I made this an exec function because of the flexibility that it allows me call it from almost any class (I think) making it as a Console Command targetted to the Player Controller.

So on my enemy pawn, I added this code to detect the distance between the enemy pawn and the player. then call the exec KnifeKillIconAnimStart(), and I finally found how to make the enemy pawn detect the weapon class the player is using (I have read all the UTPawn class, line by line, and tried all the statements which make reference to weapon and pawn until it worked):


//check knife kill function///////////////////////////////////////////////////
simulated function CheckKnifeKill()
{
    // local variables
    local Pawn Enemy;

    //Ana Irhabi Player Controller
    local Playercontroller AIPC;

    //custom var to store distance between player and enemy
    local float PawnDistance;

    if ( PlayerCanSeeMe() && IsAliveAndWell() )
    {

      //here the local player is the enemy
      Enemy = GetALocalPlayerController().Pawn;
      AIPC = GetALocalPlayerController();

      if ( Enemy != none && Enemy.IsAliveAndWell() )
      {

        PawnDistance = Vsize( Enemy.Location - Location );
        `Log( self @Enemy @PawnDistance);

          //if player is close enough to perform knife kill
          if ( PawnDistance &lt;= 45 && Enemy.Weapon.Class == class'UTWeap_AIKnife' )
          {
            `Log("FINISH HIM");          
            UTPlayerController(AIPC).ConsoleCommand("KnifeKillIconAnimStart");
          }

          //if player is out of reach to perform knife kill
          if ( PawnDistance > 45 && Enemy.Weapon.Class == class'UTWeap_AIKnife' )
          {
            `Log("YOU ARE NOT IN RANGE FOR KNIFE KILL");          
            UTPlayerController(AIPC).ConsoleCommand("KnifeKillIconAnimEnd")
          }
        //this function will play the flash animation knife kill icon/////////////////

      }

    }

}

simulated event Tick(float DeltaTime)
{
Super.Tick(DeltaTime);
CheckKnifeKill();
}
//check knife kill function///////////////////////////////////////////////////

Now I am having 2 small errors:

1- First error is that the flash movie begins stopped on the first frame, the animation does not play

2- The player proximity detection works perfect, it shows the icon whenever the player gets in the right distance and hides the icon when the player is far from the enemy, however it works only the first time. If I try again (get close then get away), whenever the icon shows up it looks like I lost the control over the player controller so that the player keeps running alone, like if the last key i pressed, in example W, it stucks on that and the player keeps running alone.

Any help?

What happens if you remove this line?



KnifeKillIconHUD.Advance(0);


Also, in your Flash movie’s code you don’t have anything that calls stop(), do you? If you have a stop() in your ActionScript, that would cause the movie to stay paused on that frame.

That second problem is really strange. Are you getting any errors in the log?

For now you might just want to make sure that your movie is not capturing any input. Next, I’m wondering if you really want to do this:



KnifeKillIconHUD.Close();


Maybe if you need to do that, you should also do



KnifeKillIconHUD = none;


But those are just ideas off the top of my head.

the reason why I was asking why this is in every enemy instead of in the player are simple: you have code running in as many enemies as you have which makes things slower for no reason. but also if you ever encounter 2 enemies at the same time and one of them moves away the icon will disappear instead of staying enabled for the other enemy - so your logic is flawed

so,

problem 1: you probably need a Play() function in your actionscript code

problem 2: lets explore this a bit…

if your KnifeKillIconHUD is None you create it, but regardless of that you reassign the MovieInfo anyway, so perhaps that’s why it doesn’t reappear. try this:


exec function KnifeKillIconAnimStart()
{
  if ( KnifeKillIconHUD == none )
  {
       KnifeKillIconHUD = new(PlayerOwner) class'UTGFxTweenableMoviePlayer';
       KnifeKillIconHUD.MovieInfo = SwfMovie'gameplay_icons.udk_knifekill';
       KnifeKillIconHUD.bDisplayWithHudOff = true;
       KnifeKillIconHUD.bEnableGammaCorrection = false;
       KnifeKillIconHUD.LocalPlayerOwnerIndex = class'Engine'.static.GetEngine().GamePlayers.Find(LocalPlayer(PlayerOwner.Player));
       KnifeKillIconHUD.SetTimingMode(TM_Real);
       KnifeKillIconHUD.SetViewScaleMode(SM_NoScale);
       KnifeKillIconHUD.SetAlignment(Align_Center);
  }
  KnifeKillIconHUD.Start();
}

even if it doesn’t fix the issue it’s cleaner to simply close the movie and reopen it rather than re-initializing it every time

I also removed the KnifeKillIconHUD.Advance(0); part from the code as Nathaniel3W suggests. it’s unnecessary and personally I prefer Flash to handle how the movie advances and plays
I wouldn’t do the other suggestion from Nathaniel3W, adding KnifeKillIconHUD = none; would cause the movie to be re-initialized every time you want to open it which is what I avoided in the code changes above

also no need to PM me to check your stuff. I monitor these forums anyway and I help when I can

Hello guys!

Sorry to be annoying :D, but thanks for all the help! Yeah, I already solved the problem, I think my player controller was kind of freezing because the console commands were occuring at the same time on the tick event, both the icon animation start and icon animation end, so because this it would sometimes not show the icon at all. So because this I created two separeted functions to show and close the icon animation, and placed these functions outside the tick event.

Another mistake was the pawn distance checking, I only checked for < and >, not <=, because I think this was somehow confusing UDK whenever I would get close and far from the enemy pawn.

So here is the final code, even though the flash animation stays on the first frame, it does not animate (in the exported swf it plays normal), but this is not a big deal, I can go on finishing my game demo to upload to Steam soon.

Thanks guys for all the help and support!!!

On my Enemy pawn:


//I declared the variables on the top of the pawn class and made them global, not local vars, so can be acessed from all the functions
var bool knifekill;
var Pawn Enemy;
var Playercontroller AIPC;
var float PawnDistance;

//here on the PostBeginPlay event I set the knifekill var as false
simulated event PostBeginPlay()
{
  Super.PostBeginPlay();
  knifekill = false;
}

//check knife kill function///////////////////////////////////////////////////
simulated function CheckKnifeKill()
{

    if ( PlayerCanSeeMe() && IsAliveAndWell() ) 
    {

      //here the local player is the enemy
      Enemy = GetALocalPlayerController().Pawn;
      AIPC = GetALocalPlayerController();

      if ( Enemy != none && Enemy.IsAliveAndWell() )
      {

        PawnDistance = Vsize( Enemy.Location - Location );
        `Log( self @Enemy @PawnDistance);

          //if player is close enough to perform knife kill
          if ( PawnDistance &lt; 46 )
          {
            `Log("FINISH HIM");    
            knifekill = true;
            setTimer(0.01, false, 'CheckKnifeKillTrue');
          }

          //if player is out of reach to perform knife kill
          if ( PawnDistance > 46 )
          {
            `Log("YOU ARE NOT IN RANGE FOR KNIFE KILL");          
            knifekill = false;
            setTimer(0.01, false, 'CheckKnifeKillFalse');
          }

      }

    }

}

//here I made these functions to play/stop flash animation outside the tick event
function CheckKnifeKillTrue()
{
  if ( knifekill == true && Enemy.Weapon.Class == class'UTWeap_AIKnife' )
  {
    AIPC.ConsoleCommand("KnifeKillIconAnimStart");
  }
}

function CheckKnifeKillFalse()
{
  if ( knifekill == false)
  {
    AIPC.ConsoleCommand("KnifeKillIconAnimEnd");
  }
}
//here I made these functions to play/stop flash animation outside the tick event

simulated event Tick(float DeltaTime)
{
Super.Tick(1.00);
CheckKnifeKill();
}
//check knife kill function///////////////////////////////////////////////////

On UTGFxHudWrapper:


//function to show knifekill icon animation////////////////////////////////////////////////////
exec function KnifeKillIconAnimStart()
{
  if ( KnifeKillIconHUD == none )
       KnifeKillIconHUD = new(PlayerOwner) class'UTGFxTweenableMoviePlayer';

  KnifeKillIconHUD.MovieInfo = SwfMovie'gameplay_icons.udk_knifekill';
  KnifeKillIconHUD.bDisplayWithHudOff = true;
  KnifeKillIconHUD.bEnableGammaCorrection = false;
  KnifeKillIconHUD.LocalPlayerOwnerIndex = class'Engine'.static.GetEngine().GamePlayers.Find(LocalPlayer(PlayerOwner.Player));
  KnifeKillIconHUD.SetTimingMode(TM_Game);
  KnifeKillIconHUD.Start();
  KnifeKillIconHUD.SetViewScaleMode(SM_NoScale);
  KnifeKillIconHUD.SetAlignment(Align_Center);
  KnifeKillIconHUD.bAutoPlay = true;
  //KnifeKillIconHUD.Advance(0);
}

exec function KnifeKillIconAnimEnd()
{
  KnifeKillIconHUD.Close();
  KnifeKillIconHUD = none;
}
//function to show knifekill icon animation////////////////////////////////////////////////////

I was reading your code and what your doing and had an idea for you to maybe try.
Your var bool knifekill . If you made that a UTPlayerReplication var that replicates to the client. Then all you would have to do is. Check the pri var in the GFxMinimapHud in its function TickHud(float DeltaTime) and in the section if(PBP == None) then check your bool and make a knife kill icon unhide from your main udkhud. Once the pawn is not none, which means he’s back alive again and has a pawn Then set the pri var bak to false to make the icon hide. This would be a way of doing it without having to make a completely new movie and using the existing hud to accomplish it.

Thanks bro for the tip!!!

However now I just need to know why the flash movie swf is not playing the animation, instead, it is stuck on its first frame. The logic of show/hide the hud icon as the player aproaches/gets away from the enemy is working perfectly, just the flash movie itself is not playing it’s animation even though the original swf file works perfectly.

Here is the animation working inside flash: https://drive.google.com/open?id=1pySIEsY-xtiKNGdxLsU6548v7hXE86rM

Here is inside game, I also loaded other flash animation icon for headshot, using the same code of UTGFxHudWrapper, and it plays fine, as you can see in the video:

https://drive.google.com/open?id=1iOR3kEuski2xBdX2vAUxtBTHR6ARmEG2