Jump to content

Character Swapping Framework Documentation

From HEModdingWiki

The "Character Swapping Framework" is a mod for Sonic Unleashed that adds in the ability for a user to install one or more model mods to their game and then toggle between each model mod in game.

The mod has a few major iterations that a modder could fork for their own work.

Glossery:[edit | edit source]

CSF: Character Swapping Framework

Data Archive: The archive containing character model, sound and ui data, such as "ActD_Char_Custom.ar"

Data Bridge: The archive used to bridge between the Data Archive and the stage instance, such as "#Custom_Africa.ar"

SR_Enter Scripts: The stage entry scripts primarily modified to facilitate this mods functions.

How The Core System Works In All Iterations.[edit | edit source]

All iterations use the same fundamental system where you require:

An archive containing your "characters" data, this for example would be similar to "Sonic.ar", but labled something like "ActD_Char_Custom.ar".

Archives to hook the Data Archive to the stage, such as "#Custom_Africa.ar" or "#Sub_Custom_Africa1.ar".

A custom archive tree, referenced as additional in the main archive trees.

Entries for Data Archives and Data Bridge archives in the "swa.arcinfo".

Entires for your flag type [integer or bool] in the "Flaglist.xml".

Flag modifier scripts for your characters, these dictate what region within the script sets the bool or integer flag.

Relevent per version cases in the "SR_Enter" scripts.

Stagelist entries directing to the flag modifer scripts.

Major Iterations.[edit | edit source]

Version 1.0.[edit | edit source]

Introduction of the system to the mod "Sonic Unleashed: Reimagined", this version is very similar to what you will see in later versions, however it utilises a bool flags, an example from the FlagList:

     <Flag type="Bool">

       <!--リザーブ-->

       <name>bFlag_isCharacter</name>

     </Flag>

     <Flag type="Bool">

       <!--リザーブ-->

       <name>bFlag_isSilver</name>

     </Flag>

Here is how the "character_flag.xml" looks, within its original implimentation in "Sonic Unleashed: Reimagined" the framework was fairly limited and hard scripted.

<?xml version="1.0" encoding="utf-8"?>
<MicroSequence>
<Switch>
  <Case flag="bFlag_isCharacter" operation="E" value="true">
	<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isCharacter</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
				<param>  
				  <FlagName>bFlag_isMarza</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
				<param>  
				  <FlagName>bFlag_isShadow</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
				<param>  
				  <FlagName>bFlag_isBlaze</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
				<param> 
				  <FlagName>bFlag_isUnwiished</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
				<param> 
				  <FlagName>bFlag_isSilver</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
				<param> 
				  <FlagName>bFlag_isEspio</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
				<param> 
				  <FlagName>bFlag_isMetal</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
	</SequenceUnit>
	</Case>
  <Case flag="bFlag_isCharacter" operation="E" value="false">	
   <Switch>
    <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_SouthEastAsia">
		<Switch>
		<Case flag="bFlag_isMarza" operation="E" value="false">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isMarza</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
				<param>
				  <FlagName>bFlag_isCharacter</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
			  </SequenceUnit>
		</Case>
		<Case flag="bFlag_isMarza" operation="E" value="true">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isMarza</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
			</SequenceUnit>
		</Case>
	  </Switch>
    </Case>
	<Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_NYCity">
		<Switch>
		<Case flag="bFlag_isShadow" operation="E" value="false">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isShadow</FlagName>
				  <FlagValue>true</FlagValue>
				</param>  
				<param>
				  <FlagName>bFlag_isCharacter</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
			  </SequenceUnit>
		</Case>
		<Case flag="bFlag_isShadow" operation="E" value="true">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isShadow</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
			</SequenceUnit>
		</Case>
	  </Switch>
    </Case>
	<Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_China">
	  <Switch>
		<Case flag="bFlag_isBlaze" operation="E" value="false">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isBlaze</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
				<param>
				  <FlagName>bFlag_isCharacter</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
			  </SequenceUnit>
		</Case>
		<Case flag="bFlag_isBlaze" operation="E" value="true">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isBlaze</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
			  </SequenceUnit>
		</Case>
	  </Switch>
    </Case>
	<Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_EuropeanCity">
	  <Switch>
		<Case flag="bFlag_isUnwiished" operation="E" value="false">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isUnwiished</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
				<param>
				  <FlagName>bFlag_isCharacter</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
			  </SequenceUnit>
		</Case>
		<Case flag="bFlag_isUnwiished" operation="E" value="true">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isUnwiished</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
			</SequenceUnit>
		</Case>
	   </Switch>
      </Case>
	  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_PetraCapital">
	  <Switch>
		<Case flag="bFlag_isSilver" operation="E" value="false">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isSilver</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
				<param>
				  <FlagName>bFlag_isCharacter</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
			  </SequenceUnit>
		</Case>
		<Case flag="bFlag_isSilver" operation="E" value="true">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isSilver</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
			</SequenceUnit>
		</Case>
	   </Switch>
      </Case>
	  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_Africa">
	  <Switch>
		<Case flag="bFlag_isEspio" operation="E" value="false">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isEspio</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
				<param>
				  <FlagName>bFlag_isCharacter</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
			  </SequenceUnit>
		</Case>
		<Case flag="bFlag_isEspio" operation="E" value="true">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isEspio</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
			</SequenceUnit>
		</Case>
	   </Switch>
      </Case>
	  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_Snow">
	  <Switch>
		<Case flag="bFlag_isMetal" operation="E" value="false">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isMetal</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
				<param>
				  <FlagName>bFlag_isCharacter</FlagName>
				  <FlagValue>true</FlagValue>
				</param>
			  </SequenceUnit>
		</Case>
		<Case flag="bFlag_isMetal" operation="E" value="true">
			<SequenceUnit>
				<type>SetFlag</type>
				<param>
				  <FlagName>bFlag_isMetal</FlagName>
				  <FlagValue>false</FlagValue>
				</param>
			</SequenceUnit>
		</Case>
	   </Switch>
      </Case>
	 </Switch>
	 <SequenceUnit>
		<type>ChangeStage</type>
		  <param>
			<StageType>Menu</StageType>
			<SettingName>Reload</SettingName>
		  </param>
	</SequenceUnit>
    </Case>
</Switch>
</MicroSequence>

A master "bFlag_isCharacter" bool is used for control of whether the Data Bridge is active.

Then the additional bool "bFlag_isSilver" (example) is used to load the Data Archive when the SR_Enter script validates the flag as true.

Below is a sample of an entry case in the SR_Enter script for Savannah Citadel act 1.

	  <Case flag="bFlag_isSilver" operation="E" value="true">
		<ArchiveName>Silver_Africa</ArchiveName>
		<OverWriteTerrainInfo>
			<DirName>ActD_Africa</DirName>
                </OverWriteTerrainInfo>
	  </Case>

Generally speaking the archive tree, arcinfo and Data Archive / Data Bridge files remain the same throught all versions after this, with relevant changes to namings but otherwise the process remains the same.

The main changes are to the underlying systems.

Addtional Info:[edit | edit source]

  • In theory version 1.0 could allow you to switch night characters but that still has to respect the 1-7 limit between day and night overall and so this was never implimated.

Version 2.0.[edit | edit source]

Released with the release of "Sonic Unleashed: Reimagined update 2.0.0", version 2.0 rewrites the core system from its previous bool flag based version, to now use integer flags. In theory this allows for an endless amount of character slots and flag modifier lists. This also reduces the FlagList occupied flags from 2-8 bool flags to just 1-2 integer flags.

This update also brought with it the ability to switch characters within night stages and the final boss, allowing for Werehog model swapping and Super Sonic model swapping.

Replaced:[edit | edit source]

bFlag_isCharacter

bFlag_is{modifiable}

bFlag_is{modifiable}

bFlag_is{modifiable}

bFlag_is{modifiable}

bFlag_is{modifiable}

bFlag_is{modifiable}

bFlag_is{modifiable}

With:[edit | edit source]

iFlag_isDayCharacter

iFlag_isNightCharacter

iFlag_isSuperCharacter

      <Flag type="Int">
        <!--リザーブ-->
        <name>iFlag_DayCharacter</name>
      </Flag>
      <Flag type="Int">
        <!--リザーブ-->
        <name>iFlag_NightCharacter</name>
      </Flag>
      <Flag type="Int">
        <!--リザーブ-->
        <name>iFlag_SuperCharacter</name>
      </Flag>

Below is an example of how the flag modifier script now looks, these can be duplicated infinitely, assuming the "FlagValue" is unique and referenced in the SR_Enter scripts.

<MicroSequence>
<Switch>
  <Case flag="eFlag_TownState" operation="E" value="eFlag_TownState_Day">
		<Switch> 
		  <Case flag="iFlag_DayCharacter" operation="GE" value="1">
		    <SequenceUnit>
		      <type>SetFlag</type>
			  <param>
			    <FlagName>iFlag_DayCharacter</FlagName>
			    <FlagValue>0</FlagValue>
			  </param>
		    </SequenceUnit>
		  </Case>
		  <Case flag="iFlag_DayCharacter" operation="E" value="0">
		    <Switch>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_EuropeanCity">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>1</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_NYCity">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>2</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_China">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>3</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_Africa">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>4</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_PetraCapital">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>5</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_EggManBase"> <!--Skip this-->
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>6</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_Snow">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>7</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_Mykonos">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>8</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_SouthEastAsia">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>9</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
		    </Switch>
			<SequenceUnit>
			<type>ChangeStage</type>
				<param>
				  <StageType>Menu</StageType>
				  <SettingName>Reload</SettingName>
				</param>
			</SequenceUnit>
		  </Case>
		</Switch>
  </Case>
  <Case flag="eFlag_TownState" operation="E" value="eFlag_TownState_Night">
		<Switch>
		  <Case flag="iFlag_NightCharacter" operation="GE" value="1">
		    <SequenceUnit>
		      <type>SetFlag</type>
			  <param>
			    <FlagName>iFlag_NightCharacter</FlagName>
			    <FlagValue>0</FlagValue>
			  </param>
		    </SequenceUnit>
		  </Case>
		  <Case flag="iFlag_NightCharacter" operation="E" value="0">
			<Switch>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_EuropeanCity">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_NightCharacter</FlagName>
					<FlagValue>1</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_NYCity">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_NightCharacter</FlagName>
					<FlagValue>2</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_China">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_NightCharacter</FlagName>
					<FlagValue>3</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_Africa">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_NightCharacter</FlagName>
					<FlagValue>4</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_PetraCapital">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_NightCharacter</FlagName>
					<FlagValue>5</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_EggManBase"> <!--Skip this-->
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_DayCharacter</FlagName>
					<FlagValue>6</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_Snow">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_NightCharacter</FlagName>
					<FlagValue>7</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_Mykonos">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_NightCharacter</FlagName>
					<FlagValue>8</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			  <Case flag="eFlag_LastTown" operation="E" value="eFlag_TownState_SouthEastAsia">
				<SequenceUnit>
				  <type>SetFlag</type>
				  <param>
					<FlagName>iFlag_NightCharacter</FlagName>
					<FlagValue>9</FlagValue>
				  </param>
				</SequenceUnit>
			  </Case>
			</Switch>
			<SequenceUnit>
			<type>ChangeStage</type>
				<param>
				  <StageType>Menu</StageType>
				  <SettingName>Reload</SettingName>
				</param>
			</SequenceUnit>
		  </Case>
		</Switch>
  </Case>
</Switch>
</MicroSequence>

The case statements for the modifiable scripts and their referencers in the SR_Enter scripts have changed as such:

Before: <Case flag="bFlag_is{modifiable text}" operation="E" value="true">

After:  <Case flag="iFlag_DayCharacter" operation="E" value="{modifiable number}">

Addtional Info:[edit | edit source]

  • EggmanLand region does not function for "iFlag_NightCharacter" & "iFlag_SuperCharacter".

Version 3.0.[edit | edit source]

Version 3.0 didn't change to much but it did streamline many aspects for use in the CSF and for use by other modders when forking the mod for their own projects.

Major Changes:[edit | edit source]

  • Removed the ability to change characters in EggmanLand as to retain consistency, due to the system not working for the Werehog in this region.
  • Removed the ability to change super characters due to the system not functioning fully at that point in time.
  • Added two extra flag modifier scripts for the main CSF mod to increase the number of characters for day and night from 8 to 24.

Mods Using Iterations.[edit | edit source]

Version 1.0:[edit | edit source]

Sonic Unleashed: Reimagined 1.0.0

Version 2.0:[edit | edit source]

Sonic Unleashed: Reimagined 2.0.0

Sonic Unleashed: Reimagined 3.0.0

Sonic Unleashed: Reimagined V4

Version 3.0:[edit | edit source]

Character Swapping Framework

Version Forks:[edit | edit source]

Version 3.0A:

Like a Werehog: Extreme Fury

Nightmare: A LAW Mod

Version 3.0 forked for the Like a Werehog mods. This fork removes the "iFlag_DayCharacter" flag and the ability to toggle between flag values in day stages. This version also reworks the system to have all regions in a given flag list correlate to a single integer number to facilitate the ability to toggle all styles within every region, along with having flag modifier lists be unique to each style (character) rather than being shared flag modifier lists.