Announcement

Collapse
No announcement yet.

Make custom weapons useing your own custom meshes

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    Make custom weapons useing your own custom meshes

    I have a model called XM8 Assault Rifle that I would like to replace the stock one with.
    I am not sure where to start or how do you make one?
    Last edited by Mega_Mad_Maxx; 04-05-2018, 01:54 AM.

    #2
    I can't help you, but for starters you can look at theese tutorials (under UnrealScript):
    https://www.3dbuzz.com/training/view...ment-2003-2004
    https://s20.postimg.org/jthlzuavx/M5400x100.png
    CEONSS: http://www.ceonss.net ; ut2004://176.57.143.200:7777 ; https://discord.gg/X4V8THM

    Comment


      #3
      I recommend starting off with a simple duplicate of the AR770 Assault Rifle, but using your weapon mesh instead. You need three "versions" of the mesh: the first person animated skeletal view mesh (w/ or w/o hands, its up to you); the third person skeletal mesh that is lower poly than the first person view mesh (with bones to attach the muzzle flash effect to); and a pickup view version which should be a static mesh if you want to have it visible on weapon lockers (you can also used a rigidized skeletal mesh for the pickup view mesh, but it won't show up on weapon lockers).

      See the files AssaultRifle.uc, AssaultAttachment.uc, AssaultRiflePickup.uc in the xWeapons source code UScript files. You will at a minimum want to make your own version of these three files. You will probably want, and may need, to make your own version of the AssaultFire.uc class if you want to eventually change the damage amount, accuracy, weapon damage type, firing sounds, or the names of the animations.

      Here is a quick list of classes that you usually need for each individual "complete" weapon. Most of these are simple subclasses of the base parent class, but you still pretty much have to have them for every single unique weapon:

      1. Weapon class (this is the actual 'weapon' and its mesh is what gets drawn in first person view)
      2. Weapon Pickup class (this is the thing that is dropped by players you frag, or what shows up on weapon pickup bases)
      3. Weapon Attachment (this is the third person actor that is attached to your pawn's hands in third person view and what you see all of the other players and bots holding)
      4. Primary fire WeaponFire class (this is the "code thing" that contains the functions that actually fires your weapon, does the 'trace' collision check and damages other pawn, or spawns a projectile)
      5. Alternate fire WeaponFire class (same thing as the Primary Fire WeaponFire class, but is used when you altfire your weapon)
      6. Weapon Damage Type class (this is the damage type of your weapon, lists things like momentum, damage scaling for vehicles and ONS Nodes and Power Cores, and whether armor stops this damage or not. It is NOT typically used to lists how much damage is done, that is usually in the WeaponFire class for instant hit weapons, or the projectile class). Sometimes you may want a second damage type for headshots, or the AlternateFire.
      7. Ammo class
      8. Ammo Pickup class (the object actually spawned in the game world that gives you ammo of the Ammo class type)
      9. Projectile class (if your weapon shoots projectiles)

      Other classes you may need or want include:
      10. Muzzle Flash Effect First person view (the muzzle flash particle effect you see in first person view)
      11. Muzzle Flash Effect Third person view (the muzzle flash particle effect you see on everyone else's version of the gun when it is fired, or your own when viewing from third person)
      12. Specialized hit effects class (the particle effect that is made when your weapon, or it's projectile, hits an object like the level geometry or a vehicle etc.)

      Comment


        #4
        Hey Maxx, since you are using the Assault Rifle code for now I thought I'd let you know about my recent experience trying to modify it for better accuracy. The event ModeDoFire() part in your XM8_Fire.uc file is what makes it so inaccurate. I tried to understand that but couldn't and ended up just removing it. This will use the default spread. I actually set mine to have perfect accuracy because I had a specific use in mind for it that would not have mixed in with regular stock weapons. It can actually kill a full health player in about two seconds, iirc. If you are interested in my painful learning and experimentation process with this you can read this thread. Most of it will be irrelevant but there might be something useful in there for you. Especially starting on post 43.

        http://forum.omnipotents.com/showthr...t=14898&page=3

        You might contact cyberhawk about weapons in general as he recently made a new rifle mutator for 2k4. He hasn't been around in a while but if you message him he might help out.

        https://www.epicgames.com/unrealtournament/forums/showthread.php?25084-UT2004-IK-STORM-V1-Weapon-Mutator

        Nice model btw.
        http://i935.photobucket.com/albums/a...psriplu1m9.png

        Comment


          #5
          Hi, Maxx

          if you want to use your own fire mode class, then you need to reference it too (in weapon's script):

          ...currently:
          Code:
               FireModeClass(0)=XWeapons.AssaultFire
          ...should be:
          Code:
               FireModeClass(0)=MegaForce.XM8_Fire
          -----

          BTW, [MENTION=18023]Binger[/MENTION], code from ModeDoFire just responsible for increasing fire cone width (i.e. randomness of individual shots). When you hold your fire button, it firstly allows for 0.5 secs of default (i.e. smallest cone) spread, then spread/cone gradually increases (until reaching pre-defined max value of 0.12). Units are radians (i.e. 1 unit of WeaponFire's spread is about 57 degrees). Also, since AssaultRifle is akimbo-able, its default spread becomes 1.5 times greater for dual guns.
          - got sig? -

          Comment


            #6
            Try NewWeapons2004 for the Assault rifle pickup.

            If you take out that bit of code then it will just use Spread=0.020000, and you can set that to whatever you want. There is also aimerror. Here is a quote from Castiel that explains it better...

            aimerror=800.000000 <--- Controls random deviation from center per shot. 0 = none, 1000 = little center hit. Think Shockrifle, LG, etc.. If you click and one projectile comes out per shot.


            Spread=0.020000 <----- Controls the spread of rotator/multi projectile/beam weapons. 0.0 = no spread, 15000 = my ToePopper weapon. This is used if u have multi projectiles per shot or auto fire such as the flak cannon or rox


            @exo. That's what I thought too but I tried experimenting with different values and it didn't seem to work like that. It's been a while so I will have to re-read what I said. To me it seemed broken and like it wasn't doing what it was intended to do but I don't know much about code so it's likely I just never really understood it.
            http://i935.photobucket.com/albums/a...psriplu1m9.png

            Comment


              #7
              Hi Maxx,
              You set the "staticmesh" property, but the mesh is in your animation package and is a Skeletal mesh. In this case change the StaticMesh line to 'none', change DrawType to DT_Mesh, and then set the Mesh property instead to: Mesh=SkeletalMesh'MegaForce_A.XM8_Pickup'

              ... that should do the trick for that error.

              Also, because the XM8 is based off of the AssaultRifle and is dual-wieldable, you will need to change a few other variable references from 'AssaultAttachment' to 'XM8_Attachment' in both your XM8_Rifle and XM8_Attachment classes (just do a word search in both and make the replacement).


              [EDIT] The UnrealWiki site seems to be back up so here are a few other useful links:
              List of Tutorials
              Basic New Weapon Type
              How UT2003 weapons fire -excellent links to how the code function chain is called on the client and server (UT2004 is almost identical but with a few differences), see the Projectile Fire page for a nice visual picture
              Basic Reloading Weapon code
              Last edited by meowcatbuf; 04-01-2017, 04:12 PM.

              Comment


                #8
                Cool, its always nice to see a new weapon in game.

                Yes, you need to have staticmesh set in the XM8's pickup class in order for it to show up in the WeaponLocker. (you cans still have the XM8_pickup use its skeletal mesh for drawing the pickup, but there must also be a static mesh assigned to it so that the Emitter that the weapon locker spawns can grab the static mesh variable to create the "staticmesh" particle for the weapon locker.)

                In order to swap out the grenade launcher for the sniper zoom you will need to change the WeaponFire(1) default property (you can us the Sniper's AltFire), AND copy/modify the Altfire code from the SniperRifle.

                Comment


                  #9
                  For the pickup class, take a look at how the entries for the staticmesh property in other classes look to see what it should look like (I think it should be something like StaticMesh=StaticMesh'XM8_Pickup.XM8_Pickup') As usual I recommend keeping the package name and asset name different just to keep things "clean".

                  Generally you need to always list the full path to an asset by first listing the package name and then the asset name: MyStaticMeshPackageName.MyStaticmesh

                  You can include the Group name as well in the asset path like this: MyStaticMeshPackageName.MyGroupname.MyStaticmesh
                  but it is not strictly necessary unless you made the choice to import two assets with the same exact name into the package but placed them in different groups.

                  In the case of default properties, depending on the property type, you also need to specify what kind of asset it is, enclosed in single quote ' marks, for example: StaticMesh'MyUPackage.MyStaticMesh' or SkeletalMesh'MyUPackage.MySkeletalMeshName' or material'MyUPackage.MyCoolCustomTexture'

                  For the muzzleFlash, if you look in the XM8_Fire code, you will see the 'InitEffects' function, and in that the code to attach the muzzleFlash effect actor to the bone named 'tip'. If you look at the AR770 AssaultRifle mesh in the editor you will see under the right hand Mesh Tab->Attach->Sockets that there is a socket called 'tip' (AttachAlias) that is based on the sksletalmesh bone 'Bone_Flash'. You should create a similar Bone Attachment in your mesh by following the explanations here.... or just change the bone name from 'tip' to whatever bone name is near the muzzle location. The nice thing about bone attach aliases in that you can offset & rotate them from the bone they are based on, however if you ever try to get the bone coordinates for the AttachAlias, it will return the Coords of the bone the alias is based on NOT the offset location of the Alias.


                  (on a side note, 2270 tris for a pickup mesh is really like 1800 too many, depending on what you are modeling with there are a number of tools that can reduce tris automatically without you having to remake/re-UV the low-tri mesh yourself.... though you will miss out on the satisfaction of making a beautifully optimized low-poly model ;-) Milkshape3D includes a DirectX triangle count auto reducer tool)
                  Last edited by meowcatbuf; 04-03-2017, 09:44 PM.

                  Comment


                    #10
                    In a way I agree, but that depends of the details you put on a weapon mesh.

                    Comment


                      #11
                      Just to recap everything I have been doing to learn how to make weapons.

                      I got some of the AR770 Assault Rifle scripts
                      (Weapon class, Weapon Fire class, Weapon Pickup class and Weapon Attachment class)
                      and renamed them XM8_Rifle.uc, XM8_Fire.uc, XM8_RiflePickup.uc and XM8_Attachment.uc
                      I put these classes in the MF_Weapons/classes folder along with my vehicles.
                      The mesh names are XM8_Anim, XM8_1st, XM8_3rd and XM8_Pickup.

                      Click image for larger version  Name:	XM8_1st.jpg Views:	1 Size:	41.7 KB ID:	397814

                      I extracted the AssaultRifle_1st.psa animation into 3dsmax
                      to get an idea of how it is set up and where the bones are.

                      Click image for larger version  Name:	Schematic-View.jpg Views:	2 Size:	96.1 KB ID:	397815

                      I attach my new XM8 model to the Bone_weapon (root bone if you will)
                      just as a test to see if it moved with the animation.
                      Guess what, it worked!! So now I don't have to re-do all those animations again.

                      Click image for larger version  Name:	where-are-the-bones.jpg Views:	1 Size:	146.8 KB ID:	397813

                      I deleted the old Assault Rifle model (and some bones) and keep the new XM8 model and saved it,
                      then reloaded 3dsmax XM8 model and played back the animations and it still worked.

                      Click image for larger version  Name:	XM8-1-bones.jpg Views:	1 Size:	148.5 KB ID:	397812

                      I was able to compile the XM8 scrips and get it ingame.
                      At this point I discovered a new problem,
                      the muzzle flash seem to stay attached to the weapons locker when I fire?

                      Click image for larger version  Name:	muzzle-flash-problem.jpg Views:	1 Size:	357.4 KB ID:	397811

                      meowcatbuf gave me the answer but, at the time I just couldn't grasp it.

                      Originally posted by meowcatbuf
                      For the pickup class, take a look at how the entries for the staticmesh property in other classes look to see what it should look like (I think it should be something like StaticMesh=StaticMesh'XM8_Pickup.XM8_Pickup.
                      Originally posted by meowcatbuf
                      If you look at the AR770 AssaultRifle mesh in the editor you will see under the right hand Mesh Tab->Attach->Sockets that there is a socket called 'tip' (AttachAlias) that is based on the sksletalmesh bone 'Bone_Flash'.
                      I think I kind of overload my brain with too much new information.
                      I had to walk away from it for a while (put it on the back burner if you will)
                      and let my sub consensus process it all then get back to it later.

                      So, now I am giving it another try.
                      I went to the Sockets and add 'tip' to (AttachAlias) and 'Bone_Flash' to (BoneName)
                      and that fixed the problem.

                      Click image for larger version  Name:	tip-Bone_Flash.jpg Views:	1 Size:	116.6 KB ID:	397810



                      ----------------------------------------------------------------------
                      So now I want to tackle the next problem.

                      How do you make a weapon card show up in the menu at the bottom of the screen?


                      Click image for larger version  Name:	weapon-card.jpg Views:	1 Size:	27.7 KB ID:	397816


                      This is what I have so far:

                      MF_AR_Rifle.uc:
                      Code:
                      /=============================================================================
                      //
                      //=============================================================================
                      class MF_AR_Rifle extends Weapon
                          config(user);
                      
                      var float DualPickupTime;
                      var MF_AR_Attachment OffhandActor;
                      var bool bDualMode;
                      var bool bWasDualMode;
                      var bool bFireLeft;
                      
                      #EXEC OBJ LOAD FILE=InterfaceContent.utx
                      #EXEC OBJ LOAD FILE=MegaForceTX.utx
                      
                      replication
                      {
                          reliable if ( Role == ROLE_Authority )
                              bDualMode;
                      }
                      
                      simulated function Loaded()
                      {
                          bDualMode = true;
                      }
                      
                      simulated function PostNetBeginPlay()
                      {
                          Super.PostNetBeginPlay();
                      
                          if ( (Role < ROLE_Authority) && (Instigator != None)  
                      && (Instigator.Controller != None) && (Instigator.Weapon
                        != self) && (Instigator.PendingWeapon != self) )
                              Instigator.Controller.ClientSwitchToBestWeapon();
                      }
                      
                      
                      simulated function bool WeaponCentered()
                      {
                          return !bDualMode && Super.WeaponCentered();
                      }
                      
                      simulated event RenderOverlays( Canvas Canvas )
                      {
                          local bool bRealHidden;
                          local int RealHand;
                      
                          if (Instigator == None)
                              return;
                      
                          if ( Instigator.Controller != None )
                              Hand = Instigator.Controller.Handedness;
                      
                          if ((Hand < -1.0) || (Hand > 1.0))
                              return;
                      
                          RealHand = Hand;
                          if ( bDualMode && (Hand == 0) )
                          {
                              Instigator.Controller.Handedness = -1;
                              Hand = -1;
                          }
                      
                          if ( bDualMode && (FireMode[1].FlashEmitter != None) )
                          {
                              bRealHidden = FireMode[1].FlashEmitter.bHidden;
                              if ( bFireLeft )
                                  FireMode[1].FlashEmitter.bHidden = true;
                              Super.RenderOverlays(Canvas);
                              FireMode[1].FlashEmitter.bHidden = bRealHidden;
                          }
                          else
                              Super.RenderOverlays(Canvas);
                      
                          if ( bDualMode )
                              RenderDualOverlay(Canvas);
                          if ( Instigator.Controller != None )
                              Instigator.Controller.Handedness = RealHand;
                      }
                      
                      simulated function RenderDualOverlay(Canvas Canvas)
                      {
                          local vector NewScale3D;
                          local rotator WeaponRotation;
                          local bool bRealHidden;
                      
                          Hand *= -1;
                          newScale3D = Default.DrawScale3D;
                          newScale3D.Y *= Hand;
                          SetDrawScale3D(newScale3D);
                          PlayerViewPivot.Roll = Default.PlayerViewPivot.Roll * Hand;
                          PlayerViewPivot.Yaw = Default.PlayerViewPivot.Yaw * Hand;
                          RenderedHand = Hand;
                      
                          if ( class'PlayerController'.Default.bSmallWeapons )
                              PlayerViewOffset = SmallViewOffset;
                          else
                              PlayerViewOffset = Default.PlayerViewOffset;
                      
                          PlayerViewOffset.Y *= Hand;
                      
                          SetLocation( Instigator.Location + Instigator.CalcDrawOffset(self)
                      );
                          WeaponRotation = Instigator.GetViewRotation();
                      
                          if ( bDualMode != bWasDualMode )
                          {
                              bWasDualMode = true;
                              DualPickupTime = Level.Timeseconds;
                          }
                          if ( DualPickupTime > Level.TimeSeconds - 0.5 )
                              WeaponRotation.Pitch = WeaponRotation.Pitch - 16384 - 32768 *
                      (DualPickupTime - Level.TimeSeconds);
                      
                          SetRotation( WeaponRotation );
                      
                          bDrawingFirstPerson = true;
                          if ( bDualMode && (FireMode[1].FlashEmitter != None) )
                          {
                              bRealHidden = FireMode[1].FlashEmitter.bHidden;
                              if ( !bFireLeft )
                                  FireMode[1].FlashEmitter.bHidden = true;
                              Canvas.DrawActor(self, false, false, DisplayFOV);
                              FireMode[1].FlashEmitter.bHidden = bRealHidden;
                          }
                          else
                             Canvas.DrawActor(self, false, false, DisplayFOV);
                          bDrawingFirstPerson = false;
                          Hand *= -1;
                      }
                      
                      simulated function DetachFromPawn(Pawn P)
                      {
                          bFireLeft = false;
                          AssaultGrenade(FireMode[1]).ReturnToIdle();
                          Super.DetachFromPawn(P);
                          if ( OffhandActor != None )
                          {
                              OffhandActor.Destroy();
                              OffhandActor = None;
                          }
                      }
                      
                      function AttachToPawn(Pawn P)
                      {
                          local name BoneName;
                      
                          if ( ThirdPersonActor == None )
                          {
                              ThirdPersonActor = Spawn(AttachmentClass,Owner);
                              InventoryAttachment(ThirdPersonActor).InitFor(self);
                          }
                          BoneName = P.GetWeaponBoneFor(self);
                          if ( BoneName == '' )
                          {
                              ThirdPersonActor.SetLocation(P.Location);
                              ThirdPersonActor.SetBase(P);
                          }
                          else
                              P.AttachToBone(ThirdPersonActor,BoneName);
                      
                          if ( bDualMode )
                          {
                              BoneName = P.GetOffHandBoneFor(self);
                              if ( BoneName == '' )
                                  return;
                              if ( OffhandActor == None )
                              {
                                  OffhandActor = MF_AR_Attachment(Spawn(AttachmentClass,Owner));
                                  OffhandActor.InitFor(self);
                              }
                              P.AttachToBone(OffhandActor,BoneName);
                              if ( OffhandActor.AttachmentBone == '' )
                                  OffhandActor.Destroy();
                              else
                              {
                                  ThirdPersonActor.SetDrawScale(0.3);
                                  OffhandActor.SetDrawScale(0.3);
                                  OffhandActor.bDualGun = true;
                                  OffhandActor.TwinGun = MF_AR_Attachment(ThirdPersonActor);
                                  if ( Mesh == OldMesh )
                                  {
                                      OffhandActor.SetRelativeRotation(rot(0,32768,0));
                                      OffhandActor.SetRelativeLocation(vect(20,-10,-5));
                                  }
                                  else
                                  {
                                      OffhandActor.SetRelativeRotation(rot(0,0,32768));
                                      OffhandActor.SetRelativeLocation(vect(40,-3,-7));
                                  }
                                  MF_AR_Attachment(ThirdPersonActor).TwinGun = OffhandActor;
                              }
                          }
                      }
                      
                      simulated function DrawWeaponInfo(Canvas Canvas)
                      {
                          NewDrawWeaponInfo(Canvas, 0.705*Canvas.ClipY);
                      }
                      
                      simulated function NewDrawWeaponInfo(Canvas Canvas, float YPos)
                      {
                          local int i,Count;
                          local float ScaleFactor;
                      
                          ScaleFactor = 99 * Canvas.ClipX/3200;
                          Canvas.Style = ERenderStyle.STY_Alpha;
                          Canvas.DrawColor = class'HUD'.Default.WhiteColor;
                          Count = Min(8,AmmoAmount(1));
                          for( i=0; i<Count; i++ )
                          {
                              Canvas.SetPos(Canvas.ClipX - (0.5*i+1) * ScaleFactor, YPos);
                              Canvas.DrawTile( Material'HudContent.Generic.HUD', ScaleFactor,
                      ScaleFactor, 174, 259, 46, 45);
                          }
                          if ( AmmoAmount(1) > 8 )
                          {
                              Count = Min(16,AmmoAmount(1));
                              for( i=8; i<Count; i++ )
                              {
                                  Canvas.SetPos(Canvas.ClipX - (0.5*(i-8)+1) * ScaleFactor,
                      YPos - ScaleFactor);
                                  Canvas.DrawTile( Material'HudContent.Generic.HUD',
                      ScaleFactor, ScaleFactor, 174, 259, 46, 45);
                              }
                          }
                      }
                      
                      function byte BestMode()
                      {
                          local Bot B;
                      
                          B = Bot(Instigator.Controller);
                          if ( (B != None) && (B.Enemy != None) )
                          {
                              if ( ((FRand() < 0.1) || !B.EnemyVisible()) &&
                      (AmmoAmount(1) >= FireMode[1].AmmoPerFire) )
                                  return 1;
                          }
                          if ( AmmoAmount(0) >= FireMode[0].AmmoPerFire )
                              return 0;
                          return 1;
                      }
                      
                      simulated function float ChargeBar()
                      {
                          return
                      FMin(1,FireMode[1].HoldTime/AssaultGrenade(FireMode[1]).mHoldClampMax);
                      }
                      
                      function bool HandlePickupQuery( pickup Item )
                      {
                          if ( class == Item.InventoryType )
                          {
                              if ( bDualMode )
                                  return super.HandlePickupQuery(Item);
                              bDualMode = true;
                              if ( Instigator.Weapon == self )
                              {
                                  PlayOwnedSound(SelectSound, SLOT_Interact,,,,, false);
                                  AttachToPawn(Instigator);
                              }
                              if (Level.GRI.WeaponBerserk > 1.0)
                                  CheckSuperBerserk();
                              else
                                  FireMode[0].FireRate = FireMode[0].Default.FireRate *  0.55;
                      
                              FireMode[0].Spread = FireMode[0].Default.Spread * 1.5;
                              if (xPawn(Instigator) != None &&
                      xPawn(Instigator).bBerserk)
                                  StartBerserk();
                      
                              return false;
                          }
                          if ( item.inventorytype == AmmoClass[1] )
                          {
                              if ( (AmmoCharge[1] >= MaxAmmo(1)) && (AmmoCharge[0]
                      >= MaxAmmo(0)) )
                                  return true;
                              item.AnnouncePickup(Pawn(Owner));
                              AddAmmo(50, 0);
                              AddAmmo(Ammo(item).AmmoAmount, 1);
                              item.SetRespawn();
                              return true;
                          }
                      
                          if ( Inventory == None )
                              return false;
                      
                          return Inventory.HandlePickupQuery(Item);
                      }
                      
                      simulated function int MaxAmmo(int mode)
                      {
                          if ( bDualMode )
                              return 2 * FireMode[mode].AmmoClass.Default.MaxAmmo;
                          else
                              return FireMode[mode].AmmoClass.Default.MaxAmmo;
                      }
                      
                      function float GetAIRating()
                      {
                          local Bot B;
                      
                          if ( !bDualMode )
                              return AIRating;
                      
                          B = Bot(Instigator.Controller);
                          if ( (B == None) || (B.Enemy == None) )
                              return AIRating;
                      
                          return (AIRating + 0.0003 * FClamp(1500 - VSize(B.Enemy.Location -
                      Instigator.Location),0,1000));
                      }
                      
                      defaultproperties
                      {
                           FireModeClass(0)=MF_Weapons.MF_AR_Fire
                           FireModeClass(1)=XWeapons.AssaultGrenade
                           PutDownAnim="PutDown"
                           SelectSound=WeaponSounds.AssaultRifle.SwitchToAssaultRifle
                           SelectForce="SwitchToAssaultRifle"
                           AIRating=0.400000
                           CurrentRating=0.400000
                           bShowChargingBar=True
                           OldMesh=SkeletalMesh'Weapons.AssaultRifle_1st'
                           OldPickup="WeaponStaticMesh.AssaultRiflePickup"
                           OldCenteredOffsetY=0.000000
                           OldPlayerViewOffset=(X=-8.000000,Y=5.000000,Z=-6.000000)
                           OldSmallViewOffset=(X=4.000000,Y=11.000000,Z=-12.000000)
                           OldPlayerViewPivot=(Pitch=400)
                           OldCenteredRoll=3000
                           Description="The XM8 is the US armys replacement for the m16."
                           EffectOffset=(X=100.000000,Y=25.000000,Z=-10.000000)
                           DisplayFOV=70.000000
                           Priority=3
                           HudColor=(B=192,G=128)
                           SmallViewOffset=(X=13.000000,Y=12.000000,Z=-10.000000)
                           CenteredOffsetY=-5.000000
                           CenteredRoll=3000
                           CenteredYaw=-1500
                           CustomCrosshair=4
                           CustomCrossHairScale=0.666700
                           CustomCrossHairTextureName="Crosshairs.Hud.Crosshair_Cross5"
                           InventoryGroup=2
                           PickupClass=MF_Weapons.MF_AR_RiflePickup
                           PlayerViewOffset=(X=4.000000,Y=5.500000,Z=-6.000000)
                           PlayerViewPivot=(Pitch=400)
                           BobDamping=1.700000
                           AttachmentClass=MF_Weapons.MF_AR_Attachment
                           IconMaterial=Texture'HUDContent.Generic.HUD'
                           IconCoords=(X1=245,Y1=39,X2=329,Y2=79)
                           ItemName="MegaForce AR Rifle"
                           LightType=LT_Pulse
                           LightEffect=LE_NonIncidence
                           LightHue=30
                           LightSaturation=150
                           LightBrightness=255.000000
                           LightRadius=4.000000
                           LightPeriod=3
                           Mesh=SkeletalMesh'MF_Weapons_A.MF_AR_3rd'
                           DrawScale=0.800000
                           HighDetailOverlay=Combiner'UT2004Weapons.WeaponSpecMap2'
                      }



                      MF_AR_Fire.uc:
                      Code:
                      //=============================================================================
                      //
                      //=============================================================================
                      class MF_AR_Fire extends InstantFire;
                      
                      var float LastFireTime;
                      var float ClickTime;
                      
                      function InitEffects()
                      {
                          Super.InitEffects();
                          if ( FlashEmitter != None )
                              Weapon.AttachToBone(FlashEmitter, 'tip');
                      }
                      
                      function FlashMuzzleFlash()
                      {
                          local rotator r;
                          r.Roll = Rand(65536);
                          Weapon.SetBoneRotation('Bone_Flash', r, 0, 1.f);
                          Super.FlashMuzzleFlash();
                      }
                      
                      simulated function bool AllowFire()
                      {
                          if (Super.AllowFire())
                              return true;
                          else
                          {
                              if ( (PlayerController(Instigator.Controller) != None) && (Level.TimeSeconds > ClickTime) )
                              {
                                  Instigator.PlaySound(Sound'WeaponSounds.P1Reload5');
                                  ClickTime = Level.TimeSeconds + 0.25;
                              }
                              return false;
                          }
                      }
                      
                      function StartBerserk()
                      {
                          DamageMin = default.DamageMin * 1.33;
                          DamageMax = default.DamageMax * 1.33;
                      }
                      
                      function StopBerserk()
                      {
                          DamageMin = default.DamageMin;
                          DamageMax = default.DamageMax;
                      }
                      
                      function StartSuperBerserk()
                      {
                          FireRate = default.FireRate * 1.5/Level.GRI.WeaponBerserk;
                          FireAnimRate = default.FireAnimRate * 0.667 * Level.GRI.WeaponBerserk;
                          DamageMin = default.DamageMin * 1.5;
                          DamageMax = default.DamageMax * 1.5;
                          if (AssaultRifle(Weapon) != None && AssaultRifle(Weapon).bDualMode)
                              FireRate *= 0.55;
                      }
                      
                      defaultproperties
                      {
                           DamageType=XWeapons.DamTypeAssaultBullet
                           DamageMin=7
                           DamageMax=7
                           Momentum=0.000000
                           bPawnRapidFireAnim=True
                           FireLoopAnim=
                           FireEndAnim=
                           FireSound=SoundGroup'WeaponSounds.AssaultRifle.AssaultRifleFire'
                           FireForce="AssaultRifleFire"
                           FireRate=0.160000
                           AmmoClass=XWeapons.AssaultAmmo
                           //just for testing
                           AmmoPerFire=-1
                           ShakeRotMag=(X=50.000000,Y=50.000000,Z=50.000000)
                           ShakeRotRate=(X=10000.000000,Y=10000.000000,Z=10000.000000)
                           ShakeRotTime=2.000000
                           ShakeOffsetMag=(X=1.000000,Y=1.000000,Z=1.000000)
                           ShakeOffsetRate=(X=1000.000000,Y=1000.000000,Z=1000.000000)
                           ShakeOffsetTime=2.000000
                           BotRefireRate=0.990000
                           FlashEmitterClass=XEffects.AssaultMuzFlash1st
                           aimerror=0.000000
                           Spread=0.000000
                           SpreadStyle=SS_Random
                      }



                      MF_AR_Attachment.uc:
                      Code:
                      //=============================================================================
                      //
                      //=============================================================================
                      class MF_AR_Attachment extends xWeaponAttachment;
                      
                      var byte OldSpawnHitCount;
                      var class<xEmitter>     mMuzFlashClass;
                      var xEmitter            mMuzFlash3rd;
                      var xEmitter            mMuzFlash3rdAlt;
                      var bool bDualGun;
                      var MF_AR_Attachment TwinGun;
                      var float AimAlpha;
                      
                      replication
                      {
                          reliable if ( Role == ROLE_Authority )
                              bDualGun, TwinGun;
                      }
                      
                      simulated function Hide(bool NewbHidden)
                      {
                          bHidden = NewbHidden;
                          if ( TwinGun != None )
                              TwinGun.bHidden = bHidden;
                      }
                      
                      simulated function Destroyed()
                      {
                          if ( bDualGun )
                          {
                              if ( Instigator != None )
                              {
                                  Instigator.SetBoneDirection(AttachmentBone, Rotation,, 0,
                      0);
                                  Instigator.SetBoneDirection('lfarm', Rotation,, 0, 0);
                              }
                          }
                          if (mMuzFlash3rd != None)
                              mMuzFlash3rd.Destroy();
                          if (mMuzFlash3rdAlt != None)
                              mMuzFlash3rdAlt.Destroy();
                          Super.Destroyed();
                      }
                      
                      simulated function SetOverlayMaterial( Material mat, float time, bool
                      bOverride )
                      {
                          Super.SetOverlayMaterial(mat, time, bOverride);
                          if ( !bDualGun && (TwinGun != None) )
                              TwinGun.SetOverlayMaterial(mat, time, bOverride);
                      }
                      
                      simulated function Tick(float deltatime)
                      {
                          local rotator newRot;
                      
                          if ( !bDualGun || (Level.NetMode == NM_DedicatedServer) )
                          {
                              Disable('Tick');
                              return;
                          }
                      
                          AimAlpha = AimAlpha * ( 1 - 2*DeltaTime);
                      
                          // point in firing direction
                          if ( Instigator != None )
                          {
                              newRot = Instigator.Rotation;
                              if ( AimAlpha < 0.5 )
                                  newRot.Yaw += 4500 * (1 - 2*AimAlpha);
                              Instigator.SetBoneDirection('lfarm', newRot,, 1.0, 1);
                      
                              newRot.Roll += 32768;
                              Instigator.SetBoneDirection(AttachmentBone, newRot,, 1.0, 1);
                          }
                      }
                      
                      /* UpdateHit
                      - used to update properties so hit effect can be spawn client side
                      */
                      function UpdateHit(Actor HitActor, vector HitLocation, vector HitNormal)
                      {
                          SpawnHitCount++;
                          mHitLocation = HitLocation;
                          mHitActor = HitActor;
                          mHitNormal = HitNormal;
                      }
                      
                      simulated function MakeMuzzleFlash()
                      {
                          local rotator r;
                      
                          AimAlpha = 1;
                          if ( TwinGun != None )
                              TwinGun.AimAlpha = 1;
                          if (mMuzFlash3rd == None)
                          {
                              mMuzFlash3rd = Spawn(mMuzFlashClass);
                              AttachToBone(mMuzFlash3rd, 'tip');
                          }
                          mMuzFlash3rd.mStartParticles++;
                          r.Roll = Rand(65536);
                          SetBoneRotation('Bone_Flash', r, 0, 1.f);
                      }
                      
                      simulated event ThirdPersonEffects()
                      {
                          local rotator r;
                          local PlayerController PC;
                      
                          if ( Level.NetMode != NM_DedicatedServer )
                          {
                              AimAlpha = 1;
                              if ( TwinGun != None )
                                  TwinGun.AimAlpha = 1;
                              if (FiringMode == 0)
                              {
                                  WeaponLight();
                                  if ( OldSpawnHitCount != SpawnHitCount )
                                  {
                                      OldSpawnHitCount = SpawnHitCount;
                                      GetHitInfo();
                                  PC = Level.GetLocalPlayerController();
                                  if ( ((Instigator != None) && (Instigator.Controller
                        == PC)) || (VSize(PC.ViewTarget.Location - mHitLocation) < 4000) )
                      
                      Spawn(class'HitEffect'.static.GetHitEffect(mHitActor, mHitLocation,  
                      mHitNormal),,, mHitLocation, Rotator(mHitNormal));
                                  }
                                  MakeMuzzleFlash();
                                  if ( !bDualGun && (TwinGun != None) )
                                      TwinGun.MakeMuzzleFlash();
                              }
                              else if (FiringMode == 1 && FlashCount > 0)
                              {
                                  WeaponLight();
                                  if (mMuzFlash3rdAlt == None)
                                  {
                                      mMuzFlash3rdAlt = Spawn(mMuzFlashClass);
                                      AttachToBone(mMuzFlash3rdAlt, 'tip2');
                                  }
                                  mMuzFlash3rdAlt.mStartParticles++;
                                  r.Roll = Rand(65536);
                                  SetBoneRotation('Bone_Flash02', r, 0, 1.f);
                              }
                          }
                      
                          Super.ThirdPersonEffects();
                      }
                      
                      defaultproperties
                      {
                           mMuzFlashClass=XEffects.AssaultMuzFlash3rd
                           bRapidFire=True
                           LightType=LT_Pulse
                           LightEffect=LE_NonIncidence
                           LightHue=30
                           LightSaturation=150
                           LightBrightness=255.000000
                           LightRadius=4.000000
                           LightPeriod=3
                           Mesh=SkeletalMesh'MF_Weapons_A.MF_AR_1st'
                           RelativeLocation=(X=-20.000000,Y=-5.000000)
                           RelativeRotation=(Pitch=32768)
                           DrawScale=0.300000
                      }



                      MF_AR_RiflePickup.uc:
                      Code:
                      //=============================================================================
                      //
                      //=============================================================================
                      class MF_AR_RiflePickup extends UTWeaponPickup;
                      
                      defaultproperties
                      {
                           StandUp=(Y=0.250000,Z=0.000000)
                           MaxDesireability=0.400000
                           InventoryType=XWeapons.AssaultRifle
                           PickupMessage="You got the XM8 Rifle."
                           PickupSound=PickupSounds.AssaultRiflePickup
                           PickupForce="AssaultRiflePickup"
                           DrawType=DT_Mesh
                           StaticMesh=StaticMesh'MF_Weapons_SM.MF_AR_Pickup'
                           DrawScale=0.500000
                      }
                      Attached Files
                      Last edited by Mega_Mad_Maxx; 03-13-2018, 06:26 AM.

                      Comment


                        #12
                        Hi Max,
                        In the MF_AR_Rifle.uc class, the following variables control what is drawn for the weapon icon:
                        Code:
                         IconMaterial=Texture'HUDContent.Generic.HUD'
                        IconCoords=(X1=245,Y1=39,X2=329,Y2=79)
                        If you create a 2D texture of the rifle, you can put it in a 128x128 pixel texture, import that into the same file with the rifle skin, and then change the IconMaterial variable to reference your new Icon texture. The IconCoords variable, if I remember correctly, is the upper left and lower right coordinates of the icon (in pixels) inside the IconMaterial texture, to draw on the HUD.

                        I don't *think* that the HUD code scaled the icon texture to fit in the box on the HUD, so the little rifle icon should fit in a similar sized box inside the IconTexture that you make (in other words it should fit inside a 84x40 pixel box (329-245 and 79-39)).
                        Last edited by meowcatbuf; 03-13-2018, 08:33 PM.

                        Comment


                          #13
                          meowcatbuf, I made an image of the Halo AR, I then pasted it in the
                          UT2004 HUD.tga image (where the InventoryGroup=4 coordinates are)
                          and imported the image into the HCE_WeaponsTX.utx file in UnrealEd.

                          Click image for larger version

Name:	HUD.jpg
Views:	1
Size:	60.1 KB
ID:	397860

                          In the HCE_Assault_Rifle Script I pasted in this code.
                          Code:
                               IconMaterial=Texture'HCE_WeaponsTX.Assault_Rifle.HUD'
                               IconCoords=(X1=250,Y1=110,X2=330,Y2=145)
                          It works in game of course, but I have a lot of guns I want to make icons for.
                          The HUD takes up texture space that is not being used.

                          I thought, their is got to be a better way.
                          So tried something different. meowcatbuf,You said that the
                          "upper left and lower right coordinates of the icon (in pixels)"
                          are used to draw on the HUD. So I made an image/icon (128x128 pixel texture)
                          of the rifle by it's self (if you know what I mean) with the icon coordinates
                          at (X1=0,Y1=0,X2=128,Y2=64) it should work thin, right?

                          Well, the image over laps no matter what changes in the coordinates I make.

                          Click image for larger version

Name:	Icon-1.jpg
Views:	1
Size:	15.6 KB
ID:	397861

                          So I decided to make the position changes with the image instead.

                          Click image for larger version

Name:	Test_XM8_Rifle_Icon.jpg
Views:	1
Size:	2.2 KB
ID:	397862

                          I made a 32 pixel buffer zone around the rifle image and then I kept
                          re-positioning the rifle image and testing it in game until it was perfect.

                          Click image for larger version

Name:	Icon-2.jpg
Views:	1
Size:	15.2 KB
ID:	397863

                          So my hope is that this experience can help other with similar problems.
                          Last edited by Mega_Mad_Maxx; 03-15-2018, 04:13 AM.

                          Comment


                            #14
                            That Icon looks nice Max! And yeah, that is what I meant you could do, by making your own small texture and then putting your icon in it. Here is the first of two weapon icon texture maps I'd made for my YARM mod weapon/player pack many years ago. Each weapon fit inside and approximately 80 wide x 40 tall pixel box, and then in each weapon class I set the individual coordinates. NOTE: When you import your texture into UEd make sure to set its LODSET variable to LODSET_Interface (for textures that are drawn on the HUD or in Menus), that way it won't use lower resolution mipmaps when you change the game texture detail settings.

                            Click image for larger version

Name:	AllIcons_Rev2.jpg
Views:	1
Size:	48.6 KB
ID:	397884

                            Comment


                              #15
                              hey meowcatbuf,
                              Wow 50+ weapons, I like all the weapons you made (modern warfare like).
                              I didn't know you could have grenades as well as swords weapons in ut2004.
                              Was it any more difficult making melee weapons than other weapons (special scripts)?

                              Comment

                              Working...
                              X