[Tutorial] Using custom models
#1

Introduction

This is my first tutorial completely written in English, so please forgive me the possible mistakes I could make.
Some persons should really learn how to use the SAMP’s “custom” function, but I didn’t find a nice tutorial about that yet, this is why I write this one.
It will be organized in two “main” parts : theory and practice. The “theory” part will explain you what the custom is and how to use it through an exercise which consists in adding an additionnal revolver weapon on the desert eagle model, and the “practice” part will give you a corrected to remove you any excuse you can find to not knowing how to use the custom. It will mainly refer to the “theory” part. Before beginning, I’d like to thank Wallegi who learnt me how to use the custom. His tutorial is in French, but don’t worry : I won’t copy & paste it with just a translation, I’ll do a completely new one from scratch.

Also, to learn in the best conditions, I’ll strongly recommend you to download this archive
Here we go !

Theory
Concretely, the “custom” function was added in SAMP 0.3 (I think) and allows a developer to add models downloaded from Internet or created from scratch as a default-samp object. What’s the point of doing that ? It could be useful for adding objects in Roleplay servers such as credit cards, additional weapons, etc. This functions has just a huge defect : the client must have the custom.img & custom.ide the server uses, either he will see nothing or a “?” mark. So if you wanna use this for your own server, make sure the client has the good files.

I personally don’t have any skill of any sort in modding, so I use to download the mods from Internet then telling they aren’t from me, but if you can make mods by yourself, then do. It’s better to have the exact thing we want. To install mods, you just have to use Spark, IMG Tool, IMG Editor or another tool which can open .img file, edit them and save. You’ll also need a text editor, the default notepad from Windows will make the job.

So first, get a mod. I’ll personally install the revolver mod that I’ll show you in the first exercise of the “Practice” part. So…You must have a .dff and a .txd file. If you don’t have, simply change of mod. Open your IMG editor (I use Spark), then click “Open”, and browse to your GTA Folder, in the SAMP sub-folder. Double click on “SAMP.img” to open it. You should see this :


Search for the files “MapMakers.txd” and “MapMarkerNew1.dff”. Export both on your desktop, you should have something like this.


Save (copy) the two files somewhere (I created a folder called invisible models, if you haven’t understood yet, you’ll see in a few) you can use them quite easily (to add more models easily).

Now, go back on your IMG Editor, and go to the models folder of your game, search for “gta3.img” and open it. Once opened, you should see this :



Extract the files desert_eagle.dff and desert_eagle.txd from the gta3.img file and put them on your desktop. Rename them to deagle.dff and deagle.txd.
Then rename the “invisible model” (I put invisible between quotes because the model isn’t really invisible, but you must wanna see the model to see it) files (MapMarkers.txd & MapMarkerNew1.dff) to desert_eagle.dff & desert_eagle.txd. You should see this (with the models file of the revolver added)



Go back to your IMG Editor, in your SAMP folder, and open the custom.img file. It should have a noModelFile.txd inside : just delete it. Add all the model files on your desktop (the six) in the custom.img and click save.



Now go on your game folder and search for the file called custom.ide, which is here (I have set Spark by default for .img files and wordpad by default for .ide files, but if you haven’t set anything, you should see blank icons)



So double click on it, and if it asks for a default program for the file, use your favorite text editor (I use WordPad which is less good looking than Word 2010, but it loads faster) as default program.
So the file is opened. It should be blank. If there something inside, simply delete.

Add exactly this code in the file, then save.

Код:
objs
14077, revolver, revolver, 299, 0
16969, deagle, deagle, 299, 0
end
I’ll (of course) explain a bit here.

objs stands for “objects”, it declares the beginning of the “object” block
14077 is an unused SAMP object ID (which gives a question mark if used in game directly)
revolver (the first) is the name of the txd file of the model to assign to the unused object id. Must be the same as the one you’ve set in the custom.img file
revolver (the second) is the name of the .dff file and do the same as above but with a model
for the “299, 0”, I don’t know what they do but everybody use to put that and it works, so if someone knows, it will be helpful for everyone to know about that.

Your text file should look like this



But why did you tell me to create a deagle file ? The deagle is by default in GTA !

If you noticed it, this is good. I also told you to replace the desert_eagle.dff and desert_eagle.txd models to invisible model files. So you can’t give the desert eagle with the weapon id 24 anymore, else it will give a blank gun. I’ll explain you how to do below. But just remember that deagle.dff and deagle.txd are the “replacements” for desert_eagle.dff and desert_eagle.txd.

Now, let’s go in the script !

As I told above, you can’t give the usual desert eagle with the usual GivePlayerWeapon function.
To do, you must do like that

PHP код:

#include <a_samp>
#include <zcmd>
#define SCM SendClientMessage
CMD:deagle(playeridparams[])
{
    if(
GetLowestID(playerid) == -1) return SCM(playerid, -1"You have too many things on you to carry a weapon !");
    
GivePlayerWeapon(playerid24999);
    
SetPlayerAttachedObject(playeridGetLowestID(playerid), 16969RIGHT_HAND);
    return 
SCM(playerid, -1"You got a desert eagle with 999 ammo !");
}
GetLowestID(playerid)
{
    for(new 
010i++)
    {
        if(!
IsPlayerAttachedObjectSlotUsed(playeridi)) return i;
    }
    return -
1;

And for the revolver, the same but with a replacement to the modelid (should be 14077).
It can be simplificated ! Just create a macro for GivePlayerWeapon but with an additional parameter called “revolver” and set it to false by default.

So it would look like this

PHP код:

#include <a_samp>
#include <zcmd>
#define SCM SendClientMessage
#define GivePlayerWeapon S_GivePlayerWeapon
CMD:deagle(playeridparams[])
{
    if(
GetLowestID(playerid) == -1) return SCM(playerid, -1"You have too many things on you to carry a weapon !");
    
GivePlayerWeapon(playerid24999);
    return 
SCM(playerid, -1"You got a desert eagle with 999 ammo !");
}
CMD:revolver(playeridparams[])
{
    
GivePlayerWeapon(playerid24999true);
    return 
SCM(playerid, -1"You got a revolver with 999 ammo !");
}
stock S_GivePlayerWeapon(playeridweaponidammobool:revolver false)
{
    if(
weaponid == 24)
    {
        if(
GetLowestID(playerid) == -1) return SCM(playerid, -1"You have too many things on you to carry a weapon !");
        if(
revolverSetPlayerAttachedObject(playeridGetLowestID(playerid), 16969RIGHT_HAND);
        else 
SetPlayerAttachedObject(playeridGetLowestID(playerid), 14077RIGHT_HAND)
    }
    
GivePlayerWeapon(playeridweaponidammo);
    return 
1;
}
GetLowestID(playerid)
{
    for(new 
010i++)
    {
        if(!
IsPlayerAttachedObjectSlotUsed(playeridi)) return i;
    }
    return -
1;

But a revolver has only six bullets per magazine, so we must set this in the script ! And when a player changes of weapon, the model will stay and it will look ugly ! Also, when the player set the deagle in his hand, it will display anything !
Also (thanks to Riddick94), we must ensure the player can't use more or less ammo than the weapon's magazine capacity.

PHP код:
new bool:revEquipped[MAX_PLAYERS char] = false;
new 
shots[MAX_PLAYERS char] , oldw[MAX_PLAYERS char];
new 
slot[2 char] = {-1, -1};
public 
OnPlayerWeaponShot(playeridweaponidhittypehitidFloat:fXFloat:fYFloat:fZ)
{
      if(
revEquipped{playerid} && ++shots{playerid} == 6)  // Checking if it's the sixth shot after the last reload
      

            
SetPlayerArmedWeapon(playerid0); // We set the armed weapon of the player to 0
            
SetPlayerArmedWeapon(playerid24); // We set the armed weapon to the revolver back, means the ammo was reloaded
            
ApplyAnimation(playerid"PYTHON""python_reload"4.100001); // We apply the reloading animation
            
shots{playerid} = 0// We reset the "shot" counter
      
}
      return 
1;
}
public 
OnPlayerUpdate(playerid)
{
      new 
neww GetPlayerWeapon(playerid);
      if(
neww != oldw[playerid])
      {
            if(
oldw{playerid} == 24)
            {
                  if(
revEquipped{playerid}) RemovePlayerAttachedObject(playeridslot{0});
                  else 
RemovePlayerAttachedObject(playeridslot{1});
            }
            if(
neww == 24)
            {
                  if(
revEquipped{playerid}) SetPlayerAttachedObject(playeridGetLowestID(playerid), 16969RIGHT_HAND);
                  else 
SetPlayerAttachedObject(playeridGetLowestID(playerid), 14077RIGHT_HAND);
            }
      }
      
oldw{playerid} = neww;
      return 
1;

Which will give at final code

PHP код:
#include <a_samp>
#include <zcmd>
#define SCM SendClientMessage
#define RIGHT_HAND 6
new bool:revEquipped[MAX_PLAYERS char] = false;
new 
shots[MAX_PLAYERS char], oldw[MAX_PLAYERS char];
new 
slot[2 char] = {-1, -1};
CMD:deagle(playeridparams[])
{
      if(
GetLowestID(playerid) == -1) return SCM(playerid, -1"You have too many things on you to carry a weapon !");
      
GivePlayerWeapon(playerid24999);
      return 
SCM(playerid, -1"You got a desert eagle with 999 ammo !");
}
CMD:revolver(playeridparams[])
{
      if(
GetLowestID(playerid) == -1) return SCM(playerid, -1"You have too many things on you to carry a weapon !");
      
GivePlayerWeapon(playerid24999true);
      
revEquipped{playerid} = true;
      return 
SCM(playerid, -1"You got a revolver with 999 ammo !");
}
public 
OnPlayerWeaponShot(playeridweaponidhittypehitidFloat:fXFloat:fYFloat:fZ)
{
      if(
revEquipped{playerid} && ++shots{playerid} == && weaponid == 24)  // Checking if it's the sixth shot after the last reload
      

            
SetPlayerArmedWeapon(playerid0); // We set the armed weapon of the player to 0
            
SetPlayerArmedWeapon(playerid24); // We set the armed weapon to the revolver back, means the ammo was reloaded
            
ApplyAnimation(playerid"PYTHON""python_reload"4.100001); // We apply the reloading animation
            
shots{playerid} = 0// We reset the "shot" counter
      
}
      return 
1;
}
public 
OnPlayerUpdate(playerid)
{
      new 
neww GetPlayerWeapon(playerid);
      if(
neww != oldw[playerid])
      {
            if(
oldw{playerid} == 24)
            {
                  if(
revEquipped{playerid}) RemovePlayerAttachedObject(playeridslot{0});
                  else 
RemovePlayerAttachedObject(playeridslot{1});
            }
            if(
neww == 24)
            {
                  if(
revEquipped{playerid}) SetPlayerAttachedObject(playeridGetLowestID(playerid), 16969RIGHT_HAND);
                  else 
SetPlayerAttachedObject(playeridGetLowestID(playerid), 14077RIGHT_HAND);
            }
      }
      
oldw{playerid} = neww;
      return 
1;
}
stock S_GivePlayerWeapon(playeridweaponidammobool:revolver false)
{
      if(
weaponid == 24)
      {
            if(
GetLowestID(playerid) == -1) return SCM(playerid, -1"You have too many things on you to carry a weapon !");
            if(
revolver)
            {
                  
slot{0} = GetLowestID(playerid);
                  
SetPlayerAttachedObject(playeridGetLowestID(playerid), 16969RIGHT_HAND);
            }
            else
            {
                  
slot{1} = GetLowestID(playerid);
                  
SetPlayerAttachedObject(playeridGetLowestID(playerid), 14077RIGHT_HAND);
            }
      }
      
GivePlayerWeapon(playeridweaponidammo);
      return 
1;
}
#if defined _ALS_GivePlayerWeapon
      #undef GivePlayerWeapon
#else
      #define _ALS_GivePlayerWeapon
#endif
#define GivePlayerWeapon S_GivePlayerWeapon
stock GetLowestID(playerid)
{
      for(new 
010i++)
      {
            if(!
IsPlayerAttachedObjectSlotUsed(playeridi)) return i;
      }
      return -
1;

The object may not be really good placed on the player, but I don’t remember the exact offsets for the revolver. I think if the player has the default skins of GTA, it will be correct, but I don’t care at all.
Well, the theorical part is over. Now, let’s have a look on the exercices !

Practice

Exercise - Adding a 40 shots ACR machinegun

Well, that’s an exercice which takes the exactly the same base as above, but with a new model, so a new weapon. It will check if you’ve correctly learnt. Open the “Exercise” folder from the downloaded archive. You should have acr.dff and acr.txd. All you have to do is to add the ACR based on the M4 model, but you must keep the original M4 ! Add also two commands : /m4 and /acr
Code, code, and code. Don’t scroll down unless you want to spoil the solution to yourself.
Get ready ? Go !





























My code is :

• The custom.ide file :

Код:
objs
12034, om4, om4, 299, 0
15222, acr, acr, 299, 0
end
• The script

PHP код:
#include <a_samp>
#include <zcmd>
#define SCM SendClientMessage
#define RIGHT_HAND 6
new bool:acrEquipped[MAX_PLAYERS char] = false;
new 
shots[MAX_PLAYERS char], oldw[MAX_PLAYERS char], bool:crouched[MAX_PLAYERS char];
new 
slot[2 char] = {-1, -1};
CMD:m4(playeridparams[])
{
      if(
GetLowestID(playerid) == -1) return SCM(playerid, -1"You have too many things on you to carry a heavy weapon !");
      
GivePlayerWeapon(playerid31999);
      return 
SCM(playerid, -1"You got a M4 with 999 ammo !");
}
CMD:acr(playeridparams[])
{
      if(
GetLowestID(playerid) == -1) return SCM(playerid, -1"You have too many things on you to carry a heavy weapon !");
      
GivePlayerWeapon(playerid31999true);
      
acrEquipped{playerid} = true;
      return 
SCM(playerid, -1"You got an ACR with 999 ammo !");
}
public 
OnPlayerKeyStateChange(playeridnewkeysoldkeys)
{
      if( (
PRESSED(KEY_CROUCH)) && (!crouched{playerid}) ) crouched{playerid} = true;
      if( (
PRESSED(KEY_CROUCH)) && ( crouched{playerid}) ) crouched{playerid} = false;
      return 
1;
}
public 
OnPlayerWeaponShot(playeridweaponidhittypehitidFloat:fXFloat:fYFloat:fZ)
{
      if(
acrEquipped{playerid} && ++shots{playerid} == 40 && weaponid == 31)
      {
            
SetPlayerArmedWeapon(playerid0); 
            
SetPlayerArmedWeapon(playerid31);
            if(!
crouched{playerid}) ApplyAnimation(playerid"COLT""colt45_reload"4.100001);
            else 
ApplyAnimation(playerid"COLT""colt45_crouchreload"4.100001);
            
shots{playerid} = 0// We reset the "shot" counter
      
}
      return 
1;
}
public 
OnPlayerUpdate(playerid)
{
      new 
neww GetPlayerWeapon(playerid);
      if(
neww != oldw{playerid})
      {
            if(
oldw{playerid} == 31)
            {
                  if(
acrEquipped{playerid}) RemovePlayerAttachedObject(playeridslot{0});
                  else 
RemovePlayerAttachedObject(playeridslot{1});
            }
            if(
neww == 31)
            {
                  if(
acrEquipped{playerid}) SetPlayerAttachedObject(playeridGetLowestID(playerid), 15222RIGHT_HAND);
                  else 
SetPlayerAttachedObject(playeridGetLowestID(playerid), 12034RIGHT_HAND);
            }
      }
      
oldw{playerid} = neww;
      return 
1;
}
stock S_GivePlayerWeapon(playeridweaponidammobool:acr false)
{
      if(
weaponid == 31)
      {
            if(
acr)
            {
                  
slot{0} = GetLowestID(playerid);
                  
SetPlayerAttachedObject(playeridGetLowestID(playerid), 15222RIGHT_HAND);
            }
            else
            {
                  
slot{1} = GetLowestID(playerid);
                  
SetPlayerAttachedObject(playeridGetLowestID(playerid), 12034RIGHT_HAND);
            }
      }
      
GivePlayerWeapon(playeridweaponidammo);
      return 
1;
}
#if defined _ALS_GivePlayerWeapon
      #undef GivePlayerWeapon
#else
      #define _ALS_GivePlayerWeapon
#endif
#define GivePlayerWeapon S_GivePlayerWeapon
stock GetLowestID(playerid)
{
      for(new 
010i++)
      {
            if(!
IsPlayerAttachedObjectSlotUsed(playeridi)) return i;
      }
      return -
1;

The only “bonus” thing is that the M4 reloads differently according to your crouching state. Because “IsPlayerCrouched” doesn’t exist, we have to use a Boolean var to store the crouched state of the player, and according the reload animation to this state.

Easy isn’t it ?

If you have understood everything, so you can use the custom in SAMP without any difficult !
Before the end of this tutorial, I’d like to thank :
• The Deutsh community, for the object previewer, which helped me to find the unused object id
• Zeex : ZCMD
• Riddick94 : Pointing me out a mistake I've done about reloading (Checking animation)
• OpenClassRooms : The "question" picture (just before the italic text)
• GTRP (FR) community : USD Pack v2 (revolver model)
• GTAInside : ACR Gun
• SA-MP Wiki : HOLDING & PRESSED pre-processor definitions
• SA-MP Team : Custom.img function/a_samp include
• Skillbrain corp : Lightshot tool
• Unknown : Spark


And that’s over ! If you have anything to say about this tutorial, just leave a comment. If you have any question, also leave a comment or send me a private message.
If I have forgotten something, I’m sorry : I have written the tutorial on Word so I don’t really know how it will display until I’ll post. Just tell me.
Reply
#2

http://www.comicsanscriminal.com/

Reading it now.
Reply
#3

And which font do you recommand ?
Reply
#4

Quote:
Originally Posted by S4t3K
Посмотреть сообщение
And which font do you recommand ?
Default one or any other which are like Arial.
Reply
#5

Done, thanks both for your advices.
Reply
#6

Good tutorial S4t3K, since as you had said English is not your first language, you made it very clear. Only grammar in your code; "You have so much things on you to carry a weapon !" should read "You have too many items to carry this weapon !" otherwise this is also good.

+REP
Reply
#7

Thanks, I'll edit right now.
Reply
#8

Thanks for this tutorial.
I've a problem with this, I tried your custom files, but in game I got this error "Warning(opcode 0x107): Exception 0xC0000005 at 0x59F8B4"
Reply
#9

Means that either you've bad installed the file or your computer doesn't support the skin models (too old, overloaded CPU, so many reasons).

I can't translate you the OpCode because I simply don't understand (yet) them. I ask someone who understand them to answer you better than I did.
Reply
#10

What if I am having revolver equipped and I am spamming my LMB button to shoot? My array will be 6, but I will still have some bullets in my capacity, right?

Check of the animation would be good, to avoid that.
Reply
#11

Well, true.

I'll correct it right now. But how to check for the shooting animation because it's applied each time a shot is fired, and we actually can't know when a shot is fired using pawn, can't we ?

EDIT : Finally done.
Reply
#12

Nice Tutorial
Reply
#13

Quote:
Originally Posted by S4t3K
View Post
Well, true.

I'll correct it right now. But how to check for the shooting animation because it's applied each time a shot is fired, and we actually can't know when a shot is fired using pawn, can't we ?

EDIT : Finally done.
The weapon is actually Deagle, isn't it? (Tip: OnPlayerWeaponShot). Or just check animation index (shooting deagle) and check if player pressed LMB and his animation index was shooting from deagle. That's it.
Reply
#14

I did another thing instead.

The animation is applied even when the player shots, that's why we can bug ourselves when we know what we do.
So I checked the animation just before the shots checking.
Reply
#15

thankss you very much
Reply
#16

edit: nvm.
Reply
#17

Thanks it work
Reply
#18

i tried ACR Machin but when use the CMD i get this :

Code:
[13:51:37] Warning(opcode 0x107): Exception 0xC0000005 at 0x59F8B4
and also it says Server Unknown Command
and... i can't create an object with them again Exception 0xC0000005

any idea ?
Reply
#19

is this valid?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)