Solutions to NDF advanced exercises

From AOW HT Wiki

Contents

Exercise 1

  • With GROUPE_SEMANTIQUE

The units are defined in the files in the following directory : <GameDirectory>\AOW\DataLight\TypeWarriorLazy\Unites\

The Marine SPF is defined in the following file : <GameDirectory>\AOW\DataLight\TypeWarriorLazy\Unites\TF\Marine SPF\AoW_TF_MSPF.ndf

The main part of the file is the template TypeWarriorAow_TF_MarineSPF. You can see it immediately because it is "exported" and therefore accessible from other files.

The caracteristics of the unit are defined through the parameter AOW_TF_MARINE_SPF_SEMANTIQUE (Nom_Parametre_Semantique = AOW_TF_MARINE_SPF_SEMANTIQUE) which description is divised into two files : <GameDirectory>\datalight\DefaultNDF\Unites\ParametreSemantiques\_zAoW_XX_ParametresSemantiquesUnites_DoNotEdit.ndf and <GameDirectory>\datalight\DefaultNDF\Unites\ParametreSemantiques\zAoW_TF_ParametresSemantiquesUnites.ndf.

The characteristic which interests us is MOUVEMENT which represents mainly the speed of the unit.

So in order to increase the speed of the MSPF, you just have to find the GROUPE_SEMANTIQUE AOW_TF_MARINE_SPF_SEMANTIQUE and modify the value MOUVEMENT = 1100

  • With Cheatcode

The cheatchodes are defined here : <GameDirectory>\datalight\effet\EffetIA\AoWCheatCode.ndf. The cheatcode that we will add looks like the 'duckhunt' one. Add :

<ndf>('supermspf', $/DefaultConst/IsMSPFAcceleratedValue := TConditionNot :
                                                       SubCondition = $/DefaultConst/IsMSPFAccelerated
),
</ndf> 

That is a global variable that indicates if the MSPF unit is accelerated or not.

You have to declare it in <GameDirectory>\datalight\DefaultNDF\System\RessourceList.ndf :

<ndf>export IsMSPFAcceleratedValue is TEugBBoolean( Value = false )
export IsMSPFAccelerated is TAccesseurBooleanFromEUGBObject
(
   EUGBObject = IsMSPFAcceleratedValue
)</ndf>

After that, you have to use this variable were the speed of the MSPF is defined. TypeWarriorAow_TF_MarineSPF is a Template_TypeWarrior_Infanterie which is defined here : <GameDirectory>\AOW\DataLight\TypeWarrior\_Common\Unites\AOW\AoW_Infanterie.ndf

In that template, search MouvementParSeconde = <Nom_Parametre_Semantique>.MOUVEMENT and replace it by

<ndf>MouvementParSeconde = TAccesseurRealTestIfTrueOrFalse :
                        Condition = <IsAccelerated>
                        AccesseurRealIfTrue = 2 * <Nom_Parametre_Semantique>.MOUVEMENT
                        AccesseurRealIfFalse = <Nom_Parametre_Semantique>.MOUVEMENT
</ndf>

The template parameter <IsAccelerated> has to be add in the parameters of Template_TypeWarrior_Infanterie (just after AdditionalDataBlockList = [],, you add IsAccelerated = False. So by default the units will not be accelerated.

Finally, go back in TypeWarriorAow_TF_MarineSPF and add IsAccelerated = $/DefaultConst/IsMSPFAccelerated to make him accelerated if the cheatcode is active.


Tips : to save your time, you should add this cheatcode :

<ndf>
                  ('units', SEQ with
                            [
                              TemplateSpawnUniteDuJoueurAuCentre(TYPE_WARRIOR_AS_STRING = 'TypeWarrior/TypeWarriorAoW_CS_ArmorFactory'),
                              TemplateSpawnUniteDuJoueurAuCentre(TYPE_WARRIOR_AS_STRING = 'TypeWarrior/TypeWarrior_AoW_CS_BTR80'),
                              TemplateSpawnUniteDuJoueurAuCentre(TYPE_WARRIOR_AS_STRING = 'TypeWarrior/TypeWarrior_AoW_US_Abrams'),
                              TemplateSpawnUniteDuJoueurAuCentre(TYPE_WARRIOR_AS_STRING = 'TypeWarrior/TypeWarriorAow_TF_MarineSPF'),
                              TemplateSpawnUniteDuJoueurAuCentre(TYPE_WARRIOR_AS_STRING = 'TypeWarrior/TypeWarrior_AoW_US_RPG'),
                              TemplateSpawnUniteDuJoueurAuCentre(TYPE_WARRIOR_AS_STRING = 'TypeWarrior/TypeWarrior_Aow_CS_Soldier')
                            ]
                  ), 
</ndf>

It will spawn the different units you need in theses exercises.

And do not forget you can spawn the bases of CS, US and TFT with the shortcut CTRL+F1, CTRL+F2 and CTRL+F3

Exercise 2

  • With GROUPE_SEMANTIQUE

Alter the rate of fire with GROUPE_SEMANTIQUE is the same as in exercise 1. The javelin is named TypeWarrior_AoW_US_RPG in <GameDirectory>\AOW\DataLight\TypeWarriorLazy\Unites\US\RPG\AoW_US_RPG.ndf

Its GROUPE_SEMANTIQUE is AoW_US_RPG_SEMANTIQUE_GRAPHIC. So in <GameDirectory>\datalight\DefaultNDF\Unites\ParametreSemantiques\_zAoW_XX_ParametresSemantiquesUnites_DoNotEdit.ndf alter DUREE_TIR of AOW_US_RPG_SEMANTIQUE and the rate of fire will be altered

  • With Cheatcode

First we add a cheatcode like in exercise 1 :

<ndf>
('superjavelin', $/DefaultConst/IsJavelinFireAcceleratedValue := TConditionNot :
                                                                   SubCondition = $/DefaultConst/IsJavelinFireAccelerated
),</ndf>

And declare the variable :

<ndf>
export IsJavelinFireAcceleratedValue is TEugBBoolean( Value = false )
export IsJavelinFireAccelerated is TAccesseurBooleanFromEUGBObject
(
   EUGBObject = IsJavelinFireAcceleratedValue
)
</ndf>

After that, we can alter directly the rate of fire of the RPG in AoW_US_RPG.ndf. Replace DUREE_RECHARGE_TIR with :

<ndf>
TAccesseurRealTestIfTrueOrFalse :
  Condition = $/DefaultConst/IsJavelinFireAccelerated
  AccesseurRealIfTrue = 0.5 * AOW_US_RPG_SEMANTIQUE.DUREE_TIR
  AccesseurRealIfFalse = AOW_US_RPG_SEMANTIQUE.DUREE_TIR} 
</ndf>

If you want, you can also improve the speed of animations : see the ACCESSEUR_DUREE_EN_SECONDE.

Exercise 3

Additional Property

Fist, we must add an additional property to the typewarrior : ObjectString_GenerationNumber

This will represent the generation number of the domino. When it's 20, it doesn't create new domino anymore

In <GameDirectory>\DataLight\DefaultNDF\System\ObjectConst.ndf add :

<ndf>export ObjectString_GenerationNumber is TEUGBString :
   Value = 'NumeroGeneration'
</ndf>

We set this additionnal property to 1 for the first domino :

<ndf>
Test is SEQ :
   VarLocaleList = [ locUnite is TemplateVariableLocaleUnitBalise() ]
with
[
   TEffetCreateWarrior :
      AccesseurPositionPlancher = DefaultConst/AccesseurPositionPlancher_PickedPoint
      TypeWarriorAsString       = '$/TypeWarrior/effettest/TypeWarriorDomino'
      AccesseurCamp             = DefaultConst/AccesseurCampDuJoueur
      VariableLocaleCible       = locUnite
   ,
   TEffetSetIntegerAdditionalProperty :
      PropertyName = $/DefaultConst/ObjectString_GenerationNumber
      AccesseurUnitBalise = locUnite
      Value = 1
]
</ndf>

When we will create another domino, we will increment this value by 1 :

<ndf>
SEQ with
[
  TEffetCreateWarrior :
    AccesseurPositionPlancher = locPosition
    TypeWarriorAsString       = '$/TypeWarrior/effettest/TypeWarriorDomino'
    AccesseurCamp             = DefaultConst/AccesseurCampDuJoueur
    VariableLocaleCible       = locUnite
  ,
  TEffetSetIntegerAdditionalProperty :
    PropertyName        = $/DefaultConst/ObjectString_GenerationNumber
    AccesseurUnitBalise = locUnite
    AccesseurValue      = TAccesseurIntegerAdd :
                            IntegerList = [
                                            1,
                                            TAccesseurIntegerFromAdditionalProperty :
                                              AccesseurUnitBalise = $/DefaultConst/SelfUnitBalise
                                              PropertyName = $/DefaultConst/ObjectString_GenerationNumber
                                          ]
]
</ndf>                     

Unit State Machine Descriptor

We create two states : SubUnitStateDescriptorList = [USD_Reproduction, USD_Suicide] The first one will wait during 1 second, and then create another domino and go to the other state.

<ndf>
   USD_Reproduction is TUnitStateDescriptor :
      MyName = 'USD_Reproduction'
      EffetDescriptor = TWaitPrecis :
                            DureeEnSecondes = 1
      EffetDescriptorBeforeEnd = SEQ with
                                 [
                                   EffectCreateAnotherWarrior
                                   ,
                                   TEffetUnitStateMachine_ChangeFatherUnitDecision :
                                      Niveau = 1
                                      NewUnitDecision = TUnitDecisionConstante :
                                                           MyName              = 'UD_Suicide'
                                                           UnitStateDescriptor = USD_Suicide
                                 ]
</ndf>

The second state will wait during 3 seconds, and then kill itself.

<ndf>
USD_Suicide is TUnitStateDescriptor :
      MyName = 'USD_Suicide'
      EffetDescriptor = TWaitPrecis :
                           DureeEnSecondes = 3
      EffetDescriptorBeforeEnd = TEffetKillUnitBalise :
                                    AccesseurUnitBalise                    = $/DefaultConst/SelfUnitBalise
                                    AccesseurCampResponsableDeLaMort       = DefaultConst/AccesseurCampDuJoueur
                                    AccesseurUnitBaliseResponsableDeLaMort = $/DefaultConst/SelfUnitBalise
                                    AcceptUnitBaliseNil                    = True
</ndf>                                    

Code

<ndf>
Test is SEQ :
   VarLocaleList = [ locUnite is TemplateVariableLocaleUnitBalise() ]
with
[
   TEffetCreateWarrior :
      AccesseurPositionPlancher = DefaultConst/AccesseurPositionPlancher_PickedPoint
      TypeWarriorAsString       = '$/TypeWarrior/effettest/TypeWarriorDomino'
      AccesseurCamp             = DefaultConst/AccesseurCampDuJoueur
      VariableLocaleCible       = locUnite
   ,
   TEffetSetIntegerAdditionalProperty :
      PropertyName = $/DefaultConst/ObjectString_GenerationNumber
      AccesseurUnitBalise = locUnite
      Value = 1
]

//------------------------------------------------------------------------------
EffectCreateAnotherWarrior is SEQ :
    VarLocaleList = [
                       locPosition is TemplateVariableLocalePositionPlancher(),
                       locShiftX is TemplateVariableLocaleReal(),
                       locShiftY is TemplateVariableLocaleReal(),
                       locUnite is TemplateVariableLocaleUnitBalise()
                    ]
with
[
   locShiftX := 0,
   locShiftY := 0,
   RandomShift is TEffetRunEffetFromIndex :
      AccesseurInteger_Index = TAccesseurIntegerRandom :
                                  ValueMin = 0
                                  Range = 4
      EffetList = [
                     locShiftX := -400,
                     locShiftX := 400,
                     locShiftY := 400,
                     locShiftY := -400
                  ]
   ,
   ShiftPosition is locPosition := TAccesseurPositionPlancher_Decalage :
                                     AccesseurRealDecalageX    = locShiftX
                                     AccesseurRealDecalageY    = locShiftY
                                     AccesseurPositionPlancher = TAccesseurPositionPlancher_SelfFromUnitBalise :
                                                                   AccesseurUnitBalise = $/DefaultConst/SelfUnitBalise
   ,
   TestIfLastGeneration is TEffetTestIfTrueOrFalse :
      Condition = TAccesseurBooleanComparatorReal :
                     AccesseurReal1 = TAccesseurIntegerFromAdditionalProperty :
                                                   AccesseurUnitBalise = $/DefaultConst/SelfUnitBalise
                                                   PropertyName = $/DefaultConst/ObjectString_GenerationNumber
                     Value2 = 10
                     Can1BeEgalA2 = True
      EffetIfFalse = SEQ with
                     [
                        TEffetCreateWarrior :
                           AccesseurPositionPlancher = locPosition
                           TypeWarriorAsString       = '$/TypeWarrior/effettest/TypeWarriorDomino'
                           AccesseurCamp             = DefaultConst/AccesseurCampDuJoueur
                           VariableLocaleCible       = locUnite
                        ,
                        TEffetSetIntegerAdditionalProperty :
                           PropertyName        = $/DefaultConst/ObjectString_GenerationNumber
                           AccesseurUnitBalise = locUnite
                           AccesseurValue      = TAccesseurIntegerAdd :
                                                    IntegerList = [
                                                                     1,
                                                                     TAccesseurIntegerFromAdditionalProperty :
                                                                        AccesseurUnitBalise = $/DefaultConst/SelfUnitBalise
                                                                        PropertyName = $/DefaultConst/ObjectString_GenerationNumber
                                                                  ]
                     ]
]


//------------------------------------------------------------------------------
TypeWarriorDomino is TTypeWarrior :
   SoldatCarac = TSoldatCarac :
                    PV             = 1
                    Detectable     = False
                    Blessable      = True
                    Visualisable   = True
                    Selectionnable = False
                    DoNotMirror    = True

   EffectReproductionBeforeEnd is SEQ with
   [
      EffectCreateAnotherWarrior
      ,
      TEffetUnitStateMachine_ChangeFatherUnitDecision :
         Niveau = 1
         NewUnitDecision = TUnitDecisionConstante :
                              MyName              = 'UD_Suicide'
                              UnitStateDescriptor = USD_Suicide
   ]
   
   USD_Reproduction is TUnitStateDescriptor :
      MyName = 'USD_Reproduction'
      EffetDescriptor = TWaitPrecis :
                            DureeEnSecondes = 1
      EffetDescriptorBeforeEnd = EffectReproductionBeforeEnd

   USD_Suicide is TUnitStateDescriptor :
      MyName = 'USD_Suicide'
      EffetDescriptor = TWaitPrecis :
                           DureeEnSecondes = 3
      EffetDescriptorBeforeEnd = TEffetKillUnitBalise :
                                    AccesseurUnitBalise                    = $/DefaultConst/SelfUnitBalise
                                    AccesseurCampResponsableDeLaMort       = DefaultConst/AccesseurCampDuJoueur
                                    AccesseurUnitBaliseResponsableDeLaMort = $/DefaultConst/SelfUnitBalise
                                    AcceptUnitBaliseNil                    = True

   UnitStateMachineDescriptor = USMD is TUnitStateMachineDescriptor :
                                   MainUnitStateDescriptor = MUSD is TUnitStateDescriptor :
                                                                EffetDescriptor = Animation is SEQ with
                                                                                  [
                                                                                     TScaleModificator :
                                                                                        ScaleX = 20
                                                                                        ScaleY = 20
                                                                                        ScaleZ = 20
                                                                                     ,
                                                                                     EffetRepeatAnim :
                                                                                        MODEL_ASE = 'Data\XFiles3\Util\PointInterrogation'
                                                                                        PERIODE_EN_SECONDE = 2
                                                                                  ]
                                                                MyName = 'MUSD_Domino'
                                                                SubUnitStateDescriptorList = [USD_Reproduction, USD_Suicide]
                                                                UnitDecision = TUnitDecisionConstante :
                                                                                  MyName = 'UD_Reproduction'
                                                                                  UnitStateDescriptor = USD_Reproduction
   WarriorKreator = WarriorKreator/WarriorKreatorMarine
   AdditionalPropertyList = [
                               TAdditionalPropertyInteger :
                                  MinValue = 1
                                  MaxValue = 10
                                  PropertyName = $/DefaultConst/ObjectString_GenerationNumber
                                  Value = 1
                            ]
</ndf>

Exercise 4

Add an upgrade to the BTR-80 (Consortium light tank) in order to make him shoot at ennemi aircrafts

The BTR-80 is TypeWarrior_AoW_CS_BTR80, defined in <GameDirectory>\AOW\DataLight\TypeWarriorLazy\Unites\CS\AoW_CS_BTR80\AoW_CS_BTR80.ndf.

Add a MAIN_EFFET_DESCRIPTOR that changes its scanner. The scanner of a unit represents what he is able to target and shoot.

<ndf>
MAIN_EFFET_DESCRIPTOR = SEQ with
[
  TEffetDescriptorSortilegeChangeScannerDescriptor :
    ScannerDescriptor = $/TypeWarrior/TemplateScannerDescriptorFromDataBlockAoW :
                          AltitudeDeVision = AOW_TF_BUGGY_MISSILE_SEMANTIQUE.ALTITUDE_VISION
                          ScannerAnalysor  = $/DefaultConst/ScannerAnalysorAntiAvionSoldatChar
                          CaracGroup       = 'Upgrade_AA'
]
</ndf>
We must also define the missile characteristics (we take the TF Buggy example) :
<ndf>
AdditionalDataBlockList = [ TDataBlock :
                              BlockModule = 'ParamsUnit'
                              BlockObject = 'AOW_TF_BUGGY_MISSILE_SEMANTIQUE'
                              CaracGroup  = 'Upgrade_AA'
                          ]
</ndf>

Now the BTR-80 is able to shoot at aircrafts. But if you try the mod, you see that the missile does not follow the aircraft.

In EffetTirBTR80 replace
UnitIACategoryList = $/DefaultConst/IACategoryList_VehiculeSol
by :
<ndf>
UnitIACategoryList = $/DefaultConst/IACategoryList_VehiculeSol
                     +
                     $/DefaultConst/IACategoryList_Helicoptere_Avion
</ndf>

Add a button in the action cube (use the AA buggy upgrade icone)

First we will create a ressource : a global variable that will indicate if the upgrade has already been done.

In <GameDirectory>\datalight\DefaultNDF\System\RessourceList.ndf, add :

<ndf>
export Ressource_CS_UpgradeBTR80AACapacity is TRessourceConstruction :
  ClefAccess = 'CS_UpgradeBTR80AACapacity'
  Nom        = '|Upgrade BTR80 AA Capacity'
</ndf>

Next we have to wait our upgrade is done to let the BTR_80 fire on aircraft, so replace the MAIN_EFFET_DESCRIPTOR by

<ndf>
   MAIN_EFFET_DESCRIPTOR =  SEQ with
                            [
                               Template_WaitForGlobalUpgrade :
                                  UPGRADE_RESSOURCE = $/DefaultConst/Ressource_CS_UpgradeBTR80AACapacity
                               ,
                               TEffetDescriptorSortilegeChangeScannerDescriptor :
                                  ScannerDescriptor = $/TypeWarrior/TemplateScannerDescriptorFromDataBlockAoW :
                                                         AltitudeDeVision = AOW_TF_BUGGY_MISSILE_SEMANTIQUE.ALTITUDE_VISION
                                                         ScannerAnalysor = $/DefaultConst/ScannerAnalysorAntiAvionSoldatChar
                                                         CaracGroup = 'Upgrade_AA'
                            ]
</ndf>

Now we can add a button in the Armor Factory to purchase this upgrade : In <GameDirectory>\AOW\DataLight\TypeWarriorLazy\Bases\CS\Aow_CS_ArmorFactory\AoW_CS_ArmorFactory.ndf In COMPETENCE_LIST_AFTER_CONSTRUCTION :

Remove : CompetenceConstruireUpgradeTunguskaExtendedAARadar/CompetenceConstruire (otherwise there is not enough place for our upgrade)

And add : CompetenceConstruire_Upgrade_BTR80AACapacity/CompetenceConstruire

This has to be defined in <GameDirectory>\AOW\DataLight\TypeWarrior\_Common\SpecialAptitude\Competence_CS.ndf. Add :

<ndf>
   CompetenceConstruire_Upgrade_BTR80AACapacity is TemplateCompetenceConstruire_UpgradeInWarp :
   ICONE_X = AoW_CUBEACTION_DIM.COLONNE_2
   ICONE_Y = AoW_CUBEACTION_DIM.LIGNE_3
   Texture = $/DefaultConst/AOW_STANDARD.PATH_ICONES + 'Competence\TF\TF_Upgrade_Buggy_AA.tga'
   TYPE_WARRIOR_TO_CREATE_AS_STRING = 'TypeWarrior/TypeWarrior_AoW_CS_Upgrade_BTR80AACapacity'
   ParametreSemantiqueHint_Bouton = AOW_TF_UPGRADE_BUGGY_AA_CAPACITY_SEMANTIQUE_HINT
   PROPERTY_NAME = $/DefaultConst/ObjectString_AoW_CS_Upgrade_BTR80AACapacity
</ndf>

As you see, you have to create a property_name : $/DefaultConst/ObjectString_AoW_CS_Upgrade_BTR80AACapacity, and a typewarrior : TypeWarrior_AoW_CS_Upgrade_BTR80AACapacity

The property_name :

In <GameDirectory>\AOW\DataLight\TypeWarrior\_Common\Unites\UnitBaliseCamp.ndf add (next to the others upgrades) :

<ndf>
Template_AdditionalProperty_Upgrade :
  PropertyName = $/DefaultConst/ObjectString_AoW_CS_Upgrade_BTR80AACapacity
</ndf>

And in <GameDirectory>\datalight\DefaultNDF\System\_AdditionalProperties_ObjectString.ndf, add :

<ndf>
export ObjectString_AoW_CS_Upgrade_BTR80AACapacity is TEUGBString ( Value = 'AoW_CS_Upgrade_BTR80AACapacity' )
</ndf>

The TypeWarrior :

In AOW_CS_ArmorFactory.ndf (at the end of the file) :

<ndf>
export TypeWarrior_AoW_CS_Upgrade_Fake_BTR80AACapacity is TemplateTypeWarriorUpgradeFakeTechno :
  Classement = 'AOW/Factions/TaskForce/Utils/FakeUpgrade/$TF_Upgrade_BuggyAACapacity'
  Nom_Parametre_Semantique = AOW_CS_UPGRADE_BTR80_AA_CAPACITY_SEMANTIQUE
  ADDITIONAL_PROPERTY_DU_CAMP = $/DefaultConst/ObjectString_AoW_CS_Upgrade_BTR80AACapacity
  UPGRADE_RESSOURCE = $/DefaultConst/Ressource_CS_UpgradeBTR80AACapacity

export TypeWarrior_AoW_CS_Upgrade_BTR80AACapacity is Template_TypeWarrior_Upgrade_GlobalCampNeMeurtJamaisEtNeSAnnuleJamais :
  Nom_Parametre_Semantique = AOW_CS_UPGRADE_BTR80_AA_CAPACITY_SEMANTIQUE
  Nom_Parametre_Semantique_Hint = AOW_TF_UPGRADE_BUGGY_AA_CAPACITY_SEMANTIQUE_HINT
  ADDITIONAL_PROPERTY_DU_CAMP = $/DefaultConst/ObjectString_AoW_CS_Upgrade_BTR80AACapacity
</ndf>

and in <GameDirectory>\AOW\datalight\TypeWarrior\_Common\_ChargementRetardeBases.ndf :

<ndf>
Chargement_TypeWarrior_Aow_CS_ArmorFactory is TemplateChargement_TWAOW :
  TWNameList = STRINGLIST
               [
                 (...)
                 'TypeWarrior_AoW_CS_Upgrade_Fake_BTR80AACapacity',
                 'TypeWarrior_AoW_CS_Upgrade_BTR80AACapacity',
               ]  
</ndf>

And finally, the AOW_CS_UPGRADE_BTR80_AA_CAPACITY_SEMANTIQUE :

<GameDirectory>\datalight\DefaultNDF\Unites\ParametreSemantiques\zAoW_CS_ParametresSemantiquesUpgrades.ndf

<ndf>
GROUPE_SEMANTIQUE AOW_CS_UPGRADE_BTR80_AA_CAPACITY_SEMANTIQUE
  Multiplicateur_DistanceAir = 1.5
  CoutTechno       = DefaultConst/EnsembleRessourceVide
  ApportTechno     = TEnsembleRessource :
    ElementRessourceListe =
    [
      TElementRessource ( RessourceGroup = $/defaultconst/Ressource_CS_UpgradeBTR80AACapacity    QuantiteRessource = 1 )
    ]
end
</ndf>

and : <GameDirectory>\datalight\DefaultNDF\Unites\ParametreSemantiques\_zAoW_XX_ParametresSemantiquesUpgrades_DoNotEdit.ndf

<ndf>
GROUPE_SEMANTIQUE AOW_CS_UPGRADE_BTR80_AA_CAPACITY_SEMANTIQUE
  TEMPS_PRODUCTION = 30
  COUT             = 1500
end
</ndf>

Unlock this upgrade via a Cheatcode

This functionnality is much more simple. Fist add a cheatcode like in exercises 1 and 2

In AOWCheatCode.ndf :

<ndf>
('superbtr80', $/DefaultConst/IsBTR80AAunlockedValue := TConditionNot( SubCondition = $/DefaultConst/IsBTR80AAunlocked ) ),
</ndf>

And in RessourceList.ndf :

<ndf>
export IsBTR80AAunlockedValue is TEugBBoolean( Value = false )
export IsBTR80AAunlocked is TAccesseurBooleanFromEUGBObject
(
   EUGBObject = IsBTR80AAunlockedValue
)
</ndf>

And in your CompetenceConstruire_Upgrade_BTR80AACapacity in Competence_CS.ndf, just add :

<ndf>ACCESSEUR_IS_AVAILABLE = $/DefaultConst/IsBTR80AAunlocked</ndf>

Exercise 5

First let's set a new additionnal property for the stealth.

In <GameDirectory>\AOW\DataLight\TypeWarrior\_Common\SpecialAptitude\properties.ndf add :

<ndf>
export AdditionalProperty_LastUseStealth is TAdditionalPropertyDate :
   PropertyName = $/DefaultConst/ObjectStringDateLastUseStealth
   MustMirror = True
</ndf>

In the file <GameDirectory>\datalight\DefaultNDF\System\ObjectConst.ndf  :

<ndf>
export ObjectStringDateLastUseStealth is TEUGBString :
  Value = 'DateLastUseStealth'
</ndf>

Add the additionnalproperty to the TypeWarrior_Aow_CS_Soldier : Replace

<ndf>AdditionalPropertyList = AdditionalPropertyList_SoldatBlessableSecourableUpgradable</ndf>

by

<ndf>AdditionalPropertyList = AdditionalPropertyList_SoldatBlessableSecourableUpgradable
                            + [ AdditionalProperty_LastUseStealth ]  
</ndf>

At the top of the file, to replace

<ndf>const 
     MODEL_ASE_PATH_AK74 = 'Data\XFiles3\AoW\Infanterie\AoW_CS_RegularSoldier\AOW_CS_RegularSoldier_' 
     MODEL_ASE_PATH_MM1 = 'Data\XFiles3\AoW\Infanterie\AoW_CS_MortarSoldier\AOW_CS_MortarSoldier_' 
     MODEL_ASE_PATH_RPG7 = 'Data\XFiles3\AoW\Infanterie\AoW_CS_RPGSoldier\AOW_CS_RPGSoldier_'
end</ndf>

by

const 
     MODEL_ASE_PATH_AK74 = 'Data\XFiles3\AoW\Infanterie\AoW_CS_RegularSoldier\AOW_CS_RegularSoldier_' 
     MODEL_ASE_PATH_MM1 = 'Data\XFiles3\AoW\Infanterie\AoW_CS_MortarSoldier\AOW_CS_MortarSoldier_' 
     MODEL_ASE_PATH_RPG7 = 'Data\XFiles3\AoW\Infanterie\AoW_CS_RPGSoldier\AOW_CS_RPGSoldier_'
     STEALTH_DURATION = 10
     STEALTH_RELOAD_DURATION = 15     
end

</pre>

Let's place our icon in the cube action and link it with the stealth action :

<ndf>
CS_AK74_Stealth is TemplateCompetenceActionInstantaneeEffetAvecChronographe :
   ICONE_X = AoW_CUBEACTION_DIM.COLONNE_2 
   ICONE_Y = AoW_CUBEACTION_DIM.LIGNE_3
   Texture = $/DefaultConst/AOW_STANDARD.PATH_ICONES + 'Competence\US\US_Upgrade_ReactiveArmor.tga'
   Caption = ''
   HINT = ''
   ACCESSEUR_IS_ENABLE = TAccesseurBooleanIsAdditionalPropertyDateDepasseeDepuisAuMoins :
                            AccesseurUnitBalise = $/DefaultConst/AccesseurUnitBaliseFromUnitBalise
                            PropertyName = $/DefaultConst/ObjectStringDateLastUseStealth
                            AccesseurTempsEcoule = TAccesseurRealConstante :
                                                      Value = STEALTH_RELOAD_DURATION
   Effet = TNewEffetDescriptorSurCible :
              AccesseurUnitBaliseList = AccesseurUnitBaliseList_FromContextForCompetence
              Effet = CS_AK74_UseStealth
   ACCESSEUR_REAL_PROGRESSION = Template_MeilleurAvancementFromSelectionEntre0Et1 :
                                   TypeWarriorConcerneAsString = 'TypeWarrior/TypeWarrior_Aow_CS_Soldier'
                                   AdditionalPropertyString = $/DefaultConst/ObjectStringDateLastUseStealth
                                   RealTempsDelai = STEALTH_RELOAD_DURATION
</ndf>

Let's define our stealth action :

<ndf>
CS_AK74_UseStealth is SEQ with
[
   TEffetResetDateAdditionalProperty :
      AccesseurUnitBalise = $/DefaultConst/SelfUnitBalise 
      PropertyName = $/DefaultConst/ObjectStringDateLastUseStealth
   ,
   TEffetFireAndForgetSurCible :
      AccesseurUnitBalise = $/DefaultConst/SelfUnitBalise
      Effet =    COMPET with
                 [
                    TWaitPrecis :
                       DureeEnSecondes = STEALTH_DURATION
                    ,
                    Template_UniteStealth :
                       Aggressif = False
                       CONDITION_SUP = $/DefaultConst/ConditionAlwaysTrue
                    ,
                    AffichageChrono is SEQ :
                       Support = TGraphicCaracTextBox :
                                    Material = $/m3d/Shader/MaterialLegacy_AlphaDetail_NoZClipping
                                    TranslateX = -40
                                    TranslateY = -35
                                    SizeX = 20
                                    Sizey = 20
                                    Pure2D = True
                                    Caption = ''
                                    calqueLevel = 1
                                    Font = $/Default3D/AOW_Font_EurostileExtendedBold_14
                                    R = 100
                                    G = 255
                                    B = 255
                                    A = 255
                                    TextFormatProperties = $/Default3D/StandardTextFormatPropertiesCenter
                    with
                    [
                       TTextBoxModificator :
                          DureeEnSecondes = 10000000
                          AccesseurString = TAccesseurStringFromReal :
                                               AccesseurReal = TAccesseurRealSub :
                                                                  RealList = [
                                                                                STEALTH_DURATION,
                                                                                TAccesseurRealSub :
                                                                                   RealList = [
                                                                                                 TAccesseurDateEnSecondes(),
                                                                                                 TAccesseurDateFromAdditionalProperty :
                                                                                                    AccesseurUnitBalise = $/DefaultConst/SelfUnitBalise
                                                                                                    PropertyName = $/DefaultConst/ObjectStringDateLastUseStealth
                                                                                              ]
                                                                             ]
                                               NbDigit = 3
                                               UseExtended = True
                          EveryTurn = True
                    ]   
                 ]
]
</ndf>

Now, add the skill to your AK74 soldier (named CS_AK74_MUSD).

Replace :

<ndf>COMPETENCE_LIST = AoW_CompetenceListStandardSoldatCaptureur</ndf>

by :

<ndf>
   COMPETENCE_LIST = AoW_CompetenceListStandardSoldatCaptureur
                     +
                     [ CS_AK74_Stealth/CompetenceActionInstantanee ]
</ndf>