Project Perfect Mod Forums
:: Home :: Get Hosted :: PPM FAQ :: Forum FAQ :: Privacy Policy :: Search :: Memberlist :: Usergroups :: Register :: Profile :: Log in to check your private messages :: Log in ::


The time now is Tue Mar 19, 2024 8:36 am
All times are UTC + 0
Step by step on how to create Petroglyph's Nuke Tank {TD} **
Moderators: Global Moderators
Post new topic   Reply to topic Page 1 of 1 [12 Posts] Mark the topic unread ::  View previous topic :: View next topic
Author Message
Banshee
Supreme Banshee


Also Known As: banshee_revora (Steam)
Joined: 15 Aug 2002
Location: Brazil

PostPosted: Thu Jun 04, 2020 1:43 am    Post subject:  Step by step on how to create Petroglyph's Nuke Tank {TD} **
Subject description: We will be updating this tutorial as soon we access the assets.
Reply with quote  Mark this post and the followings unread

Hello everyone! In this topic we will explain how to add a new unit for Tiberian Dawn in C&C: Remastered Collection. And, as a sample, we will use this Nuke Tank as sample, since Petroglyph Games has properly documented each step done to add this unit and tested it extensively.



Quote:
“What would the Brotherhood of Nod do if they captured the Mammoth Tank?”  Well, one guess is they’d replace the turret with a giant artillery cannon, and have it fire tactical nukes!  Thus, the Nuke Tank was born.


-------------------------------------------------------------------------------------

So, let's show how they have coded this Nuke Tank, shall we?

First of all, all units in Tiberian Dawn are declared inside the DLL, so you will need appropriate tools (Visual Studio compatible IDE) to open the source code and compile it. We recommend you to follow the instructions of this topic to do it. Once you are able to compile the source code, let's move on:


1) Define the constants for your new unit.

At the file DEFINES.H, you will need to defines constants that you will use to refer to your unit, projectile, weapon type, voice and few other entities that you may need to create to allow your unit to work as you desire. In Nuke Tank's case, we will only define labels for the unit, projectile, weapon type and voice (sound effect played when you select the unit or order it to do something).

At the typedef enum UnitType, you should define a new constant to your unit before UNIT_COUNT, as seen in bold.

I.e.:

Quote:
UNIT_STEG, // Stegasaurus
UNIT_NUKE_TANK, // Mammoth with a nuke
UNIT_COUNT,


At the typedef enum BulletType, you should define a new constant to your projectile before BULLET_COUNT, as seen in bold.

Quote:
BULLET_TREXBITE, // Tyrannosaurus Rex's bite - especially bad for infantry
BULLET_NUKE_LOB, // Nuke projectile
BULLET_COUNT,


At the typedef enum WeaponType, you should define a new constant to your weapon before WEAPON_COUNT, as seen in bold.

Quote:
WEAPON_TREX,
WEAPON_NUKE_LOB,
WEAPON_COUNT


At the typedef enum VocType, you should define a new constant to your voice sound effect before VOC_COUNT, as seen in bold.

Quote:
VOC_DINODIE1, // Dino die sound.
VOC_NUKE_LOB, // Modded unit firing sound
VOC_COUNT,



-------------------------------------------------------------------------------------

Now that we have labels to refers to these entities, it is time to define them and their attributes.

2) Let's start with the voice, since the voice doesn't require anyone else.

You will need to define its attributes at AUDIO.CPP, by adding a new element at the end of SoundEffectName[VOC_COUNT].

You will define the name of the sound file that it plays, the priority and the context. The context is explained above it in ContextType.

In our case, we have:

Quote:
{"NUKE_LOB", 10, IN_NOVAR} // VOC_NUKE_LOB Mod expansion unit firing sound


So, you must have a sound file called NUKE_LOB, and your sound has a priority of 10 and it won't have any variations (IN_NOVAR), no effects applied to it of any kind.

Be aware that the sounds listed at SoundEffectName[VOC_COUNT] must be in the same exact order of VocType in DEFINES.H.

-------------------------------------------------------------------------------------

3) Now let's do the bullet, also known as projectile. The bullet is a class, since it is more complex and allow more options. It is declared at BBDATA.CPP.

So, we need to declare it as a class NukeLob of the type BulletClass. You can copy any other class based on BulletClass and modify its properties, like what we will do below:

Code:
static BulletTypeClass const NukeLob(
   BULLET_NUKE_LOB,
   "BOMB",                  // NAME:         Text name of this unit type.
      true,                  // Flies over tall walls?
      false,               // Homes in on target?
      true,                  // Projectile arcs to the target?
      false,               // Is this a dropping bomb-like object?
      false,               // Is this projectile invisible?
      false,               // Will it blow up even if it gets just NEAR to target?
      false,               // Does it have flickering flame animation?
      false,               // Can it run out of fuel?
      true,                  // Is there no visual difference between projectile facings?
      true,                  // Is projectile inherently inaccurate?
      false,               // Translucent colors are used?
      false,               // Good against aircraft?
   0,                        // ARMING:      Time to arm projectile after launch.
   0,                        // RANGE:      Inherent override range factor.
   MPH_MEDIUM_FAST,         // SPEED:      Miles per hour.
   0,                        // ROT:         Rate of turn (degrees per tick).
   WARHEAD_HE,               // WARHEAD:      If fires weapon, warhead type
   ANIM_ATOM_BLAST         // Explosion to use upon impact.
);


So we have a class called NukeLob that inherits BulletClass and it has all the attributes documented above. If anyone wants me to explain each attribute, it will be done in a later version of this tutorial.

And finally, in order to allow the game to use this class, it must know about it at the same BBDATA.CPP, there is an array of pointers below called BulletTypeClass::Pointers[BULLET_COUNT]. You should add a pointer to the NukeLob class at the end of the list. Like this:

Quote:
&NukeLob, // BULLET_NUKE_LOB



-------------------------------------------------------------------------------------

4) We have the voice and we have the projectile. With these two classes ready, we can move to the weapon type. Due to optimization reasons (game performance), you must add it at CONST.CPP. There is a const for it known as WeaponTypeClass const Weapons[WEAPON_COUNT] where all projectiles are defined. You should add yours at the end of the declaration and provide the following attributes respectively: Damage, Rate of Fire, Range, Sound, and Animation.

So, in this sample:

Quote:
{BULLET_NUKE_LOB, 150, 130, 0x0B00, VOC_NUKE_LOB, ANIM_MUZZLE_FLASH}, // WEAPON_NUKE_LOB


BULLET_NUKE_LOB does 150 hit points of damage, takes 130 ticks to reload, is the weapon with the highest range of the game, plays the WEAPON_NUKE_LOB sound, and plays the ANIM_MUZZLE_FLASH animation (which is the tank firing animation seen in Light, Medium Tank and few other units).

Be aware that the weapons listed at the Weapons[WEAPON_COUNT] must be in the same exact order of WeaponType in DEFINES.H.



-------------------------------------------------------------------------------------

5) Now that the weapon is ready... we need to build the main thing, our main objective here: the unit! The bloody Nuke Tank, bout time! So, let's move to UDATA.CPP.

The unit willl be a class that will inherit UnitTypeClass. And there you will have a myriad of attributes to define. So, copy and paste another unit that is as similar as possible to yours and modify its attributes, like this:


Code:
// Nuke tank
static UnitTypeClass const UnitNukeTank(
   UNIT_NUKE_TANK,
   TXT_HTANK,                        // NAME:         Text name of this unit type.
   "NTNK",                           // NAME:         Text name of this unit type.
   ANIM_ART_EXP1,                     // EXPLOSION:   Type of explosion when destroyed.
   7,                        // Build level.
   STRUCTF_TEMPLE,         // Building prerequisite.
      true,            // Can this be a goodie surprise from a crate?
      true,            // Is a leader type?
      false,         // Only has eight facings?
      false,         // Always use the given name for the vehicle?
      false,         //   Is this a typical transport vehicle?
      false,         // Can it be crushed by a heavy vehicle?
      true,            // Can this unit squash infantry?
      false,         // Does this unit harvest Tiberium?
      false,         // Is invisible to radar?
      true,            // Is selectable by player?
      true,            // Can it be a target for attack or move?
      false,         // Is it insignificant (won't be announced)?
      false,         // Is it immune to normal combat damage?
      true,            // Is it equipped with a combat turret?
      false,         // Fires multiple shots in quick succession?
      true,            // Can it be repaired in a repair facility?
      true,            // Can the player construct or order this unit?
      true,            // Is there a crew inside?
      false,         // Does it have a rotating radar dish?
      false,         // Is there an associated firing animation?
      false,         // Must the turret be in a locked down position while moving?
      true,            // Does it lay tracks while moving?
      true,            // Is this a gigundo-rotund-enormous unit?
      false,         // Is the unit's art as "chunky" cardinal facing only?
      false,         // Is the unit capable of cloaking?
      false,         // Does the unit have a constant animation?
   -1,                              // AMMO:         Number of shots it has (default).
   600,                              // STRENGTH:   Strength (in damage points).
   6,                                 // SIGHTRANGE:   Range of sighting.
   1500,                              // COST:         Cost to build (Credits).
   10,                              // SCENARIO:   Starting availability scenario.
   80,80,                            // RISK/RWRD:   Risk/reward rating values.
   HOUSEF_MULTI1|
   HOUSEF_MULTI2|
   HOUSEF_MULTI3|
   HOUSEF_MULTI4|
   HOUSEF_MULTI5|
   HOUSEF_MULTI6|
   HOUSEF_JP|
   HOUSEF_BAD,                        // OWNABLE:      Ownable by house (bit field).
   WEAPON_NUKE_LOB,WEAPON_NONE,
   ARMOR_STEEL,                     // ARMOR:      Armor type
   SPEED_TRACK,                     // MOVE:         Locomotion type.
   MPH_KINDA_SLOW,                  // SPEED:      Miles per hour.
   3,                                 // ROT:         Rate of turn (degrees per tick).
   0,                                 // Turret center offset along body centerline.
   MISSION_HUNT                     // ORDERS:      Default order to give new unit.
);



Most things there are explained by Petroglyph/Westwood's documentation, so I will focus on few things above.

The house/faction that this unit belongs is defined by HOUSEF_MULTI1 | HOUSEF_MULTI2 | HOUSEF_MULTI3 | HOUSEF_MULTI4 | HOUSEF_MULTI5 | HOUSEF_MULTI6 | HOUSEF_JP | HOUSEF_BAD. Except for HOUSEF_BAD, everything else is mere formality that does not deny any player from building it nor the "Disaster Containment Team" to own it... but the real deal is HOUSEF_GOOD means that GDI can build it and HOUSEF_BAD means that Nod can build it.

The weapons are set right after the houses. WEAPON_NUKE_LOB,WEAPON_NONE means that primary weapon is WEAPON_NUKE_LOB and that there is no secondary weapon.


And just like the weapons, you need to add the pointer to this class at UnitTypeClass::Pointers[UNIT_COUNT].

Code:
   &UnitNukeTank,      // UNIT_NUKE_TANK


The order of these pointers must be syncronized with UnitType typedef in DEFINES.H.


And for those wondering, where do we declare the graphics? By default, it uses the TEXT attribute in the class declaration above, but our Nuke Tank reuses the image from Mammoth Tank. So, Petroglyph has done a quick "workaround" to handle this issue by editing the OneTime method at UnitTypeClass, at void UnitTypeClass::One_Time(void) in UDATA.CPP.

So, before defining:

Code:
      ((void const *&)uclass.ImageData) = ptr;


They've set this ptr into something else specifically if the unit is the UNIT_NUKE_TANK.

Code:
      /*
      ** Need some kind of shape data for our modded unit
      */
      if (index == UNIT_NUKE_TANK && ptr == NULL) {
         _makepath(fullname, NULL, NULL, "HTNK", ".SHP");
         ptr = MixFileClass::Retrieve(fullname);
      }



Finally, our nuke tank has a turret. And we need to determine its fire coordinates. I mean, where will the projectile be created when it fires? So, in TURRET.CPP, we will have to edit the Fire_Coord method of TurretClass. More specifically for searching purposes: COORDINATE TurretClass::Fire_Coord(int which) const

Right after the other units get mentioned, you should add:

Code:
      case UNIT_NUKE_TANK:
         coord = Coord_Move(coord, DIR_N, 0x00A0);
         dist = 0x00A0;
         break;


In case the unit is UNIT_NUKE_TANK, the coordinate will be 240 leptons (?) above the center of the turret.




-------------------------------------------------------------------------------------

6) Final remarks:

And that's it. Now that you have the code ready, it is time to compile it and test it out.

Remember that Nuke Tank is properly documented by Petroglyph Games and they've separated its code between #ifdef PETROGLYPH_EXAMPLE_MOD and #endif. That's a good coding manners, since if it is something goes wrong, all you need to do is to disable PETROGLYPH_EXAMPLE_MOD (in this sample) or whaever you define. Also, thanks to this coding manners, we could figure out how to create a unit without being able to play the game yet.

I know that you won't code a unit in this order. You will certainly think of a unit and, if it needs a weapon, a projectile or a voice, you will code these things later. It is ok and intuitive to do that instead. The order we have used here allows you to test the code as you do each step.

So, happy modding and have fun!


Key Words: #Tutorials #Modding #CommandAndConquerRemastered #DLLEditing 

Last edited by Banshee on Thu Jun 04, 2020 7:16 am; edited 1 time in total

Back to top
View user's profile Send private message Visit poster's website Skype Account
Lin Kuei Ominae
Seth


Joined: 16 Aug 2006
Location: Germany

PostPosted: Thu Jun 04, 2020 6:58 am    Post subject: Reply with quote  Mark this post and the followings unread

and now i understand why several things like a TertiaryWeapon will be pain to implement. The structures/signatures are fixed and would need to be changed on every single object in the game to accommodate such entirely new logics.

I assume the first thing modders will do is adding an ini support, to enable modding for the less programming experienced.


changing the game to use metric system may be also useful #Tongue

_________________
SHP Artist of Twisted Insurrection:  Nod buildings

Public SHPs
X-Mech Calendar (28 Mechs for GDI and Nod)
5 GDI, 5 Nod, 1 Mutant, 1 Scrin unit, 1 GDI building

Tools
Image Shaper______TMP Shop______C&C Executable Modifier

Back to top
View user's profile Send private message
FS-21
Cyborg Soldier


Joined: 09 Dec 2002
Location: Spain

PostPosted: Thu Jun 04, 2020 8:21 am    Post subject: Reply with quote  Mark this post and the followings unread

RA1 used ini config files, now it works like inside the code like this TD example?

_________________
C&C:Reloaded > GDI, Nod, Allies, Soviets & Yuri... & TS terrain!
[ Discord ] [ ModDB ] [ YouTube Channel ] [ Telegram Channel ] [ Official Forums@Revora ]

Back to top
View user's profile Send private message Send e-mail Visit poster's website ModDB Profile ID
Banshee
Supreme Banshee


Also Known As: banshee_revora (Steam)
Joined: 15 Aug 2002
Location: Brazil

PostPosted: Thu Jun 04, 2020 8:47 am    Post subject: Reply with quote  Mark this post and the followings unread

Technically yes, it does.... although it does accept INI code as well. There is a INI.H and INI.CPP to handle these things. UDATA.CPP only has few units.

Theorically, these source codes are an upgrade of the original games, so they allow you to do everything the original games allowed you to do.

Back to top
View user's profile Send private message Visit poster's website Skype Account
Nyerguds
General


Joined: 24 May 2004
Location: Flanders (Be) Posts:300000001

PostPosted: Thu Jun 04, 2020 9:58 am    Post subject: Reply with quote  Mark this post and the followings unread

Note, I'm not sure if the "gigundo-rotund-enormous unit" option still has any effect in the remaster... but in the original game, it is necessary for units that have graphics that are larger than a game cell (24x24 in the original), to make their graphics refresh and clear properly outside the cell they're on.

My patch enables that to fix refresh errors on the Rocket Launcher.

_________________

Back to top
View user's profile Send private message Visit poster's website Skype Account
CCHyper
Defense Minister


Joined: 07 Apr 2005

PostPosted: Thu Jun 04, 2020 10:41 am    Post subject: Reply with quote  Mark this post and the followings unread

Banshee, this alone will not work as there are XML, Audio and Art assets added in that mod, as well as the formatting of a Workshop item. The game as I'm aware doesn't ship the Nuke Tank HD assets (and doesn't have legacy artwork either).

Back to top
View user's profile Send private message
Banshee
Supreme Banshee


Also Known As: banshee_revora (Steam)
Joined: 15 Aug 2002
Location: Brazil

PostPosted: Thu Jun 04, 2020 4:45 pm    Post subject: Reply with quote  Mark this post and the followings unread

@CCHyper, that Nuke Tank uses assets from Mammoth Tank  (HTNK assets):

Code:
if (index == UNIT_NUKE_TANK && ptr == NULL) {
         _makepath(fullname, NULL, NULL, "HTNK", ".SHP");
         ptr = MixFileClass::Retrieve(fullname);


And yea, the other assets itself were not included and I have not mentioned them yet because I don't have access to it. I will update this tutorial as soon as I can access the game and the Nuke Tank assets. And that should happen soon.

Back to top
View user's profile Send private message Visit poster's website Skype Account
Exley
Commander


Joined: 09 May 2011
Location: Approaching the Great Pyramid

PostPosted: Sat Jun 06, 2020 5:42 pm    Post subject: Reply with quote  Mark this post and the followings unread

good way to demoralize people to mod things...

_________________
Quote:

how did we end up here ?

this place is horrible ...

smells like balls ...


Back to top
View user's profile Send private message
Lin Kuei Ominae
Seth


Joined: 16 Aug 2006
Location: Germany

PostPosted: Sat Jun 06, 2020 5:58 pm    Post subject: Reply with quote  Mark this post and the followings unread

Only if they are learn resistant.

_________________
SHP Artist of Twisted Insurrection:  Nod buildings

Public SHPs
X-Mech Calendar (28 Mechs for GDI and Nod)
5 GDI, 5 Nod, 1 Mutant, 1 Scrin unit, 1 GDI building

Tools
Image Shaper______TMP Shop______C&C Executable Modifier

Back to top
View user's profile Send private message
munkle555
Civilian


Joined: 07 Jun 2020

PostPosted: Mon Jun 08, 2020 8:39 am    Post subject: Reply with quote  Mark this post and the followings unread

Hi, I have added a new tank in RA, I have updated the define_h, udata and rules ini and a new icon appears in the weapons factory but its a glitched icon that looks like the fake construction yard and wont actually build. Any Idea what I have done wrong. I am basing it on the mammoth tank so copied its data and changed the identifiers to a new one

Back to top
View user's profile Send private message
Reinforcementshavearrived
Vehicle Driver


Joined: 09 Jun 2020

PostPosted: Tue Jun 09, 2020 7:42 pm    Post subject: Re: Step by step on how to create Petroglyph's Nuke Tank {TD} ** Reply with quote  Mark this post and the followings unread

Banshee wrote:
And for those wondering, where do we declare the graphics? By default, it uses the TEXT attribute in the class declaration above, but our Nuke Tank reuses the image from Mammoth Tank. So, Petroglyph has done a quick "workaround" to handle this issue by editing the OneTime method at UnitTypeClass, at void UnitTypeClass::One_Time(void) in UDATA.CPP.

So, before defining:

Code:
      ((void const *&)uclass.ImageData) = ptr;


They've set this ptr into something else specifically if the unit is the UNIT_NUKE_TANK.

Code:
      /*
      ** Need some kind of shape data for our modded unit
      */
      if (index == UNIT_NUKE_TANK && ptr == NULL) {
         _makepath(fullname, NULL, NULL, "HTNK", ".SHP");
         ptr = MixFileClass::Retrieve(fullname);
      }



So I guess this isn't something that can be added to RA.
In my case, the One_time(void) method is like this
Code:
      
void AircraftTypeClass::One_Time(void)
{

   for (int index = AIRCRAFT_FIRST; index < AIRCRAFT_COUNT; index++) {
      char fullname[_MAX_FNAME+_MAX_EXT];
      AircraftTypeClass   const & uclass = As_Reference((AircraftType)index);
      void const* ptr = NULL;
      /*
      **   Fetch the supporting data files for the unit.
      */
      char buffer[_MAX_FNAME];
      sprintf(buffer, "%sICON", uclass.Graphic_Name());
      _makepath(fullname, NULL, NULL, buffer, ".SHP");
      ((void const *&)uclass.CameoData) = MFCD::Retrieve(fullname);

      /*
      **   Generic shape for all houses load method.
      */
      _makepath(fullname, NULL, NULL, uclass.Graphic_Name(), ".SHP");
      ((void const *&)uclass.ImageData) = MFCD::Retrieve(fullname);
   }

   LRotorData = MFCD::Retrieve("LROTOR.SHP");
   RRotorData = MFCD::Retrieve("RROTOR.SHP");
}

and there is no call to the MixFileClass. I'm not much of a coder but I'm still struggling to understand how this can be adapted to RA.

Back to top
View user's profile Send private message
fusedtoast
Guest




PostPosted: Fri Jan 15, 2021 7:13 am    Post subject: NukeTank in RA Reply with quote  Mark this post and the followings unread

I did my best to guess how, but it didn't work.

Back to top
Display posts from previous:   
Post new topic   Reply to topic Page 1 of 1 [12 Posts] Mark the topic unread ::  View previous topic :: View next topic
 
Share on TwitterShare on FacebookShare on Google+Share on DiggShare on RedditShare on PInterestShare on Del.icio.usShare on Stumble Upon
Quick Reply
Username:


If you are visually impaired or cannot otherwise answer the challenges below please contact the Administrator for help.


Write only two of the following words separated by a sharp: Brotherhood, unity, peace! 

 
You cannot post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © phpBB Group

[ Time: 0.1705s ][ Queries: 11 (0.0102s) ][ Debug on ]