Формат файла мода. Файл мода - обычный xml файл. Корневой элемент - тэг Mod. Другими словами любой файл мода имеет следующий вид:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="имя базового xml файла">
<!-- Тут содержимое -->
</Mod>
1. Тэг Mod имеет один обязательный атрибут BaseFile - относительный или абсолютный путь к базовому файлу.
Базовый файл - стандартный xml файл из игры. К примеру, C:/Program Files/Worms/data/Tweak/Local.xml
Пример:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="C:/Program Files/Worms/data/Tweak/Local.xml">
<!-- Тут содержимое -->
</Mod>
В W4TweakGen для стандартных файлов выделена папка base, а для файлов модов samples,
поэтому, если в папке base лежит копия стандартного файла, а файл мода находится в samples,
то в атрибуте BaseFile можно написать относительный путь ../base/Local.xml
То есть это будет выглядеть так:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Local.xml">
<!-- Тут содержимое -->
</Mod>
Внутри тэга Mod разрешены следующие тэги:
Remove
Int
Uint
Float
String
Color
Vector
Любой другой тэг.
1.1. Тэг Remove нужен для удаления из базового файла каких либо контейнеров.
Под удалением понимается удаление ссылки на контейнер в разделе XDataBank и самого контейнера из xomObjects.
Тэг Remove не имеет атрибутов.
Внутри тэга Remove пишется id контейнера, который надо удалить.
К примеру, чтобы удалить из базового файла Tweak.xml контейнер с id='Ninja.NumShoots'.
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Tweak.xml">
<Remove>Ninja.NumShoots</Remove>
</Mod>
Можно указать любой id. Если это id контейнера XContainerResourceDetails, то удаляется и тот контейнер, на который ссылается XContainerResourceDetails.
К примеру, вот фрагмент файла Local.xml:
Code
...
<FlagDataContainer id='Flag.OldWorm-0'>
<TextResource>FETXT.Flag.OldWorm</TextResource>
<TargaName>Custom OldWorm</TargaName>
</FlagDataContainer>
<XContainerResourceDetails id='Flag.Pakistan'>
<Value href='Flag.Pakistan-0'/>
<Name>Flag.Pakistan</Name>
<Flags>80</Flags>
</XContainerResourceDetails>
<FlagDataContainer id='Flag.Pakistan-0'>
<TextResource>FETXT.Flag.Pakistan</TextResource>
<TargaName>Pakistan</TargaName>
</FlagDataContainer>
<XContainerResourceDetails id='Flag.Poland'>
<Value href='Flag.Poland-0'/>
<Name>Flag.Poland</Name>
<Flags>80</Flags>
</XContainerResourceDetails>
...
Если написать следующий мод:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Local.xml">
<Remove>Flag.Pakistan</Remove>
</Mod>
то будут удалены контейнеры <XContainerResourceDetails id='Flag.Pakistan'> и <FlagDataContainer id='Flag.Pakistan-0'>
Получим такой результат:
Code
...
<FlagDataContainer id='Flag.OldWorm-0'>
<TextResource>FETXT.Flag.OldWorm</TextResource>
<TargaName>Custom OldWorm</TargaName>
</FlagDataContainer>
<XContainerResourceDetails id='Flag.Poland'>
<Value href='Flag.Poland-0'/>
<Name>Flag.Poland</Name>
<Flags>80</Flags>
</XContainerResourceDetails>
...
Если же написать
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Local.xml">
<Remove>Flag.Pakistan-0</Remove>
</Mod>
то будет удалён только один контейнер <FlagDataContainer id='Flag.Pakistan-0'>Получим такой результат:
Code
...
<FlagDataContainer id='Flag.OldWorm-0'>
<TextResource>FETXT.Flag.OldWorm</TextResource>
<TargaName>Custom OldWorm</TargaName>
</FlagDataContainer>
<XContainerResourceDetails id='Flag.Pakistan'>
<Value href='Flag.Pakistan-0'/>
<Name>Flag.Pakistan</Name>
<Flags>80</Flags>
</XContainerResourceDetails>
<XContainerResourceDetails id='Flag.Poland'>
<Value href='Flag.Poland-0'/>
<Name>Flag.Poland</Name>
<Flags>80</Flags>
</XContainerResourceDetails>
...
Действие тэга Remove распространяется только на базовый файл! Если вы создаёте новый контейнер,
и пытаетесь его удалить, то ничего не выйдет.
1.2. Тэги Int,Uint,Float,String,Vector и Color
Предназначены для создания тех типов данных, которые не используют XContainerResourceDetails.
У каждого из этих тэгов имеется обязательный атрибут id. Он указывает, какой id должен иметь
созданный контейнер.
Внутри тэгов Int,Uint,Float и String просто пишется значение:
Code
<Int id="the.integer">-356</Int>
<Uint id="unsigned.number">55</Uint>
<Float id="some.float">0.3</Float>
<String id="txtGerich">Герыч</String>
Vector и Color немного посложнее:
Code
<Vector id="pos">
<x>3</x>
<y>20</y>
<z>0</z>
</Vector>
Code
<Color id="transparentred">
<r>255</r>
<g>0</g>
<b>0</b>
<a>128</a>
</Color>
Внутренние тэги у тэгов Vector и Color необязательные, по умолчанию принимаются равными 0.
Пример. Такой мод:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Local.xml">
<String id="txtGerich">Герыч</String>
</Mod>
Добавит в базовый файл Local.xml в раздел XDataBank следующую строчку:
Code
...
<StringResources href='txtGerich'/>
...
а в конце xomObjects
Code
...
<XStringResourceDetails id='txtGerich'>
<Name>'txtGerich'</Name>
<Value>Герыч</Value>
<Flags>80</Flags>
</XStringResourceDetails>
...
Важная особенность: если при создании контейнера вы указываете id контейнера из базового файла,
то он будет заменён на ваш контейнер.
К примеру следующий мод просто изменит значение Jetpack.InitFuel с 7500 на 30000
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Tweak.xml">
<Int id="Jetpack.InitFuel">30000</Int>
</Mod>
1.3. Остальные тэги.
Если написать любой другой тэг внутри тэга Mod, то он воспринимается как новый контейнер,
который надо добавить в базовый файл.
Обязательным атрибутом является id.
Пример:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Local.xml">
<FlagDataContainer id='Flag.Gerich'>
<TextResource>txtGerich</TextResource>
<TargaName>Gerich</TargaName>
</FlagDataContainer>
</Mod>
Такой мод добавит в результате строчку в XDataBank:
Code
...
<ContainerResources href='Flag.Gerich'/>
...
и создаст 2 контейнера: сам FlagDataContainer и XContainerResourceDetails, ссылающийся на него.
В итоге получим:
Code
...
<XContainerResourceDetails id='Flag.Gerich'>
<Value href='Flag.Gerich-0'/>
<Name>Flag.Gerich</Name>
<Flags>80</Flags>
</XContainerResourceDetails>
<FlagDataContainer id='Flag.Gerich-0'>
<TextResource>txtGerich</TextResource>
<TargaName>Gerich</TargaName>
</FlagDataContainer>
...
Иногда не надо добавлять ссылку в XDataBank и не надо делать XContainerResourceDetails.
Для этого надо предназначен атрибут header. Если он равен 'no', то не будет
генерироваться заголовок и XContainerResourceDetails:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Local.xml">
<FlagDataContainer id='Flag.Gerich' header='no'>
<TextResource>txtGerich</TextResource>
<TargaName>Gerich</TargaName>
</FlagDataContainer>
</Mod>
В результате получим:
Code
...
<FlagDataContainer id='Flag.Gerich'>
<TextResource>txtGerich</TextResource>
<TargaName>Gerich</TargaName>
</FlagDataContainer>
...
Для собственных тэгов действует то же правило, что и для Int, Uint и т.д:
если при создании контейнера вы указываете id контейнера из базового файла,
то он будет заменён на ваш контейнер.
Часто 2 однотипных контейнера отличаются одним-двумя тэгами.
Если каждый раз копировать содержимое тэга полностью можно устать, запутаться и ошибиться.
Для этого контейнеру можно задать атрибут base. Он указывает id того элемента, на основе которого будет
будет создан новый контейнер.
Пример:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Local.xml">
<FlagDataContainer id='Flag.Gerich' base='Flag.RussianFederation'/>
</Mod>
Тут мы создаём новый контейнер - копию контейнера Flag.RussianFederation, но с другим id. При этом контейнер Flag.RussianFederation удалён/заменён или изменён не будет. Теперь изменим полученную копию:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/Local.xml">
<FlagDataContainer id='Flag.Gerich' base='Flag.RussianFederation'>
<TextResource>txtGerich</TextResource>
</FlagDataContainer>
</Mod>
Этот код изменит копию, заменив значение тэга TextResource, то есть у этого флага будет та же картинка, но другое название. Рассмотрим ещё несколько задач, решаемых с помощью W4TweakGen, на примере работы с контейнерами эффектов в файле PartTwk.xml.
Code
...
<XContainerResourceDetails id='WXP_MeshBang_HotCoreLarge'>
<Value href='WXP_MeshBang_HotCoreLarge-0'/>
<Name>WXP_MeshBang_HotCoreLarge</Name>
<Flags>81</Flags>
</XContainerResourceDetails>
<ParticleEmitterContainer id='WXP_MeshBang_HotCoreLarge-0'>
<Comment></Comment>
<EmitterType>0</EmitterType>
<SpriteSet>Particle.WXSprite3</SpriteSet>
<MeshAnimNodeName></MeshAnimNodeName>
<EmitterAcceleration x='0' y='0' z='0' />
<EmitterAccelerationRandomise x='0' y='0' z='0' />
<EmitterIsAttachedToLand>false</EmitterIsAttachedToLand>
<EmitterIsOfInterest>false</EmitterIsOfInterest>
<EmitterIsLaunchedFromWeapon>false</EmitterIsLaunchedFromWeapon>
<EmitterLifeTime>1</EmitterLifeTime>
<EmitterLifeTimeRandomise>0</EmitterLifeTimeRandomise>
<EmitterMaxParticles>2</EmitterMaxParticles>
<EmitterNumCollide>0</EmitterNumCollide>
<EmitterNumSpawn>1</EmitterNumSpawn>
<EmitterNumSpawnRadnomise>0</EmitterNumSpawnRadnomise>
<EmitterOriginOffset x='0' y='0' z='0' />
<EmitterOriginRandomise x='0' y='0' z='0' />
<EmitterParticleExpireFX></EmitterParticleExpireFX>
<EmitterParticleFX></EmitterParticleFX>
<EmitterSameDirectionAsWorm>false</EmitterSameDirectionAsWorm>
<EmitterSoundFX></EmitterSoundFX>
<EmitterSoundFXVolume>1</EmitterSoundFXVolume>
<EmitterSpawnFreq>10</EmitterSpawnFreq>
<EmitterSpawnFreqRansomise>0</EmitterSpawnFreqRansomise>
<EmitterSpawnSizeVelocity x='0' y='0' />
<EmitterStartDelay>250</EmitterStartDelay>
<EmitterVelocity x='0' y='0' z='0' />
<EmitterVelocityRandomise x='0' y='0' z='0' />
<ParticleAcceleration x='0' y='-1' z='0' />
<ParticleAccelerationRandomise x='0' y='0' z='0' />
<ParticleAlpha>1</ParticleAlpha>
<ParticleAlphaFadeIn>5</ParticleAlphaFadeIn>
<ParticleAlphaVelocity>-1</ParticleAlphaVelocity>
<ParticleAlphaVelocityDelay>50</ParticleAlphaVelocityDelay>
<ParticleAlternateAccelerationN>0</ParticleAlternateAccelerationN>
<ParticleAlternateAccelerationS>0</ParticleAlternateAccelerationS>
<ParticleAnimationFrame>0</ParticleAnimationFrame>
<ParticleAnimationFrameRandomise>0</ParticleAnimationFrameRandomise>
<ParticleAnimationSpeed>0</ParticleAnimationSpeed>
<ParticleAnimationSpeedRandomize>0</ParticleAnimationSpeedRandomize>
<ParticleAttractor x='0' y='0' z='0' />
<ParticleAttractorRandomise x='0' y='0' z='0' />
<ParticleAttractorIsActive>false</ParticleAttractorIsActive>
<ParticleCanEnterWater>true</ParticleCanEnterWater>
<ParticleCollisionFreq>0</ParticleCollisionFreq>
<ParticleCollisionImmuneTime>0</ParticleCollisionImmuneTime>
<ParticleCollisionMinAlpha>0</ParticleCollisionMinAlpha>
<ParticleCollisonRadius>0</ParticleCollisonRadius>
<ParticleCollisonRadiusOffset x='0' y='0' z='0' />
<ParticleCollisonRadiusVelocity>0</ParticleCollisonRadiusVelocity>
<ParticleCollisionShowDebug>false</ParticleCollisionShowDebug>
<ParticleCollisionWormDamageMagnitude>0</ParticleCollisionWormDamageMagnitude>
<ParticleCollisionWormImpulseMagnitude>0</ParticleCollisionWormImpulseMagnitude>
<ParticleCollisionWormImpulseYMagnitude>0</ParticleCollisionWormImpulseYMagnitude>
<ParticleCollisionWormPoisonMagnitude>0</ParticleCollisionWormPoisonMagnitude>
<ParticleCollisionWormType>0</ParticleCollisionWormType>
<ParticleColor r='1' g='1' b='1' />
<ParticleColor r='1' g='0.8' b='0' />
<ParticleColor r='1' g='0' b='0' />
<ParticleColorBand>0</ParticleColorBand>
<ParticleColorBand>0.2</ParticleColorBand>
<ParticleColorBand>0.5</ParticleColorBand>
<ParticleColorBand>1</ParticleColorBand>
<ParticleExpireShake>false</ParticleExpireShake>
<ParticleExpireShakeLength>0</ParticleExpireShakeLength>
<ParticleExpireShakeMagnitude>0</ParticleExpireShakeMagnitude>
<ParticleIsAlternateAcceleration>false</ParticleIsAlternateAcceleration>
<ParticleIsEffectedByWind>false</ParticleIsEffectedByWind>
<ParticleIsSpiral>false</ParticleIsSpiral>
<ParticleIsUnderWaterEffect>false</ParticleIsUnderWaterEffect>
<ParticleLandCollideType>1</ParticleLandCollideType>
<ParticleLife>1600</ParticleLife>
<ParticleLifeRandomise>800</ParticleLifeRandomise>
<ParticleMass>0</ParticleMass>
<ParticleNumColors>2</ParticleNumColors>
<ParticleNumFrames>0</ParticleNumFrames>
<ParticleOrientation x='0' y='0' z='0' />
<ParticleOrientationRandomise x='0' y='0' z='0' />
<ParticleOrientationVelocity x='0' y='0' z='0' />
<ParticleOrientationVelocityRandomise x='0' y='0' z='5' />
<ParticleSize x='65' y='65' />
<ParticleSizeOriginIsCenterPoint>false</ParticleSizeOriginIsCenterPoint>
<ParticleSizeRandomise>0</ParticleSizeRandomise>
<ParticleSizeVelocity x='1' y='1' />
<ParticleSizeVelocityRandomise x='0.4' y='0.4' />
<ParticleSizeVelocityDelay>0</ParticleSizeVelocityDelay>
<ParticleSizeVelocityDelayRandomise>0</ParticleSizeVelocityDelayRandomise>
<ParticleFinalSizeScale x='0' y='0' />
<ParticleFinalSizeScaleRandomise>0</ParticleFinalSizeScaleRandomise>
<ParticleSizeFadeIn>0</ParticleSizeFadeIn>
<ParticleSizeFadeInRandomize>0</ParticleSizeFadeInRandomize>
<ParticleSizeFadeInDelay>0</ParticleSizeFadeInDelay>
<ParticleSizeFadeInDelayRandomize>0</ParticleSizeFadeInDelayRandomize>
<ParticleRenderScene>1</ParticleRenderScene>
<ParticleSpiralRadius>0</ParticleSpiralRadius>
<ParticleSpiralRadiusRandomise>0</ParticleSpiralRadiusRandomise>
<ParticleSpiralRadiusVelocity>0</ParticleSpiralRadiusVelocity>
<ParticleSpiralRadiusVelocityRandomise>0</ParticleSpiralRadiusVelocityRandomise>
<ParticleSpiralRadiusSizeVelocity>0</ParticleSpiralRadiusSizeVelocity>
<ParticleVelocity x='0' y='0' z='0' />
<ParticleVelocityRandomise x='0.02' y='0' z='0.02' />
<ParticleVelocityIsNormalised>false</ParticleVelocityIsNormalised>
</ParticleEmitterContainer>
...
Как видите контейнер ужасно большой и с ним очень неудобно возиться, поэтому, создавая свой эффект,
хочется не переписывать всё заново, а создать эффект на основе уже существуещего.
Если вы внимательно посмотрите содержимое контейнера, то заметите, что в нём повторяются имена тэгов:
Code
<ParticleColor r='1' g='1' b='1' />
<ParticleColor r='1' g='0.8' b='0' />
<ParticleColor r='1' g='0' b='0' />
и
Code
<ParticleColorBand>0</ParticleColorBand>
<ParticleColorBand>0.2</ParticleColorBand>
<ParticleColorBand>0.5</ParticleColorBand>
<ParticleColorBand>1</ParticleColorBand>
Поэкспериментируем с этим контейнером.
За основу возьмём такой мод:
Code
<?xml version="1.0" encoding="UTF-8"?>
<Mod BaseFile="../base/PartTwk.xml">
<ParticleEmitterContainer id='New.Effect' base='WXP_MeshBang_HotCoreLarge'>
</ParticleEmitterContainer>
</Mod>
а затем будем его менять.