Objects & Modules - Andreas-W/GeneralsGameCode_Modding GitHub Wiki

Object Improvements

WeaponSet

Added new parameter to an object's WeaponSet definition

  • WeaponReloadSharedAcrossSets = No - If a unit switched between weaponset, it's reload time and ammo count (in percent) will be kept. For instance Migs will not reload in air when they get BlackNapalm.

AutoChooseSources

Added new types for AutoChooseSources

  • SYNC_TO_PRIMARY - This weapon slot cannot fire on its own, but will be fired whenever PRIMARY is fired.
  • SYNC_TO_SECONDARY - This weapon slot cannot fire on its own, but will be fired whenever SECONDARY is fired.
  • SYNC_TO_TERTIARY - This weapon slot cannot fire on its own, but will be fired whenever TERTIARY is fired.

Syncs a weapon slot to another. The weapon slot cannot be used except when it's parent weapon is fired. This ignores all conditions and checks of the synced weapon.

Example:

Weapon = PRIMARY MainWeapon
Weapon = SECONDARY SyncedWeapon
AutoChooseSources = SECONDARY SYNC_TO_PRIMARY

In this example, the secondary weapon SyncedWeapon will not be used on its own. Whenever the unit attacks with its primary MainWeapon, the secondary weapon will be fired as well. This can be used for Aircraft to reliably fire multiple weapons on each attack.

AmmoPips style

Added options to customize Ammo Pips, e.g. for Aircraft with a very large clip size.

Added a new parameter for object definitions:

  • AmmoPipsStyle = DEFAULT - (Change the unit's display style for ammo pips to one of these:)
    • DEFAULT - default ZH style; 1 yellow pip symbol for each shot.
    • PERCENTAGE_BAR - display a yellow bar similar to the health bar, showing the ammo count in percent.
    • SINGLE - default ZH pip visuals, but only show a single symbol regardless of clip size. Ammo count is displayed via fading yellow color.

Note: This parameter might be moved to individual weapons in the future, to allow displaying ammo pips for multiple weapon slots at once.

Object Modules

AIUpdateInterface (And all other AIUpdate types)

New experimental parameter:

  • PreferredAttackAngle = <angle> [MIRRORED] - (mirrored keyword is optional) When a unit turns to attack, it will attempt to turn to this angle. If mirrored is enable it can also use the same angle +180°. Possibly useful for battleship setups with multiple turrets. Only works for locomotors that can turn in place (minTurnSpeed = 0) Note: this is NOT needed for limited turret angles (See below). Units will follow the actual turret angles when trying to attack.

Turret

New paramters for Turret or AltTurret entries

  • MinTurretAngle = 0 - Minimum angle the turret is allowed to turn
  • MaxTurretAngle = 0 - Maximum angle the turret is allowed to turn Notes:
  • for backwards facing configurations, MaxTurretAngle can be > MinTurretAngle; Currently this is not working 100% reliably
  • Remove the angle limit lines to use unlimited angle. A value of 0 will use 0 as limit.
  • If the turret cannot turn to the front (e.g. side mounted gun on a helicopter), the unit will attempt to turn to the turret's firing arc
    • this feature only works for locomotors that can turn in place (minTurnSpeed = 0)

WeaponSetUpgrade

Added new parameters for WeaponSetUpgrade

  • WeaponSetFlag = <WeaponSetFlag> - define which Weaponset to enable (default = PLAYER_UPGRADE)
  • WeaponSetFlagsToClear = <WeaponSetFlag1> <WeaponSetFlag2> .. - define which Weaponsets to disable
  • NeedsParkedAircraft = No - Units with JetAIUpdate need to be parked in hangar to research this upgrade

Notes: WeaponSetFlagsToClear can be used to switch between WeaponSets using multiple upgrades. example:

  Behavior = WeaponSetUpgrade ModuleTag_04a
    WeaponSetFlag = PLAYER_UPGRADE
    WeaponSetFlagsToClear = PLAYER_UPGRADE2 PLAYER_UPGRADE3
    TriggeredBy = Upgrade_GLAWorkerFakeCommandSet
    RemovesUpgrades = Upgrade_GLAWorkerRealCommandSet Upgrade_GLAWorkerFakeCommandSet Test_Upgrade_DummyToggle
  End
  
  Behavior = WeaponSetUpgrade ModuleTag_04b
    WeaponSetFlag = PLAYER_UPGRADE2
    WeaponSetFlagsToClear = PLAYER_UPGRADE PLAYER_UPGRADE3
    TriggeredBy = Upgrade_GLAWorkerRealCommandSet
    RemovesUpgrades = Upgrade_GLAWorkerRealCommandSet Upgrade_GLAWorkerFakeCommandSet Test_Upgrade_DummyToggle
  End
  
  Behavior = WeaponSetUpgrade ModuleTag_04c
    WeaponSetFlag = PLAYER_UPGRADE3
    WeaponSetFlagsToClear = PLAYER_UPGRADE PLAYER_UPGRADE2
    TriggeredBy = Test_Upgrade_DummyToggle
    RemovesUpgrades = Upgrade_GLAWorkerRealCommandSet Upgrade_GLAWorkerFakeCommandSet Test_Upgrade_DummyToggle
  End

You can combine this with NeedsParkedAircraft to allow Jets to switch their ammo type when parked using multiple object upgrades.

ArmorUpgrade

Added new parameters for ArmorUpgrade

  • ArmorSetFlag = <ArmorSetFlag> - define which Armorset to enable (default = PLAYER_UPGRADE)
  • ArmorSetFlagsToClear = <ArmorSetFlag1> <ArmorSetFlag2> .. - define which ArmorSets to disable

Notes: ArmorSetFlagsToClear can be used to switch between ArmorSets using multiple upgrades (see WeaponSetUpgrade).

LocomotorSetUpgrade

Added new parameter for LocomotorSetUpgrade

  • EnableUpgrade = No - (if 'Yes' (default), locomotor is switched to SET_NORMAL_UPGRADED; if 'No' locomotor is switched back to SET_NORMAL)

Notes: This only allows for a single locomotor upgrade, but it can be toggled on/off with multiple upgrades. Freely selecting Locomotor sets might be added as well in the future, but there are currently some issues, as they wouldn't be persistent in some cases.

MaxHealthUpgrade

Added new parameter for MaxHealthUpgrade

  • MultiplyMaxHealth = 1.0 - (multiplier on the unit's current HP; default = 1.0 -> no change.)

Notes:

  • It is recommended to change all health upgrades to multiplicative as they will not be affected by other HP changes like veterancy, and can be freely stacked (and even reversed).
  • You can still use AddMaxHealth for additive boni, and could even combine it with MultiplyMaxHealth. The formula is NewHP = (CurrentHP * MultiplyMaxHealth) + AddMaxHealth.

ArmorDamageScalarUpdate (New)

This module was designed for a temporary armor buff ability. The module will apply a damage/armor scale value to every unit in the area for the given amount of time. In addition, various visual effects can be added.

example:

Behavior = ArmorDamageScalarUpdate ModuleTag_01
    AllowedAffectKindOf = VEHICLE STRUCTURE  ; (required; any object matching *any* of these KindOfs is a valid target)
    ForbiddenAffectKindOf = INFANTRY  ; (optional; any object matching *any* of these KindOfs is an invalid target)
    AffectsTargets = ALLIES NEUTRALS  ; (required; any combination of ALLIES, NEUTRALS, ENEMIES)
    AffectAirborne = Yes   ; (default = Yes; Should this affect units currently in the air) 
    BonusDuration = 10000     ; (required; How long effect lasts, in ms)
    BonusRange = 100     ; (required; Radius of the effect)
    ArmorDamageScalar = 0.9;   ; (default = 1.0; damage scalar to apply; 1.0 = no effect; 0.5 = takes half damage; 2.0 = takes double damage; min = 0.01)
    EffectParticleSystem = <entry from particlesystem.ini>  ; (optional; apply particlesystem to affected objects. SystemLifeTime is scaled automatically. If VolumeType = BOX, the size will be changed to the object's geometry.)
    OverrideDamageFX = <entry from damageFX.ini> ; (optional; change the object's DamageFX to this entry over the duration)
    ScaleParticleSystem = Yes  ; (default = No; If enabled, the particle system's spawn rate will be adjusted for the object's size)
    ApplyColorTint = Yes  ; (default = No; Apply a dark red color tint to the objects for the duration)
End

Notes:

  • This module is designed to be put on a dummy object marker, like for EmergencyRepair or Frenzy.
  • To correctly track the objects over the duration, the marker object needs to stay alive for the duration. Lifetime is tracked in the module itself. You do not need to add a lifetimeupdate as well. If the object is killed earlier, the effect will be removed from all units.
  • The effect is applied once at the beginning. Objects leaving or entering the radius later will not get the effect.
  • The module can be used to apply a damage increase to enemy units (i.e. lower their armor)

CostModiferUpgrade

New Parameters added. Example:

Behavior = CostModiferUpgrade ModuleTag_123
  TriggeredBy = Upgrade_CostReduction  ; entry from upgrade.ini
  EffectKindOf = VEHICLE  ; Units with this KindOf will be affected
  Percentage = -20%  ; amount that cost will be reduced
  IsOneShotUpgrade = No  ; (NEW) Is this a one time global upgrade, or should it be removed when the object dies or changes owner?
  BonusStacksWith = DIFFERENT_VALUE  ; (NEW) Stacking behavior when multiple bonus sources exist
End

** BonusStacksWith types **

  • DIFFERENT_VALUE - Default behavior: Does not stack with other bonus with the same value. Does stack with bonus with different value.
  • OTHER_TYPE - Does stack with bonus from other type of unit with the same value. Does not stack with bonus from the same type of unit. I.e. Multiple OilRefineries would not stack, but a Refinery would stack with an IndustrialPlant if it had the same value.
  • SAME_TYPE - Bonus from multiple sources of the same type will stack. I.e. Owning multiple Refineries grants additional bonus.

Notes:

  • Bonus stacking is additive, not multiplicative

ProductionTimeModiferUpgrade (New)

This works just like CostModiferUpgrade (Oil Refinery) to apply a global production time reduction for the given KindOf example:

Behavior = ProductionTimeModifierUpgrade ModuleTag_123
  TriggeredBy = Upgrade_CostReduction  ; entry from upgrade.ini
  EffectKindOf = VEHICLE  ; Units with this KindOf will be affected
  Percentage = -20%  ; amount that build time will be reduced
  IsOneShotUpgrade = No  ; Is this a one time global upgrade, or should it be removed when the object dies or changes owner?
  BonusStacksWith = DIFFERENT_VALUE  ; Stacking behavior when multiple bonus sources exist
End

ExperienceScalarUpgrade

Added new parameter to modify XP value of a unit (i.e. XP that is gained for the enemy when the unit is killed)

  • AddXPValueScalar = 0.0 - Additive modifier for XP value scalar. I.e.: XPValueNew = XPValueOld * (1.0 + AddXPValueScalar).

Laser Improvements

LaserUpdate

New parameters are added to allow the laser to grow/shrink or fade in/out

  • BeamFadeInDuration = 0 - (time in ms. Alpha scalar is linear interpolated from 0 to 1 over the given time at the start.)
  • BeamFadeOutDuration = 0 - (time in ms. Alpha scalar is linear interpolated from 1 to 0 at the end of the beam's lifetime. Requires LifetimeUpdate)
  • BeamGrowDuration = 0 - (time in ms. Beam width is linear interpolated from 0 to 1 over the given time at the start.)
  • BeamShrinkDuration = 0 - (time in ms. Beam width is linear interpolated from 1 to 0 at the end of the beam's lifetime. Requires LifetimeUpdate)
  • UseMultiLaserDraw = No - (This flag is needed, if a Laser object has multiple LaserDraw modules, to correctly update all of them)
  • UseHouseColoredParticles = No - (Apply house colored tint to the laser's muzzle and target particle systems)

W3DLaserDraw

Added parameters to specify grid animation. Currently only a 1xn grid is allowed (i.e. multiple columns) to work together with scrollRate.

  • TextureGridTotalColumns = 1 - (total number of columns in the texture)
  • TextureGridColumns = 1 - (actual number of columns used for the animation)
  • UseHouseColorOuter = No - (apply house color to the laser's outer color)
  • UseHouseColorOuter = No - (apply house color to the laser's inner color)

Note: Usually both TextureGridColumns and TextureGridTotalColumns numbers would be the same. But having separate numbers allows to use an odd number of frames and still keep proper DDS texture sizes. E.g. you have a texture width of 512, with 8 frames of 64. But you only want 7 frames, so you can set TextureGridTotalColumns=8 and TextureGridColumns=7.

MissileAIUpdate

Added new parameters to MissileAIUpdate module:

  • RandomPathOffset = 0.0 - distance in meters. Missile projectils will spread out randomly to fly a random arc pattern for more interesting visuals.

  • ZCorrectionFactor = 2.0 - Missiles attacking air units will have their direction shifted upwards by this factor. (2.0 is vZH default)

  • ApplyLauncherBonus = No - Any extra weapon that is fired from the projectile (On death, fireweaponupdate, etc.) will inherit the shooter's weapon bonus values

Notes:

  • ZCorrectionFactor is what causes AA missiles in vZH to be never aligned to the launcher. For units with actual fire pitch (e.g. Patriot), it is recommended to set this value to 0. For units that cannot pitch (e.g. Missile Defender) a value between 1 and 2 is recommended.

DumbProjectileBehavior

New parameters:

  • ApplyLauncherBonus = No - Any extra weapon that is fired from the projectile (On death, fireweaponupdate, etc.) will inherit the shooter's weapon bonus values

FreeFallProjectileBehavior

New type of projectile module that mimics the behavior of Bombs dropped by genpowers. Projectiles will move based on physics, making it suitable for carpet bomb or strafing run aircraft weapons. On collision, the weapon's damage and detonation effects are applied.

Example:

Behavior = FreeFallProjectileBehavior ModuleTag_009
   MaxLifespan = 10000  ; Maximum lifetime of the object
   TumbleRandomly = No  ; Adds random rotation, same as for DumbProjectileBehavior
   CourseCorrectionScalar = 1.0   ; guide the bomb towards the intended target. 1=no homing, 0=snapto; 0.99=smooth, 0.95=too-fast
   UseWeaponSpeed = No   ; apply additional speed from the unit's weapon
   ExitPitchRate = 0 ; Angle tilt per second to apply (respects centerOfMassOffset in the projectile's physics)
   ApplyLauncherBonus = Yes  ; Apply weapon bonus from launcher for any secondary weapon effects
   DetonateOnGround = Yes   ; Will the projectile detonate when hitting the ground or live on (to bounce or rest on ground)?
   DetonateOnCollide = Yes    ; Same as above, when hitting another object (See Weapon for collission settings)
   GarrisonHitKillRequiredKindOf = <Kindof list>  ; Same as MissileAI/DumbProjectile
   GarrisonHitKillForbiddenKindOf= <Kindof list>  ; Same as MissileAI/DumbProjectile
   GarrisonHitKillCount = 0  ; Same as MissileAI/DumbProjectile
   GarrisonHitKillFX = <FXList>  ; Same as MissileAI/DumbProjectile
End

Notes:

  • This module's behavior depends a lot on the projectile's physics settings, such as mass, friction, etc. It takes some finetuning to get the exact behavior you want.
  • For basic carpet bombing, you can copy the settings from existing genpowers.

ScatterShotUpdate (New)

New module intended for weapon projectiles, to allow scattering in mid air and fire multiple shots to targets within range.

Parameters:

  • Weapon = - (The weapon to be fired at targets.)
  • NumShots = - (default = 0; number of shots to fire)
  • TargetSearchRadius = - (default = 0; range around the weapon's target location or object that we look for targets)
  • TargetMinRadius = - (default = 0; minimum range targets need to be away from the original target)
  • MaxShotsPerTarget = - (default = 0; How many shots to fire at each target. 0 = randomly attack ground only; 1 = attack each target once; >1 when each target was attacked once, start from the beginning)
  • PreferSimilarTargets = - (default = No; Choose air or ground targets similar to the main target object. I.e. if we attack an air unit, all targets will be picked from air units first)
  • PreferNearestTargets = - (default = No; Prefer targets closest to the original target; Otherwise choose randomly)
  • NoTargetsScatterRadius = - (default = 0; If not targets were found/picked, use this random scatter radius to attack the ground)
  • AttackGroundWhenNoTargets = - (default = yes; If Yes, when we run out of targets, fire randomly at the ground; If No, do not fire.)
  • TriggerDistanceToTarget = - (default = 0; How close the projectile needs to be to the target to trigger the scatter shot.)
  • TriggerLifetime = - (default = 0; How long after the projectile was created to trigger the scatter shot. 0 = no limit.)
  • TriggerOnImpact = - (default = No; Trigger scatter shot on projectile impact.)
  • TriggerInstantly = - (default = No; Trigger scatter shot instantly after the projectile was created)
  • StayAliveAfterTrigger = - (default = No; The original weapon's projectile will stay alive after the scatter shot was triggered.)
  • TriggeredDeathType = - (default = NORMAL; The death type to use for the projectile object when the scatter shot is triggered.)
  • ScatterFX = - (default = None; entry from FXList.ini to play when scatter shot is triggered.)

Notes:

  • The weapon used for the scatter shot needs to have a clip size large enough to fire all shots.
  • When picking targets for the scatter shots, they need to be viable targets for the weapon's damage type.
  • When the original weapon targets an object, that original target will always be picked to fire a scatter weapon at.
  • This module can be used on non-projectile objects as well (using lifetime or instant triggers), e.g. to create an object that fires at multiple units in range simultaneously

Contain Modules

Added new features for all contain modules. WeaponBonus types that are passed to passengers can now be configured.

  • PassengerWeaponBonusList = <BONUS1> <BONUS2> - (provide a list of WeaponBonus types that will be applied to the contained objects)

Default values:

  • GarrisonContain: GARRISONED
  • TransportContain: CONTAINED

Setting PassengerWeaponBonusList = None will override the default value.

Note: HelixContain grants GARRISONED to its passengers in vanilla ZH. This is changed to CONTAINED. To restore vanilla behaviour you will need to manually set the bonus here.

RadiusDecalBehavior (New)

New module to create a radius decal that follows a unit. Can be triggered via upgrade.

Example:

Behavior = RadiusDecalBehavior ModuleTag_decal1
    TriggeredBy = <Upgrade entry>  ; Optional
    ; < All other basic upgrade entries (ConflictsWith, RemovesUpgrades, FXListUpgrade, RequiresAllTriggers) >
    StartsActive = No  ; Set to yes, to enable initially
    Radius = 100.0 ; (radius in meters)
    RadiusDecal   ; Decal Template, Same parameters as DeliveryDecal in OCL ini
      Texture           = SCCFuelAirBomb_USA   ; Texture name
      Style             = SHADOW_ALPHA_DECAL   ; SHADOW_DECAL, SHADOW_ALPHA_DECAL or SHADOW_ADDITIVE_DECAL
      OpacityMin        = 25%    ; default = 100%, Opacity will move between min and max
      OpacityMax        = 50%    ; default = 100%
      OpacityThrobTime  = 500    ; default = 1000
      Color             = R:255 G:0 B:0 A:255 
      OnlyVisibleToOwningPlayer = Yes     ; Disable to make the decal visible to all players
      End
  End

Note: This module reacts to the upgrade being removed (by a different upgrade). This means you can make the decal toggle on/off.

ParkingPlaceBehavior

Added new features and parameters to ParkingPlaceBehavior (Airfield)

  • ParkedUnitsDamageScalar = 1.0 - scalar for damage taken applied to all parked aircraft (0.9 = only take 90% of damage)
  • ParkedUnitsDamageScalarUpgraded = 1.0 - same as above, after upgrade
  • DamageScalarUpgradedTriggeredBy = <upgrade name> - upgrade to trigger the upgraded scalar value
  • RequiredKindOf = <KindOf list> - if set, only aircraft that has these KindOfs is allowed to dock here
  • ForbiddenKindOf = <KindOf list> - if set, aircraft that has these KindOfs is not allowed to dock here.

Notes:

  • ParkedUnitsDamageScalar can be used to apply an upgrade that grants damage protection to parked aircraft
  • Required/Forbidden KindOf can be used to allow only specific kinds of aircraft to land (i.e. to use different sizes, or differ between VTOL/Regular jets)

UnitProductionBonusUpgrade (New)

This upgrade module allows to set a cost and/or build time modifier for individual types of units. This affects the whole player and not just individual factories.

Parameters:

  • <All common upgrade params; e.g. TriggeredBy>
  • CostModifierPercentage = 0 - Percentage amount that the unit's costs are modified
  • BuildTimeModifierPercentage = 0 - Percentage amount that the unit's build time is modified
  • UnitTemplateName = <Name of an Object> - The unit to apply this bonus to. (multiple lines are allowed)

Example

Behavior = UnitProductionBonusUpgrade ModuleTag_01
  TriggeredBy = Upgrade_CostReduction   ; The upgrade trigger
  CostModifierPercentage = -40%    ; Cost is reduced by 40%
  BuildTimeModifierPercentage = -80%    ; Build time is reduced by 80%
  UnitTemplateName = Tank_ChinaInfantryRedguard    ; The units this bonus applies to
  UnitTemplateName = Tank_ChinaTankBattleMaster
End

Notes

  • This upgrade is currently not removable, i.e. it will not work like the CostModifierUpgrade module for Tech OilRefinery. It's only suitable as a global upgrade for now

WeaponBonusUpdate

Added Parameters:

  • AffectsTargets = [ALLIES/ENEMIES/NEUTRALS] ; Allows applying a bonus to enemies
  • AffectsAirborne = Yes ; allow/disallow the bonus be applied to currently airborne units
  • TintStatusType = [TINT_STATUS type] ; which color tint to apply

TeleporterAIUpdate (New - EXPERIMENTAL)

** Warning: This module is experimental, i.e. it is not fully tested and might undergo revisions**

AIUpdate module designed to work like a Chrono Legionnaire in RA2. I.e. The unit teleports instead of moving normally, and needs to recharge depending on the distance it teleported. ** Note: Currently this module is only working properly for infantry units. It currently does not work properly for vehicles and it is not certain it ever will.**

Example:

Behavior = TeleporterAIUpdate ModuleTag_123
   TeleportStartFX = [FXList entry] ; FX to play at the unit's previous position when it teleports
   TeleportTargetFX = [FXList entry] ; FX to play at the unit's target position when it teleports
   TeleportRecoverEndFX = [FXList entry] ; FX to play on the unit, when it has finished recovering
   MinDistanceForTeleport = 20.0  ; distance in which the unit moves normally instead of teleporting
   DisabledDurationPerDistance = 10.0 ; How long the unit will need to recover, linear to the distance (in MS per distance). Recommended values = 5-10. 
   TeleportRecoverSoundAmbient = [AudioEvent entry] ; Ambient sound played on the unit while it recovers from a teleport.
   TeleportRecoverOpacityStart = 0.1  ; Unit maximum transparency when it starts to recover.
   TeleportRecoverOpacityEnd = 0.8  ; Unit minimum transparency when it has finished recovering.
   TeleportRecoverTint = TELEPORT_RECOVER  ; Color tint status to apply while recovering
   [entries from AIUpdate]
End

When a unit is recovering from a teleport, the conditionstate TELEPORT_RECOVER is set. Note: In most cases, the unit will also be MOVING after a teleport, so it's recommended to define both states.

Misc Improvements

ObjectExtend

Allows to use inheritence in the parser. ObjectExtend is similar to ObjectReskin but inherit all modules and allow modifications. The parent object must be defined before the ObjectExtend.

Syntax: ObjectExtend NewObject ObjectToInheritFrom

Use RemoveModule ModuleTag_xx to remove a module inherited from the parent.
WeaponSet and ArmorSet are inherited, but if you define another one in the child, the inherited sets are removed.
If the parent has multiple WeaponSets all will be removed from the child if the child defines one.

Examples:

ObjectExtend ZExtendedTank Chem_GLAVehicleRadarVan  
  ; *** ART Parameters ***  
  SelectPortrait = SNHacker2_L ;define other icons  
  ButtonImage = SNHacker2  
    
  RemoveModule ModuleTag_01 ; Remove the parent's draw  
  
  Draw = W3DTankDraw ModuleTag_1337 ; add a new draw  
    OkToChangeModelColor = Yes  
    DefaultConditionState  
      Model = NVInferno  
      Turret = Turret  
      TurretPitch = TurretEL01  
      WeaponFireFXBone = PRIMARY Muzzle  
      WeaponRecoilBone = PRIMARY Barrel  
      WeaponLaunchBone = PRIMARY Muzzle  
      HideSubObject = PARTSUP TurretEl02  
      ShowSubObject = TurretEL01 TURRETPARTS  
    End  
    ConditionState = RUBBLE REALLYDAMAGED  
      Model = NVInferno_D  
    End  
    TrackMarks = EXTnkTrack.tga  
    TreadAnimationRate = 2.0  
  End  
  Draw = W3DModelDraw ModuleTag_0123 ; add a second draw (tree on top)  
    DefaultConditionState  
      Model = PTOak01  
    End  
  End  
  Prerequisites ; change the prerequisites  
    Object = Tank_ChinaCommandCenter TEST_MODE  
  End  
  WeaponSet ; define new weaponset, all parent inherited weapons are cleared  
    Conditions = None  
    Weapon = PRIMARY Tank_InfernoCannonGun  
  End  
  RemoveModule ModuleTag_Stealth ; Remove the stealth update inherited from the parent  
End  
ObjectExtend ZExtendedTank2 ZExtendedTank  ; inherit again
  RemoveModule ModuleTag_0123  ; remove the tree draw
  WeaponSet  ; replaces all weaponset
    Conditions = None  
    Weapon = PRIMARY MarauderTankGun  
  End  
  ArmorSet  ; replaces all armor sets
    Conditions = None  
    Armor = TruckArmorExtended  
    DamageFX = TankDamageFX  
  End  
End  
⚠️ **GitHub.com Fallback** ⚠️