How to make 3D characters workI'm going to explain how to make the characters work properly. Read carefully.
Optional: before we download the files, it's recommended to move the VanBuren3D files that are located in the folders data/art/critters and data/textures into a zip file.
This zip file needs to have the same structure as the data folder. That means you need to have on the file's root a folder named textures, and another one named art, and inside art the folder critters. When we have that file, we can clear those two folders, and place the zip in the client folder. Once the zip is there, we edit the file named DataFiles.cfg, which is located in the same folder, and add a line to it with the name of our zip file.Getting the filesFirst we download the files from the repository with a subversion (svn) client, like TortoiseSVN and we set it to download into client/data folder.
With this URL
http://svn3.xp-dev.com/svn/FOnline3d/trunk/data/If everything goes right, the files should download into data/textures and data/art/critters
Now we edit some game files.
Note: always backup the files you edit. And it is recommended that you test the game after you edit each code inside the scripts.
Enabling the characters.Once the downloaded files are in the right folders, we need to set them up in the server.
To enable the 3D characters go to the folder server/data/scripts and edit _defines.fos and uncomment this line by erasing those two slashes (//)
//#define PLAYERS_3D // Enable 3d players
(Change To)
#define PLAYERS_3D // Enable 3d players
Test. Now the character creation should be 3D. Always erase the cache before you test any change in the scripts.
Setting the new bodytypes.Next, in the file server/data/CritterTypes.cfg we set up the new body types, replacing the default 3D characters.
Find critter ID 292 (@ 292 in the file)
We'll modify number 292, 293, 295, and 296
Change their names (default name "VBMaleStrong") to these:
292 FOMaleStrong
293 FOMaleStrong_Death
295 FoFemaleNormal
296 FoFemaleNormal_Death
Optional: you can set a new number if you want to keep the old 3D models. But be careful with some scripts that use those numbers.Test. In the character creation, one of the bodytypes should be the new 3D character. If you can't pick the bodytype from the character creation, select a default body and play. Then inside a map, run the command ~run debug body 0 292 1
and the character should render.
Setting up the armorsNext is to set up the armors. To do this, open the file scripts/Client_main.fos, search for the line "void animation3d_process", scroll down until you see
"switch(armorPid)"
Note: Be careful with this, because there is another line that says "/*switch(armorPid)". That's not the oneSelect from "switch(armorPid) to the last time the string "break;" appears (right before // Backpack) and paste this code
switch(armorPid)
{
case PID_LEATHER_JACKET:
bodyAtr = 1;
handsAtr = 1;
break;
case PID_POWERED_ARMOR:
case PID_HARDENED_POWER_ARMOR:
bodyAtr = 6;
feetAtr = 6;
break;
case PID_TIBBETS_PRISON:
bodyAtr = 0;
break;
case PID_JUMPSUIT:
case PID_FAKE_JUMPSUIT:
case PID_VAULT_SUIT:
bodyAtr = 0;
break;
case PID_LEATHER_ARMOR:
bodyAtr = 8;
handsAtr = 8;
break;
case PID_LEATHER_ARMOR_MK_II:
bodyAtr = 20;
handsAtr = 20;
break;
case PID_CURED_LEATHER_ARMOR:
bodyAtr = 10;
handsAtr = 10;
break;
case PID_METAL_ARMOR:
bodyAtr = 2;
handsAtr = 2;
break;
case PID_METAL_ARMOR_MK_II:
bodyAtr = 3;
handsAtr = 2;
break;
case PID_TESLA_ARMOR:
bodyAtr = 19;
handsAtr = 16;
break;
case 600:
bodyAtr = 7;
handsAtr = 7;
break;
case PID_COMBAT_ARMOR:
bodyAtr = 5;
handsAtr = 5;
backpackAtr = 3;
break;
case PID_COMBAT_ARMOR_MK_II:
bodyAtr = 14;
handsAtr = 5;
backpackAtr = 3;
break;
case PID_BROTHERHOOD_COMBAT_ARMOR:
bodyAtr = 15;
handsAtr = 5;
backpackAtr = 3;
break;
case PID_BLACK_COMBAT_ARMOR:
bodyAtr = 16;
handsAtr = 16;
backpackAtr = 3;
break;
case PID_ADVANCED_POWER_ARMOR:
case PID_ADVANCED_POWER_ARMOR_MK2:
bodyAtr = 9;
feetAtr = 9;
break;
case PID_PURPLE_ROBE:
bodyAtr = 11;
break;
case PID_KEEPBRIGE_ROBE:
bodyAtr = ATTRIBUTE_Body_PrisonSuit;
feetAtr = ATTRIBUTE_Feet_PrisonSuit;
headAtr = ATTRIBUTE_Head_StrawHat;
break;
case PID_BLACK_ROBE:
bodyAtr = ATTRIBUTE_Body_PrisonSuit;
feetAtr = ATTRIBUTE_Feet_PrisonSuit;
headAtr = ATTRIBUTE_Head_ArmingCap;
break;
default:
break;
IMPORTANT be careful not to erase the closing bracket after "break;" "}"Test. Use different armors.
Additional Info:
Inside that code, the name of the attributes don't match the ones I used. This is what they actually are:
# rhandleAtr = Right Hand
# lhandleAtr = Unactive Slot/Holstered weapons
# handsAtr = Armor Clothing Layer
# bodyAtr = Armor Layer
# feetAtr = Headwear Layer
# headAtr = Unused/Free
# eyeAtr = Eyewear (nothing available yet)
# shoulderAtr = Custom Pants
# backAtr = Custom Shoes
# backpackAtr = BackpackSetting up the weaponsStill inside client_main scroll down and find "int GetHandleValue(uint16 pid)"
select from ther to the last bracket (}), right before "#endif" and paste this:
int GetHandleValue(uint16 pid)
{
if(pid == 0 || (pid >= 1000 && pid <=1100)) return 0;
int handle = 0;
return int(pid);
}
Test. Try different weapons (or items)
Making the Death animations work.First, find in client_main a line that says "case ACTION_DEAD:"
Select from that line to the last "break;", right before "case ACTION_CONNECT", and paste this.
case ACTION_DEAD:
if( not cr.IsDead() && not cr.IsAnim3d())
{
cr.ClearAnim();
cr.Animate( 0, actionExt );
Message("DEBUG NOTE: 2D critter died. No bodytype switched", FOMB_GAME );
}
else if( cr.IsAnim3d())
{
switch( actionExt )
{
case ANIM2_DEAD_FRONT:
cr.ClearAnim();
cr.Animate( 0, actionExt );
Message("DEBUG NOTE: 3D critter died on DEAD_FRONT. No special anim, so bodytype has not changed", FOMB_GAME );
break;
case ANIM2_DEAD_BACK :
cr.ClearAnim();
cr.Animate( 0, actionExt );
Message("DEBUG NOTE: 3D critter died on DEAD_BACK. No special anim, so bodytype has not changed", FOMB_GAME );
break;
case ANIM2_DEAD_BLOODY_SINGLE:
cr.ClearAnim();
if (cr.Stat[ST_GENDER] == 0)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),293,110,null,null);
PlaySound("HMXXXXBD.ACM");
}
else if (cr.Stat[ST_GENDER] == 1)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),296,110,null,null);
PlaySound("HFXXXXBD.ACM");
}
Message("DEBUG NOTE: 3D critter died on BLOODY_SINGLE. Bodytype switched to dead model", FOMB_GAME );
break;
case ANIM2_DEAD_BLOODY_BURST:
cr.ClearAnim();
if (cr.Stat[ST_GENDER] == 0)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),293,111,null,null);
PlaySound("HMXXXXBF.ACM");
}
else if (cr.Stat[ST_GENDER] == 1)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),296,111,null,null);
PlaySound("HFXXXXBF.ACM");
}
Message("DEBUG NOTE: 3D critter died on BLOODY_BURST. Bodytype switched to dead model", FOMB_GAME );
break;
case ANIM2_DEAD_BURST:
cr.ClearAnim();
if (cr.Stat[ST_GENDER] == 0)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),293,112,null,null);
PlaySound("HMXXXXBG.ACM");
}
else if (cr.Stat[ST_GENDER] == 1)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),296,112,null,null);
PlaySound("HFXXXXBG.ACM");
}
Message("DEBUG NOTE: 3D critter died on BURST. Bodytype switched to dead model", FOMB_GAME );
break;
case ANIM2_DEAD_LASER:
cr.ClearAnim();
if (cr.Stat[ST_GENDER] == 0)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),293,115,null,null);
PlaySound("HMXXXXBI.ACM");
}
else if (cr.Stat[ST_GENDER] == 1)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),296,115,null,null);
PlaySound("HFXXXXBI.ACM");
}
Message("DEBUG NOTE: 3D critter died on LASER. Bodytype switched to dead model", FOMB_GAME );
break;
case ANIM2_DEAD_FUSED:
cr.ClearAnim();
if (cr.Stat[ST_GENDER] == 0)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),293,116,null,null);
PlaySound("HMXXXXBM.ACM");
}
else if (cr.Stat[ST_GENDER] == 1)
{
RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),296,116,null,null);
PlaySound("HFXXXXBM.ACM");
}
Message("DEBUG NOTE: 3D critter died on FUSED (plasma). Bodytype switched to dead model", FOMB_GAME );
break;
case ANIM2_DEAD_PRONE_FRONT :
cr.ClearAnim();
cr.Animate( 0, actionExt );
Message("DEBUG NOTE: 3D critter died on PRONE_FRONT. No bodytype switch needed", FOMB_GAME );
break;
case ANIM2_DEAD_PRONE_BACK:
cr.ClearAnim();
cr.Animate( 0, actionExt );
Message("DEBUG NOTE: 3D critter died on PRONE_BACK. No bodytype switch needed", FOMB_GAME );
break;
case ANIM2_DEAD_PULSE:
cr.ClearAnim();
if (cr.Stat[ST_GENDER] == 0) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),11,113,null,null);
if (cr.Stat[ST_GENDER] == 1) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),5,113,null,null);
Message("DEBUG NOTE: 3D critter died on PULSE. No 3d anim available. Needs switch to 2d and play anim again", FOMB_GAME );
break;
case ANIM2_DEAD_PULSE_DUST :
cr.ClearAnim();
if (cr.Stat[ST_GENDER] == 0) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),11,114,null,null);
if (cr.Stat[ST_GENDER] == 1) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),5,114,null,null);
Message("DEBUG NOTE: 3D critter died on PULSE_DUST. No 3d anim available. Needs switch to 2d and play anim again", FOMB_GAME );
break;
case ANIM2_DEAD_EXPLODE :
if (cr.Stat[ST_GENDER] == 0) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),12,117,null,null);
if (cr.Stat[ST_GENDER] == 1) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),5,117,null,null);
Message("DEBUG NOTE: 3D critter died on EXPLODE. No 3d anim available. Needs switch to 2d and play anim again", FOMB_GAME );
break;
case ANIM2_DEAD_BURN :
cr.ClearAnim();
if (cr.Stat[ST_GENDER] == 0) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),11,118,null,null);
if (cr.Stat[ST_GENDER] == 1) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),5,118,null,null);
Message("DEBUG NOTE: 3D critter died on burn. No 3d anim available. Needs switch to 2d and play anim again", FOMB_GAME );
break;
case ANIM2_DEAD_BURN_RUN:
cr.ClearAnim();
if (cr.Stat[ST_GENDER] == 0) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),11,119,null,null);
if (cr.Stat[ST_GENDER] == 1) RunServerScriptUnsafe("debug@unsafe_specialdeath",(cr.Id),5,119,null,null);
Message("DEBUG NOTE: 3D critter died on BURN_RUN. No 3d anim available. Needs switch to 2d and play anim again", FOMB_GAME );
break;
default:
break;
}
You need two closing brackets at the end.
Second, we open the file debug.fos and add this code at the bottom:
void unsafe_specialdeath(Critter& player, int param0, int param1, int param2, string@ param3, int[]@ param4)
{
Critter@ target=GetCritter(def(param0,player.Id));
if (not valid(target)) return;
target.ChangeCrType(param1);
target.Animate( player.Id, param2, null, true, true );
}
Info: This method is not very effective, but it's all I can do. This has to be coded inside the engine and not executed from an external script. I'm sure someone will find a way to make it work properly.
Test. Try to die. Or use these commands:
~run debug body 0 293 1
~run debug anim 0 1 115
ShadersPlace these files inside client/effects.
Edit IOstructures.inc and add this at the bottom
struct VsToPs_3DNormal
{
float4 Position : POSITION;
float2 TexCoord : TEXCOORD0;
float3 Normal : TEXCOORD1;
};
Erase the cache. Test, and you should see some armors shine, and a different shading on the character.
That's all for now, I hope it works for you.
Please send me a message if you have any question. Sometimes I miss something or make a mistake that I don't notice, so don't hesitate and tell me about it.
Also, to enable the muzzleflashes, and death gore use this command
~param 0 161 101
or
~run debug SetCritParam (#crID) 161 101
last one works on other critters using their id number