├── .gitignore ├── LICENSE ├── NetworkAnarchy.sln ├── NetworkAnarchy ├── ChirperAtlas │ ├── Chirper.png │ ├── ChirperChristmas.png │ ├── ChirperChristmasDisabled.png │ ├── ChirperChristmasFocused.png │ ├── ChirperChristmasHovered.png │ ├── ChirperChristmasPressed.png │ ├── ChirperConcerts.png │ ├── ChirperConcertsDisabled.png │ ├── ChirperConcertsFocused.png │ ├── ChirperConcertsHovered.png │ ├── ChirperConcertsPressed.png │ ├── ChirperDeluxe.png │ ├── ChirperDeluxeDisabled.png │ ├── ChirperDeluxeFocused.png │ ├── ChirperDeluxeHovered.png │ ├── ChirperDeluxePressed.png │ ├── ChirperDisabled.png │ ├── ChirperDisastersHazmat.png │ ├── ChirperDisastersHazmatDisabled.png │ ├── ChirperDisastersHazmatFocused.png │ ├── ChirperDisastersHazmatHovered.png │ ├── ChirperDisastersHazmatPressed.png │ ├── ChirperDisastersPilot.png │ ├── ChirperDisastersPilotDisabled.png │ ├── ChirperDisastersPilotFocused.png │ ├── ChirperDisastersPilotHovered.png │ ├── ChirperDisastersPilotPressed.png │ ├── ChirperDisastersWorker.png │ ├── ChirperDisastersWorkerDisabled.png │ ├── ChirperDisastersWorkerFocused.png │ ├── ChirperDisastersWorkerHovered.png │ ├── ChirperDisastersWorkerPressed.png │ ├── ChirperFocused.png │ ├── ChirperFootball.png │ ├── ChirperFootballDisabled.png │ ├── ChirperFootballFocused.png │ ├── ChirperFootballHovered.png │ ├── ChirperFootballPressed.png │ ├── ChirperHovered.png │ ├── ChirperIcon.png │ ├── ChirperJesterhat.png │ ├── ChirperJesterhatDisabled.png │ ├── ChirperJesterhatFocused.png │ ├── ChirperJesterhatHovered.png │ ├── ChirperJesterhatPressed.png │ ├── ChirperLumberjack.png │ ├── ChirperLumberjackDisabled.png │ ├── ChirperLumberjackFocused.png │ ├── ChirperLumberjackHovered.png │ ├── ChirperLumberjackPressed.png │ ├── ChirperParkRanger.png │ ├── ChirperParkRangerDisabled.png │ ├── ChirperParkRangerFocused.png │ ├── ChirperParkRangerHovered.png │ ├── ChirperParkRangerPressed.png │ ├── ChirperPressed.png │ ├── ChirperRally.png │ ├── ChirperRallyDisabled.png │ ├── ChirperRallyFocused.png │ ├── ChirperRallyHovered.png │ ├── ChirperRallyPressed.png │ ├── ChirperRudolph.png │ ├── ChirperRudolphDisabled.png │ ├── ChirperRudolphFocused.png │ ├── ChirperRudolphHovered.png │ ├── ChirperRudolphPressed.png │ ├── ChirperSouvenirGlasses.png │ ├── ChirperSouvenirGlassesDisabled.png │ ├── ChirperSouvenirGlassesFocused.png │ ├── ChirperSouvenirGlassesHovered.png │ ├── ChirperSouvenirGlassesPressed.png │ ├── ChirperSurvivingMars.png │ ├── ChirperSurvivingMarsDisabled.png │ ├── ChirperSurvivingMarsFocused.png │ ├── ChirperSurvivingMarsHovered.png │ ├── ChirperSurvivingMarsPressed.png │ ├── ChirperTrafficCone.png │ ├── ChirperTrafficConeDisabled.png │ ├── ChirperTrafficConeFocused.png │ ├── ChirperTrafficConeHovered.png │ ├── ChirperTrafficConePressed.png │ ├── ChirperTrainConductor.png │ ├── ChirperTrainConductorDisabled.png │ ├── ChirperTrainConductorFocused.png │ ├── ChirperTrainConductorHovered.png │ ├── ChirperTrainConductorPressed.png │ ├── ChirperWintercap.png │ ├── ChirperWintercapDisabled.png │ ├── ChirperWintercapFocused.png │ ├── ChirperWintercapHovered.png │ ├── ChirperWintercapPressed.png │ ├── ChirperZookeeper.png │ ├── ChirperZookeeperDisabled.png │ ├── ChirperZookeeperFocused.png │ ├── ChirperZookeeperHovered.png │ ├── ChirperZookeeperPressed.png │ ├── Chirpercrown.png │ ├── ChirpercrownDisabled.png │ ├── ChirpercrownFocused.png │ ├── ChirpercrownHovered.png │ ├── ChirpercrownPressed.png │ ├── EmptySprite.png │ ├── ThumbChirperBeanie.png │ ├── ThumbChirperBeanieDisabled.png │ ├── ThumbChirperBeanieFocused.png │ ├── ThumbChirperBeanieHovered.png │ ├── ThumbChirperBeaniePressed.png │ ├── ThumbChirperFlower.png │ ├── ThumbChirperFlowerDisabled.png │ ├── ThumbChirperFlowerFocused.png │ ├── ThumbChirperFlowerHovered.png │ ├── ThumbChirperFlowerPressed.png │ ├── ThumbChirperTech.png │ ├── ThumbChirperTechDisabled.png │ ├── ThumbChirperTechFocused.png │ ├── ThumbChirperTechHovered.png │ └── ThumbChirperTechPressed.png ├── ChirperManager.cs ├── Icons │ ├── Anarchy.png │ ├── AnarchyDisabled.png │ ├── AnarchyFocused.png │ ├── AnarchyHovered.png │ ├── AnarchyPressed.png │ ├── Bending.png │ ├── BendingDisabled.png │ ├── BendingFocused.png │ ├── BendingHovered.png │ ├── BendingPressed.png │ ├── BridgeMode.png │ ├── BridgeModeDisabled.png │ ├── BridgeModeFocused.png │ ├── BridgeModeHovered.png │ ├── BridgeModePressed.png │ ├── Collision.png │ ├── CollisionDisabled.png │ ├── CollisionFocused.png │ ├── CollisionHovered.png │ ├── CollisionPressed.png │ ├── ElevatedMode.png │ ├── ElevatedModeDisabled.png │ ├── ElevatedModeFocused.png │ ├── ElevatedModeHovered.png │ ├── ElevatedModePressed.png │ ├── GroundMode.png │ ├── GroundModeDisabled.png │ ├── GroundModeFocused.png │ ├── GroundModeHovered.png │ ├── GroundModePressed.png │ ├── NormalMode.png │ ├── NormalModeDisabled.png │ ├── NormalModeFocused.png │ ├── NormalModeHovered.png │ ├── NormalModePressed.png │ ├── Snapping.png │ ├── SnappingDisabled.png │ ├── SnappingFocused.png │ ├── SnappingHovered.png │ ├── SnappingPressed.png │ ├── StraightSlope.png │ ├── StraightSlopeDisabled.png │ ├── StraightSlopeFocused.png │ ├── StraightSlopeHovered.png │ ├── StraightSlopePressed.png │ ├── TunnelMode.png │ ├── TunnelModeDisabled.png │ ├── TunnelModeFocused.png │ ├── TunnelModeHovered.png │ ├── TunnelModePressed.png │ ├── ZoneOverride.png │ ├── ZoneOverrideDisabled.png │ ├── ZoneOverrideFocused.png │ ├── ZoneOverrideHovered.png │ └── ZoneOverridePressed.png ├── Integration │ ├── CrossTheLine.cs │ ├── NetworkMultitool.cs │ ├── NetworkSkins.cs │ └── ZoningAdjuster.cs ├── Lang │ ├── Str.cs │ ├── Str.cs.resx │ ├── Str.de.resx │ ├── Str.es.resx │ ├── Str.fr.resx │ ├── Str.it.resx │ ├── Str.ja.resx │ ├── Str.ko.resx │ ├── Str.pl.resx │ ├── Str.pt.resx │ ├── Str.resx │ ├── Str.ru.resx │ ├── Str.th.resx │ └── Str.zh-cn.resx ├── LoadingManagers.cs ├── ModInfo.cs ├── NA_Fixes.cs ├── NA_GUI.cs ├── NA_Operation.cs ├── NA_SimulationTick.cs ├── NetAIWrapper.cs ├── NetPrefab.cs ├── NetworkAnarchy.cs ├── NetworkAnarchy.csproj ├── OptionsKeymapping.cs ├── Patches │ ├── BuildingTool.cs │ ├── Collision.cs │ ├── EarlyPatches.cs │ ├── GetInfo.cs │ ├── LeftHandTraffic.cs │ ├── Misc.cs │ ├── NetTool.cs │ ├── Networks.cs │ ├── RoadAI.cs │ └── Water.cs └── UI │ ├── ModOptions.cs │ ├── Popups.cs │ ├── ToolOptionsButton.cs │ └── ToolOptionsButtonCreate.cs ├── README.md └── crowdin.yml /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | libs/ 352 | /NetworkAnarchy/Properties 353 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Quboid 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NetworkAnarchy.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32819.101 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetworkAnarchy", "NetworkAnarchy\NetworkAnarchy.csproj", "{291D9EA9-6945-4EA3-8756-37464D40FF00}" 7 | EndProject 8 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "QCommon Harmony", "..\..\..\QCommon\Repo\QCommon\QCommon\Harmony\QCommon Harmony.shproj", "{9D9EC2D2-3CEE-42E2-8296-FA667D0B73E6}" 9 | EndProject 10 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "QCommon Shared", "..\..\..\QCommon\Repo\QCommon\QCommon\Shared\QCommon Shared.shproj", "{233B2695-91AD-4B85-A778-1FFF467FAE35}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {291D9EA9-6945-4EA3-8756-37464D40FF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {291D9EA9-6945-4EA3-8756-37464D40FF00}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {291D9EA9-6945-4EA3-8756-37464D40FF00}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {291D9EA9-6945-4EA3-8756-37464D40FF00}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | GlobalSection(ExtensibilityGlobals) = postSolution 27 | RESX_ShowErrorsInErrorList = False 28 | RESX_SaveFilesImmediatelyUponChange = True 29 | RESX_Rules = {"EnabledRules":["StringFormat","WhiteSpaceLead","WhiteSpaceTail","PunctuationLead"]} 30 | SolutionGuid = {52D8687F-6BFB-4D01-9E1E-AC85E69AB925} 31 | RESX_NeutralResourcesLanguage = en-GB 32 | EndGlobalSection 33 | GlobalSection(SharedMSBuildProjectFiles) = preSolution 34 | ..\..\..\QCommon\Repo\QCommon\QCommon\Shared\QCommon Shared.projitems*{233b2695-91ad-4b85-a778-1fff467fae35}*SharedItemsImports = 13 35 | ..\..\..\QCommon\Repo\QCommon\QCommon\Harmony\QCommon Harmony.projitems*{291d9ea9-6945-4ea3-8756-37464d40ff00}*SharedItemsImports = 5 36 | ..\..\..\QCommon\Repo\QCommon\QCommon\Shared\QCommon Shared.projitems*{291d9ea9-6945-4ea3-8756-37464d40ff00}*SharedItemsImports = 5 37 | ..\..\..\QCommon\Repo\QCommon\QCommon\Harmony\QCommon Harmony.projitems*{9d9ec2d2-3cee-42e2-8296-fa667d0b73e6}*SharedItemsImports = 13 38 | EndGlobalSection 39 | EndGlobal 40 | -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/Chirper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/Chirper.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperChristmas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperChristmas.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperChristmasDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperChristmasDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperChristmasFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperChristmasFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperChristmasHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperChristmasHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperChristmasPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperChristmasPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperConcerts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperConcerts.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperConcertsDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperConcertsDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperConcertsFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperConcertsFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperConcertsHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperConcertsHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperConcertsPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperConcertsPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDeluxe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDeluxe.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDeluxeDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDeluxeDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDeluxeFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDeluxeFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDeluxeHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDeluxeHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDeluxePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDeluxePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmat.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmatDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmatDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmatFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmatFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmatHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmatHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmatPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersHazmatPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersPilot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersPilot.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersPilotDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersPilotDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersPilotFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersPilotFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersPilotHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersPilotHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersPilotPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersPilotPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersWorker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersWorker.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersWorkerDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersWorkerDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersWorkerFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersWorkerFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersWorkerHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersWorkerHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperDisastersWorkerPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperDisastersWorkerPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperFootball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperFootball.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperFootballDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperFootballDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperFootballFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperFootballFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperFootballHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperFootballHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperFootballPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperFootballPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperIcon.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperJesterhat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperJesterhat.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperJesterhatDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperJesterhatDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperJesterhatFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperJesterhatFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperJesterhatHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperJesterhatHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperJesterhatPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperJesterhatPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperLumberjack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperLumberjack.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperLumberjackDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperLumberjackDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperLumberjackFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperLumberjackFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperLumberjackHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperLumberjackHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperLumberjackPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperLumberjackPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperParkRanger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperParkRanger.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperParkRangerDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperParkRangerDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperParkRangerFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperParkRangerFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperParkRangerHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperParkRangerHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperParkRangerPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperParkRangerPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRally.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRally.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRallyDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRallyDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRallyFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRallyFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRallyHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRallyHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRallyPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRallyPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRudolph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRudolph.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRudolphDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRudolphDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRudolphFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRudolphFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRudolphHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRudolphHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperRudolphPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperRudolphPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlasses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlasses.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlassesDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlassesDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlassesFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlassesFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlassesHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlassesHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlassesPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSouvenirGlassesPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSurvivingMars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSurvivingMars.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSurvivingMarsDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSurvivingMarsDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSurvivingMarsFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSurvivingMarsFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSurvivingMarsHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSurvivingMarsHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperSurvivingMarsPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperSurvivingMarsPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrafficCone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrafficCone.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrafficConeDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrafficConeDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrafficConeFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrafficConeFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrafficConeHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrafficConeHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrafficConePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrafficConePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrainConductor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrainConductor.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrainConductorDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrainConductorDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrainConductorFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrainConductorFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrainConductorHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrainConductorHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperTrainConductorPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperTrainConductorPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperWintercap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperWintercap.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperWintercapDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperWintercapDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperWintercapFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperWintercapFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperWintercapHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperWintercapHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperWintercapPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperWintercapPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperZookeeper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperZookeeper.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperZookeeperDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperZookeeperDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperZookeeperFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperZookeeperFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperZookeeperHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperZookeeperHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirperZookeeperPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirperZookeeperPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/Chirpercrown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/Chirpercrown.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirpercrownDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirpercrownDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirpercrownFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirpercrownFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirpercrownHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirpercrownHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ChirpercrownPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ChirpercrownPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/EmptySprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/EmptySprite.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperBeanie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperBeanie.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperBeanieDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperBeanieDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperBeanieFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperBeanieFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperBeanieHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperBeanieHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperBeaniePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperBeaniePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperFlower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperFlower.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperFlowerDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperFlowerDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperFlowerFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperFlowerFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperFlowerHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperFlowerHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperFlowerPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperFlowerPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperTech.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperTech.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperTechDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperTechDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperTechFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperTechFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperTechHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperTechHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperAtlas/ThumbChirperTechPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/ChirperAtlas/ThumbChirperTechPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/ChirperManager.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework.UI; 2 | using HarmonyLib; 3 | using QCommonLib; 4 | using System.Linq; 5 | 6 | namespace NetworkAnarchy 7 | { 8 | public class ChirperManager 9 | { 10 | static UITextureAtlas normalAtlas = null; 11 | static UITextureAtlas anarchyAtlas = null; 12 | static UIButton chirperButton = null; 13 | static string hoveredSprite, normalSprite, pressedSprite; 14 | 15 | public static void Initialise() 16 | { 17 | normalAtlas = QTextures.GetAtlas("ChirperAtlas"); 18 | anarchyAtlas = GetChirperAtlas(); 19 | chirperButton = UIView.GetAView().FindUIComponent("Zone"); 20 | 21 | if (normalAtlas == null) UnityEngine.Debug.Log($"NetworkAnarchy: Failed to load Chirper normal atlas [NA10]"); 22 | if (anarchyAtlas == null) UnityEngine.Debug.Log($"NetworkAnarchy: Failed to load Chirper anarchy atlas [NA11]"); 23 | if (chirperButton == null) UnityEngine.Debug.Log($"NetworkAnarchy: Failed to find Chirper button [NA12]"); 24 | if (normalAtlas == null || anarchyAtlas == null || chirperButton == null) return; 25 | 26 | hoveredSprite = chirperButton.hoveredBgSprite; 27 | normalSprite = chirperButton.normalBgSprite; 28 | pressedSprite = chirperButton.pressedBgSprite; 29 | } 30 | 31 | internal static void UpdateAtlas() 32 | { 33 | if (normalAtlas == null) return; 34 | if (anarchyAtlas == null) return; 35 | if (chirperButton == null) return; 36 | 37 | if (NetworkAnarchy.Anarchy) 38 | { 39 | chirperButton.atlas = anarchyAtlas; 40 | if (!anarchyAtlas.spriteNames.Contains(chirperButton.normalBgSprite)) 41 | { 42 | chirperButton.hoveredBgSprite = "ChirperHovered"; 43 | chirperButton.normalBgSprite = "ChirperIcon"; 44 | chirperButton.pressedBgSprite = "ChirperPressed"; 45 | } 46 | } 47 | else 48 | { 49 | chirperButton.atlas = normalAtlas; 50 | chirperButton.hoveredBgSprite = hoveredSprite; 51 | chirperButton.normalBgSprite = normalSprite; 52 | chirperButton.pressedBgSprite = pressedSprite; 53 | } 54 | 55 | if (NetworkAnarchy.Collision) 56 | { 57 | chirperButton.opacity = 1f; 58 | } 59 | else 60 | { 61 | chirperButton.opacity = 0.5f; 62 | } 63 | } 64 | 65 | public static UITextureAtlas GetChirperAtlas() 66 | { 67 | string[] spriteNames = new string[] 68 | { 69 | "Chirper", 70 | "ChirperChristmas", 71 | "ChirperChristmasDisabled", 72 | "ChirperChristmasFocused", 73 | "ChirperChristmasHovered", 74 | "ChirperChristmasPressed", 75 | "ChirperConcerts", 76 | "ChirperConcertsDisabled", 77 | "ChirperConcertsFocused", 78 | "ChirperConcertsHovered", 79 | "ChirperConcertsPressed", 80 | "Chirpercrown", 81 | "ChirpercrownDisabled", 82 | "ChirpercrownFocused", 83 | "ChirpercrownHovered", 84 | "ChirpercrownPressed", 85 | "ChirperDeluxe", 86 | "ChirperDeluxeDisabled", 87 | "ChirperDeluxeFocused", 88 | "ChirperDeluxeHovered", 89 | "ChirperDeluxePressed", 90 | "ChirperDisabled", 91 | "ChirperDisastersHazmat", 92 | "ChirperDisastersHazmatDisabled", 93 | "ChirperDisastersHazmatFocused", 94 | "ChirperDisastersHazmatHovered", 95 | "ChirperDisastersHazmatPressed", 96 | "ChirperDisastersPilot", 97 | "ChirperDisastersPilotDisabled", 98 | "ChirperDisastersPilotFocused", 99 | "ChirperDisastersPilotHovered", 100 | "ChirperDisastersPilotPressed", 101 | "ChirperDisastersWorker", 102 | "ChirperDisastersWorkerDisabled", 103 | "ChirperDisastersWorkerFocused", 104 | "ChirperDisastersWorkerHovered", 105 | "ChirperDisastersWorkerPressed", 106 | "ChirperFocused", 107 | "ChirperFootball", 108 | "ChirperFootballDisabled", 109 | "ChirperFootballFocused", 110 | "ChirperFootballHovered", 111 | "ChirperFootballPressed", 112 | "ChirperHovered", 113 | "ChirperIcon", 114 | "ChirperJesterhat", 115 | "ChirperJesterhatDisabled", 116 | "ChirperJesterhatFocused", 117 | "ChirperJesterhatHovered", 118 | "ChirperJesterhatPressed", 119 | "ChirperLumberjack", 120 | "ChirperLumberjackDisabled", 121 | "ChirperLumberjackFocused", 122 | "ChirperLumberjackHovered", 123 | "ChirperLumberjackPressed", 124 | "ChirperParkRanger", 125 | "ChirperParkRangerDisabled", 126 | "ChirperParkRangerFocused", 127 | "ChirperParkRangerHovered", 128 | "ChirperParkRangerPressed", 129 | "ChirperPressed", 130 | "ChirperRally", 131 | "ChirperRallyDisabled", 132 | "ChirperRallyFocused", 133 | "ChirperRallyHovered", 134 | "ChirperRallyPressed", 135 | "ChirperRudolph", 136 | "ChirperRudolphDisabled", 137 | "ChirperRudolphFocused", 138 | "ChirperRudolphHovered", 139 | "ChirperRudolphPressed", 140 | "ChirperSouvenirGlasses", 141 | "ChirperSouvenirGlassesDisabled", 142 | "ChirperSouvenirGlassesFocused", 143 | "ChirperSouvenirGlassesHovered", 144 | "ChirperSouvenirGlassesPressed", 145 | "ChirperSurvivingMars", 146 | "ChirperSurvivingMarsDisabled", 147 | "ChirperSurvivingMarsFocused", 148 | "ChirperSurvivingMarsHovered", 149 | "ChirperSurvivingMarsPressed", 150 | "ChirperTrafficCone", 151 | "ChirperTrafficConeDisabled", 152 | "ChirperTrafficConeFocused", 153 | "ChirperTrafficConeHovered", 154 | "ChirperTrafficConePressed", 155 | "ChirperTrainConductor", 156 | "ChirperTrainConductorDisabled", 157 | "ChirperTrainConductorFocused", 158 | "ChirperTrainConductorHovered", 159 | "ChirperTrainConductorPressed", 160 | "ChirperWintercap", 161 | "ChirperWintercapDisabled", 162 | "ChirperWintercapFocused", 163 | "ChirperWintercapHovered", 164 | "ChirperWintercapPressed", 165 | "ChirperZookeeper", 166 | "ChirperZookeeperDisabled", 167 | "ChirperZookeeperFocused", 168 | "ChirperZookeeperHovered", 169 | "ChirperZookeeperPressed", 170 | "EmptySprite", 171 | "ThumbChirperBeanie", 172 | "ThumbChirperBeanieDisabled", 173 | "ThumbChirperBeanieFocused", 174 | "ThumbChirperBeanieHovered", 175 | "ThumbChirperBeaniePressed", 176 | "ThumbChirperFlower", 177 | "ThumbChirperFlowerDisabled", 178 | "ThumbChirperFlowerFocused", 179 | "ThumbChirperFlowerHovered", 180 | "ThumbChirperFlowerPressed", 181 | "ThumbChirperTech", 182 | "ThumbChirperTechDisabled", 183 | "ThumbChirperTechFocused", 184 | "ThumbChirperTechHovered", 185 | "ThumbChirperTechPressed" 186 | }; 187 | 188 | return QTextures.CreateTextureAtlas("ChirperAtlasAnarchy", spriteNames, "NetworkAnarchy.ChirperAtlas."); 189 | } 190 | } 191 | 192 | 193 | // Update the atlas if the player changes Chirper icon 194 | [HarmonyPatch(typeof(ChirpOptionsPanel), "OnSelected")] 195 | class CP_OnSelected 196 | { 197 | public static void Postfix() 198 | { 199 | ChirperManager.Initialise(); 200 | ChirperManager.UpdateAtlas(); 201 | } 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/Anarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/Anarchy.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/AnarchyDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/AnarchyDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/AnarchyFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/AnarchyFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/AnarchyHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/AnarchyHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/AnarchyPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/AnarchyPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/Bending.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/Bending.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/BendingDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/BendingDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/BendingFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/BendingFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/BendingHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/BendingHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/BendingPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/BendingPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/BridgeMode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/BridgeMode.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/BridgeModeDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/BridgeModeDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/BridgeModeFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/BridgeModeFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/BridgeModeHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/BridgeModeHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/BridgeModePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/BridgeModePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/Collision.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/Collision.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/CollisionDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/CollisionDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/CollisionFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/CollisionFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/CollisionHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/CollisionHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/CollisionPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/CollisionPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ElevatedMode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ElevatedMode.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ElevatedModeDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ElevatedModeDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ElevatedModeFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ElevatedModeFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ElevatedModeHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ElevatedModeHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ElevatedModePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ElevatedModePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/GroundMode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/GroundMode.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/GroundModeDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/GroundModeDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/GroundModeFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/GroundModeFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/GroundModeHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/GroundModeHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/GroundModePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/GroundModePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/NormalMode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/NormalMode.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/NormalModeDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/NormalModeDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/NormalModeFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/NormalModeFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/NormalModeHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/NormalModeHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/NormalModePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/NormalModePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/Snapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/Snapping.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/SnappingDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/SnappingDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/SnappingFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/SnappingFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/SnappingHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/SnappingHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/SnappingPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/SnappingPressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/StraightSlope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/StraightSlope.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/StraightSlopeDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/StraightSlopeDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/StraightSlopeFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/StraightSlopeFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/StraightSlopeHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/StraightSlopeHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/StraightSlopePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/StraightSlopePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/TunnelMode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/TunnelMode.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/TunnelModeDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/TunnelModeDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/TunnelModeFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/TunnelModeFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/TunnelModeHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/TunnelModeHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/TunnelModePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/TunnelModePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ZoneOverride.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ZoneOverride.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ZoneOverrideDisabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ZoneOverrideDisabled.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ZoneOverrideFocused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ZoneOverrideFocused.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ZoneOverrideHovered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ZoneOverrideHovered.png -------------------------------------------------------------------------------- /NetworkAnarchy/Icons/ZoneOverridePressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Quboid/NetworkAnarchy/b9589abc3f695d8f85aa631ee747497c2977fd5f/NetworkAnarchy/Icons/ZoneOverridePressed.png -------------------------------------------------------------------------------- /NetworkAnarchy/Integration/CrossTheLine.cs: -------------------------------------------------------------------------------- 1 | using NetworkAnarchy.Patches; 2 | using QCommonLib; 3 | using System.Reflection; 4 | 5 | namespace NetworkAnarchy.Mods 6 | { 7 | internal class CrossTheLine 8 | { 9 | private static Assembly ModAssembly; 10 | 11 | private static bool _IsEnabled; 12 | internal static bool IsEnabled => _IsEnabled; 13 | 14 | private static bool IsPatched = false; 15 | private static QPatcher Patcher; 16 | 17 | internal static void Initialise(QPatcher patcher) 18 | { 19 | Patcher = patcher; 20 | ModAssembly = QCommon.GetAssembly("mod", "buildanywhere"); 21 | if (ModAssembly != null) 22 | { 23 | Log.Info($"NetworkAnarchy: Cross The Line found, skipping patch", "[NA60]"); 24 | _IsEnabled = true; 25 | return; 26 | } 27 | 28 | _IsEnabled = false; 29 | 30 | if (!IsPatched) 31 | { 32 | Patcher.Prefix(typeof(GameAreaManager).GetMethod("QuadOutOfArea"), typeof(GAM_QuadOutOfArea).GetMethod("Prefix")); 33 | IsPatched = true; 34 | Log.Info($"NetworkAnarchy: Cross The Line not found, patch applied", "[NA61]"); 35 | } 36 | } 37 | 38 | internal static void Deactivate() 39 | { 40 | if (IsPatched) 41 | { 42 | Patcher.Unpatch(typeof(GameAreaManager).GetMethod("QuadOutOfArea"), typeof(GAM_QuadOutOfArea).GetMethod("Prefix")); 43 | IsPatched = false; 44 | Log.Info($"NetworkAnarchy: Cross The Line unpatched", "[NA62]"); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /NetworkAnarchy/Integration/NetworkMultitool.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework; 2 | using QCommonLib; 3 | using System; 4 | using System.Reflection; 5 | 6 | namespace NetworkAnarchy.Mods 7 | { 8 | internal class NetworkMultitool 9 | { 10 | private static bool IsEnabled; 11 | private static Assembly ModAssembly; 12 | private static Type toolClass; 13 | 14 | internal static void Initialise() 15 | { 16 | ModAssembly = QCommon.GetAssembly("mod", "networkmultitool"); 17 | if (ModAssembly == null) 18 | { 19 | Log.Info($"NetworkAnarchy: Network Multitool not found", "[NA04]"); 20 | IsEnabled = false; 21 | return; 22 | } 23 | 24 | toolClass = ModAssembly.GetType("NetworkMultitool.NetworkMultitoolTool"); 25 | if (toolClass == null) 26 | { 27 | Log.Info($"NetworkAnarchy: Network Multitool failed loading", "[NA05]"); 28 | IsEnabled = false; 29 | return; 30 | } 31 | 32 | Log.Info($"NetworkAnarchy: Network Multitool loaded", "[NA06]"); 33 | IsEnabled = true; 34 | } 35 | 36 | internal static bool IsToolActive() 37 | { 38 | if (!IsEnabled) return false; 39 | 40 | return Singleton.instance.CurrentTool.GetType() == toolClass; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /NetworkAnarchy/Integration/NetworkSkins.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework.UI; 2 | using System; 3 | using System.Reflection; 4 | using UnityEngine; 5 | 6 | namespace NetworkAnarchy.Mods 7 | { 8 | internal class NetworkSkins 9 | { 10 | private static object m_instance; 11 | 12 | private static FieldInfo m_selectedPrefab; 13 | private static MethodInfo m_update; 14 | 15 | private static Type m_UINetworkSkinsPanel = Type.GetType("NetworkSkins.UI.UINetworkSkinsPanel , NetworkSkins"); 16 | 17 | private static int m_tries; 18 | 19 | public static void ForceUpdate() 20 | { 21 | try 22 | { 23 | if (modExists && InstanceFound()) 24 | { 25 | m_selectedPrefab.SetValue(m_instance, null); 26 | m_update.Invoke(m_instance, null); 27 | } 28 | } 29 | catch (Exception e) 30 | { 31 | m_UINetworkSkinsPanel = null; 32 | m_instance = null; 33 | Log.Error(e, "[NA45]"); 34 | } 35 | } 36 | 37 | public static bool modExists 38 | { 39 | get 40 | { 41 | return m_UINetworkSkinsPanel != null; 42 | } 43 | } 44 | 45 | public static void Init() 46 | { 47 | try 48 | { 49 | m_tries = 0; 50 | m_instance = null; 51 | m_UINetworkSkinsPanel = Type.GetType("NetworkSkins.UI.UINetworkSkinsPanel, NetworkSkins"); 52 | 53 | if (m_UINetworkSkinsPanel != null) 54 | { 55 | m_selectedPrefab = m_UINetworkSkinsPanel.GetField("_selectedPrefab", BindingFlags.Instance | BindingFlags.NonPublic); 56 | m_update = m_UINetworkSkinsPanel.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public); 57 | 58 | if (m_selectedPrefab != null && m_update != null) 59 | { 60 | Log.Info("NetworkAnarchy: Network Skins loaded", "[NA07]"); 61 | } 62 | else 63 | { 64 | m_UINetworkSkinsPanel = null; 65 | m_selectedPrefab = null; 66 | m_update = null; 67 | Log.Info("NetworkAnarchy: Network Skins not loaded", "[NA08]"); 68 | } 69 | } 70 | else 71 | { 72 | Log.Info("NetworkAnarchy: Network Skins not found", "[NA09]"); 73 | } 74 | } 75 | catch (Exception e) 76 | { 77 | m_UINetworkSkinsPanel = null; 78 | Log.Error(e, "[NA34]"); 79 | } 80 | } 81 | 82 | private static bool InstanceFound() 83 | { 84 | try 85 | { 86 | if (m_instance == null && m_tries++ < 10) 87 | { 88 | m_instance = GameObject.FindObjectOfType(m_UINetworkSkinsPanel); 89 | 90 | if (m_tries >= 10) 91 | { 92 | m_UINetworkSkinsPanel = null; 93 | } 94 | } 95 | 96 | return m_instance != null && ((UIComponent)m_instance).enabled; 97 | } 98 | catch (Exception e) 99 | { 100 | m_UINetworkSkinsPanel = null; 101 | m_instance = null; 102 | Log.Error(e, "[NA35]"); 103 | return false; 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /NetworkAnarchy/Integration/ZoningAdjuster.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework; 2 | using QCommonLib; 3 | using System; 4 | using System.Reflection; 5 | 6 | namespace NetworkAnarchy.Mods 7 | { 8 | internal class ZoningAdjuster 9 | { 10 | private static bool IsEnabled; 11 | private static Assembly ModAssembly; 12 | private static Type toolClass; 13 | 14 | internal static void Initialise() 15 | { 16 | ModAssembly = QCommon.GetAssembly("mod", "zoningadjuster"); 17 | if (ModAssembly == null) 18 | { 19 | Log.Info($"NetworkAnarchy: Zoning Adjuster not found", "[NA01]"); 20 | IsEnabled = false; 21 | return; 22 | } 23 | 24 | toolClass = ModAssembly.GetType("ZoningAdjuster.ZoningTool"); 25 | 26 | if (toolClass == null) 27 | { 28 | Log.Info($"NetworkAnarchy: Zoning Adjuster failed loading", "[NA02]"); 29 | IsEnabled = false; 30 | return; 31 | } 32 | 33 | Log.Info($"NetworkAnarchy: Zoning Adjuster loaded", "[NA03]"); 34 | IsEnabled = true; 35 | } 36 | 37 | internal static bool IsToolActive() 38 | { 39 | if (!IsEnabled) return false; 40 | 41 | return Singleton.instance.CurrentTool.GetType() == toolClass; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /NetworkAnarchy/Lang/Str.cs: -------------------------------------------------------------------------------- 1 | namespace NetworkAnarchy.Lang 2 | { 3 | public class Str 4 | { 5 | public static System.Globalization.CultureInfo Culture {get; set;} 6 | public static QCommonLib.Lang.LocalizeManager LocaleManager {get;} = new QCommonLib.Lang.LocalizeManager("Str", typeof(Str).Assembly); 7 | 8 | /// 9 | /// Cycle Modes Left 10 | /// 11 | public static string key_cycleModesLeft => LocaleManager.GetString("key_cycleModesLeft", Culture); 12 | 13 | /// 14 | /// Cycle Modes Right 15 | /// 16 | public static string key_cycleModesRight => LocaleManager.GetString("key_cycleModesRight", Culture); 17 | 18 | /// 19 | /// Elevation Down 20 | /// 21 | public static string key_elevationDown => LocaleManager.GetString("key_elevationDown", Culture); 22 | 23 | /// 24 | /// Reset Elevation 25 | /// 26 | public static string key_elevationReset => LocaleManager.GetString("key_elevationReset", Culture); 27 | 28 | /// 29 | /// Elevation Step Down 30 | /// 31 | public static string key_elevationStepDown => LocaleManager.GetString("key_elevationStepDown", Culture); 32 | 33 | /// 34 | /// Elevation Step Up 35 | /// 36 | public static string key_elevationStepUp => LocaleManager.GetString("key_elevationStepUp", Culture); 37 | 38 | /// 39 | /// Elevation Up 40 | /// 41 | public static string key_elevationUp => LocaleManager.GetString("key_elevationUp", Culture); 42 | 43 | /// 44 | /// Toggle Anarchy 45 | /// 46 | public static string key_toggleAnarchy => LocaleManager.GetString("key_toggleAnarchy", Culture); 47 | 48 | /// 49 | /// Toggle Bending 50 | /// 51 | public static string key_toggleBending => LocaleManager.GetString("key_toggleBending", Culture); 52 | 53 | /// 54 | /// Toggle Editor Grid 55 | /// 56 | public static string key_toggleGrid => LocaleManager.GetString("key_toggleGrid", Culture); 57 | 58 | /// 59 | /// Toggle Snapping 60 | /// 61 | public static string key_toggleSnapping => LocaleManager.GetString("key_toggleSnapping", Culture); 62 | 63 | /// 64 | /// Toggle Straight Slopes 65 | /// 66 | public static string key_toggleStraightSlopes => LocaleManager.GetString("key_toggleStraightSlopes", Culture); 67 | 68 | /// 69 | /// Toggle Zone Override 70 | /// 71 | public static string key_toggleZoneOverride => LocaleManager.GetString("key_toggleZoneOverride", Culture); 72 | 73 | /// 74 | /// More tool options for roads and other networks 75 | /// 76 | public static string mod_Description => LocaleManager.GetString("mod_Description", Culture); 77 | 78 | /// 79 | /// Always show the Network Anarchy panel 80 | /// 81 | public static string options_alwaysVisible => LocaleManager.GetString("options_alwaysVisible", Culture); 82 | 83 | /// 84 | /// Enable debug messages logging 85 | /// 86 | public static string options_enableDebugLogging => LocaleManager.GetString("options_enableDebugLogging", Culture); 87 | 88 | /// 89 | /// If checked, additional debug messages will be logged. 90 | /// 91 | public static string options_enableDebugLoggingTooltip => LocaleManager.GetString("options_enableDebugLoggingTooltip", Culture); 92 | 93 | /// 94 | /// Max turn angle 95 | /// 96 | public static string options_maxTurnAngle => LocaleManager.GetString("options_maxTurnAngle", Culture); 97 | 98 | /// 99 | /// Reduce rail catenary masts 100 | /// 101 | public static string options_reduceCatenaries => LocaleManager.GetString("options_reduceCatenaries", Culture); 102 | 103 | /// 104 | /// Reduce the number of catenary mast of rail lines from 3 to 1 per segment. 105 | /// 106 | public static string options_reduceCatenariesTooltip => LocaleManager.GetString("options_reduceCatenariesTooltip", Culture); 107 | 108 | /// 109 | /// Reset tool window position 110 | /// 111 | public static string options_resetToolWindowPosition => LocaleManager.GetString("options_resetToolWindowPosition", Culture); 112 | 113 | /// 114 | /// Show elevation step slider 115 | /// 116 | public static string options_showElevationStepSlider => LocaleManager.GetString("options_showElevationStepSlider", Culture); 117 | 118 | /// 119 | /// Show slider for changing the elevation step, from 1m to 12m. 120 | /// 121 | public static string options_showElevationStepSliderTooltip => LocaleManager.GetString("options_showElevationStepSliderTooltip", Culture); 122 | 123 | /// 124 | /// Show Labels 125 | /// 126 | public static string options_showLabels => LocaleManager.GetString("options_showLabels", Culture); 127 | 128 | /// 129 | /// Disable to save some screen space 130 | /// 131 | public static string options_showLabelsTooltip => LocaleManager.GetString("options_showLabelsTooltip", Culture); 132 | 133 | /// 134 | /// Show max segment length slider 135 | /// 136 | public static string options_showMaxSegmentLengthSlider => LocaleManager.GetString("options_showMaxSegmentLengthSlider", Culture); 137 | 138 | /// 139 | /// Show slider for changing the maximum segment length, from 4m to 256m (default is 96m). 140 | /// 141 | public static string options_showMaxSegmentLengthSliderTooltip => LocaleManager.GetString("options_showMaxSegmentLengthSliderTooltip", Culture); 142 | 143 | /// 144 | /// Change max turn angle for more realistic tram tracks turns 145 | /// 146 | public static string options_tramMaxTurnAngle => LocaleManager.GetString("options_tramMaxTurnAngle", Culture); 147 | 148 | /// 149 | /// Change all roads with tram tracks max turn angle by the value below if current value is higher. 150 | /// 151 | public static string options_tramMaxTurnAngleTooltip => LocaleManager.GetString("options_tramMaxTurnAngleTooltip", Culture); 152 | 153 | /// 154 | /// Click this button to show Network Anarchy 155 | /// 156 | public static string popup_buttonReminder => LocaleManager.GetString("popup_buttonReminder", Culture); 157 | 158 | /// 159 | /// Collision has been combined with Anarchy mode. 160 | /// 161 | public static string popup_collisionRemoved => LocaleManager.GetString("popup_collisionRemoved", Culture); 162 | 163 | /// 164 | /// Click here for Tool Options 165 | /// 166 | public static string ui_clickForToolOptions => LocaleManager.GetString("ui_clickForToolOptions", Culture); 167 | 168 | /// 169 | /// {0} and {1} to change elevation step 170 | /// 171 | public static string ui_elevationSliderKeyTip => LocaleManager.GetString("ui_elevationSliderKeyTip", Culture); 172 | 173 | /// 174 | /// Elevation Step: 175 | /// 176 | public static string ui_elevationStep => LocaleManager.GetString("ui_elevationStep", Culture); 177 | 178 | /// 179 | /// Show Editor Grid 180 | /// 181 | public static string ui_grid => LocaleManager.GetString("ui_grid", Culture); 182 | 183 | /// 184 | /// Max Segment Length: 185 | /// 186 | public static string ui_maxSegmentLength => LocaleManager.GetString("ui_maxSegmentLength", Culture); 187 | 188 | /// 189 | /// Bridge: Forces the use of bridge pieces if available 190 | /// 191 | public static string ui_modeBridge => LocaleManager.GetString("ui_modeBridge", Culture); 192 | 193 | /// 194 | /// {0} and {1} to cycle modes 195 | /// 196 | public static string ui_modeCycleKeyTip => LocaleManager.GetString("ui_modeCycleKeyTip", Culture); 197 | 198 | /// 199 | /// Elevated: Forces the use of elevated pieces if available 200 | /// 201 | public static string ui_modeElevated => LocaleManager.GetString("ui_modeElevated", Culture); 202 | 203 | /// 204 | /// Ground: Forces the ground to follow the elevation of the road 205 | /// 206 | public static string ui_modeGround => LocaleManager.GetString("ui_modeGround", Culture); 207 | 208 | /// 209 | /// Normal: Unmodded road placement behavior 210 | /// 211 | public static string ui_modeNormal => LocaleManager.GetString("ui_modeNormal", Culture); 212 | 213 | /// 214 | /// Modes: 215 | /// 216 | public static string ui_modes => LocaleManager.GetString("ui_modes", Culture); 217 | 218 | /// 219 | /// Tunnel: Forces the use of tunnel pieces if available 220 | /// 221 | public static string ui_modeTunnel => LocaleManager.GetString("ui_modeTunnel", Culture); 222 | 223 | /// 224 | /// Toggle anarchy 225 | /// 226 | public static string ui_toggleAnarchy => LocaleManager.GetString("ui_toggleAnarchy", Culture); 227 | 228 | /// 229 | /// Toggle road bending 230 | /// 231 | public static string ui_toggleBending => LocaleManager.GetString("ui_toggleBending", Culture); 232 | 233 | /// 234 | /// Toggle collision 235 | /// 236 | public static string ui_toggleCollision => LocaleManager.GetString("ui_toggleCollision", Culture); 237 | 238 | /// 239 | /// Toggle straight slope (don't follow terrain shape) 240 | /// 241 | public static string ui_toggleSlope => LocaleManager.GetString("ui_toggleSlope", Culture); 242 | 243 | /// 244 | /// Toggle node snapping 245 | /// 246 | public static string ui_toggleSnapping => LocaleManager.GetString("ui_toggleSnapping", Culture); 247 | 248 | /// 249 | /// Override zone collision 250 | /// 251 | public static string ui_toggleZoneOverride => LocaleManager.GetString("ui_toggleZoneOverride", Culture); 252 | } 253 | } -------------------------------------------------------------------------------- /NetworkAnarchy/Lang/Str.ja.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | モードを左に移る 122 | 123 | 124 | モードを右に移る 125 | 126 | 127 | 高さを下げる 128 | 129 | 130 | 高さをリセット 131 | 132 | 133 | 高さを少し下げる 134 | 135 | 136 | 高さを少し上げる 137 | 138 | 139 | 高さを上げる 140 | 141 | 142 | アナーキーを切替 143 | 144 | 145 | 湾曲の切り替え 146 | 147 | 148 | グリッド表示の切替 149 | 150 | 151 | スナップの切替 152 | 153 | 154 | 直線スロープの切替 155 | 156 | 157 | ゾーニングの上書きを切り替え 158 | 159 | 160 | 道路やネットワークのためのより多くのツール 161 | 162 | 163 | Network Anarchyのパネルを常に表示 164 | 165 | 166 | デバッグメッセージのログを有効化 167 | 168 | 169 | チェック時は追加のデバッグメッセージをログします。 170 | 171 | 172 | 最大回転角度 173 | 174 | 175 | 架線柱を減らす 176 | 177 | 178 | 架線柱の数を1セグメントにつき3つから1つに減らします。 179 | 180 | 181 | ウィンドウの位置をリセットする 182 | 183 | 184 | 高さのスライダーを表示 185 | 186 | 187 | 高さのステップを1m〜12mに変更するためのスライダーを表示します。 188 | 189 | 190 | ラベルを表示 191 | 192 | 193 | 画面のスペースを節約したい場合は無効化します。 194 | 195 | 196 | セグメントの最大長を調整するためのスライダーを表示 197 | 198 | 199 | セグメントの最大長を4m〜256mに変更するためのスライダーを表示します(デフォルトは96m)。 200 | 201 | 202 | トラム線路のカーブをより現実的にするために最大回転角を変更します 203 | 204 | 205 | 現在の最大角のほうが大きい場合、トラム線路のある全ての道路の最大角が変更されます。 206 | 207 | 208 | Network Anarchyを表示するには、ボタンをクリックして下さい。 209 | 210 | 211 | 衝突判定は、アナーキーモードと統合されました。 212 | 213 | 代わりに「ゾーニングの衝突判定を上書き」ボタンは、パスやフェンスが付近のゾーニング生成の有無を制御します。 214 | 215 | 216 | クリックでオプションを表示 217 | 218 | 219 | {0} と {1} で高さのピッチを変更します。 220 | {0} and {1} will be replaced by the keybindings for elevation steps 221 | 222 | 223 | 高さの変更量: 224 | Keep the ":" if used in your language 225 | 226 | 227 | エディタのグリッドを表示 228 | 229 | 230 | セグメントの最大長: 231 | Keep the ":" if used in your language 232 | 233 | 234 | 橋梁: 可能であれば橋梁を使用する 235 | 236 | 237 | {0} と {1} でモードを左右に切り替えます。 238 | {0} and {1} will be replaced by the keybindings for cycling modes 239 | 240 | 241 | 高架: 可能であれば高架を使用する 242 | 243 | 244 | 地面: 道路の傾斜を地面に沿わせる 245 | 246 | 247 | 通常: 非mod状態で道路を配置する 248 | 249 | 250 | モード 251 | Keep the ":" if used in your language 252 | 253 | 254 | トンネル: 可能であればトンネルを使用する 255 | 256 | 257 | アナーキーの切替 258 | 259 | 260 | 湾曲の切替 261 | 262 | 263 | 衝突判定の切替 264 | 265 | 266 | 直線スロープの切替 (地形に追従しない) 267 | 268 | 269 | ノードスナップの切替 270 | 271 | 272 | ゾーニングの衝突判定を上書き 273 | 274 | -------------------------------------------------------------------------------- /NetworkAnarchy/Lang/Str.zh-cn.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 左循环模式 122 | 123 | 124 | 右循环模式 125 | 126 | 127 | 高度下降 128 | 129 | 130 | 重设高度 131 | 132 | 133 | 高度单次下降 134 | 135 | 136 | 高度单次提升 137 | 138 | 139 | 高度提升 140 | 141 | 142 | 切换无碰撞状态 143 | 144 | 145 | 切换弯曲 146 | 147 | 148 | 切换编辑器网格 149 | 150 | 151 | 切换捕捉吸附 152 | 153 | 154 | 切换平直坡道 155 | 156 | 157 | 切换区域覆盖 158 | 159 | 160 | 更多的道路及其他网络工具选项 161 | 162 | 163 | 始终显示 Network Anarchy 的控制面板 164 | 165 | 166 | 启用调试信息日志记录 167 | 168 | 169 | 如果选中该选项,则将会记录额外的调试信息。 170 | 171 | 172 | 最大转角 173 | 174 | 175 | 减少轨道接触网支柱 176 | 177 | 178 | 将每段轨道的接触网支柱数量从3个减少到1个。 179 | 180 | 181 | 重设工具窗口位置 182 | 183 | 184 | 显示一次性调整高度滑条 185 | 186 | 187 | 显示将高度单次调整范围更改为1m~12m的滑条。 188 | 189 | 190 | 显示标签 191 | 192 | 193 | 禁用以节省一些屏幕空间 194 | 195 | 196 | 显示最大分段长度滑条 197 | 198 | 199 | 显示最大分段长度调整4m~256m(默认值为96m)的滑条。 200 | 201 | 202 | 为了更真实的有轨电车与列车转向而更改最大转角 203 | 204 | 205 | 如果当前值较高,则将所有有轨电车轨道最大转弯角度的道路更改为以下值。 206 | 207 | 208 | 点击此按钮显示 Network Anarchy 209 | 210 | 211 | 碰撞功能已经和无碰撞模式相结合。 212 | 在它所在位置,覆盖区域碰撞功能按钮以控制路径/围栏是否会阻止周围的分区地块的生成。 213 | 214 | 215 | 点击此处查看工具选项 216 | 217 | 218 | 按 {0} 以及 {1} 来改变单次调整高度 219 | {0} and {1} will be replaced by the keybindings for elevation steps 220 | 221 | 222 | 单次调整高度: 223 | Keep the ":" if used in your language 224 | 225 | 226 | 显示编辑器网格 227 | 228 | 229 | 最大路段长度: 230 | Keep the ":" if used in your language 231 | 232 | 233 | 桥梁:如果开启,道路将强制在任何地形使用桥梁模式。 234 | 235 | 236 | 按 {0} 以及 {1} 来切换模式 237 | {0} and {1} will be replaced by the keybindings for cycling modes 238 | 239 | 240 | 高架:如果开启,道路将强制在任何地形使用高架模式 241 | 242 | 243 | 地面:如果开启,道路将强制在任何地形使用地面模式 244 | 245 | 246 | 正常:即游戏默认的逢山开洞、遇水架桥行为 247 | 248 | 249 | 模式: 250 | Keep the ":" if used in your language 251 | 252 | 253 | 隧道:如果开启,道路将在任何地形强制使用隧道模式 254 | 255 | 256 | 切换无碰撞状态 257 | 258 | 259 | 切换道路弯曲 260 | 261 | 262 | 切换碰撞 263 | 264 | 265 | 切换平直的斜坡(不跟随地形) 266 | 267 | 268 | 切换捕捉吸附 269 | 270 | 271 | 覆盖区域碰撞 272 | 273 | -------------------------------------------------------------------------------- /NetworkAnarchy/LoadingManagers.cs: -------------------------------------------------------------------------------- 1 | using QCommonLib; 2 | using System; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | 6 | namespace NetworkAnarchy 7 | { 8 | // Adapted from AnyRoadOutsideConnectionsRevisited by Mbyron26 9 | internal class AnyRoadOutsideConnection 10 | { 11 | private static BuildingInfo connectionTemplate; 12 | private static readonly Queue InfoQueue = new Queue(); 13 | private static int count = 0; 14 | 15 | /// 16 | /// Clear the queue/template, needed for second-loads 17 | /// 18 | public static void Initialise() 19 | { 20 | connectionTemplate = null; 21 | InfoQueue.Clear(); 22 | } 23 | 24 | /// 25 | /// Finish up the road AI conversion after the level has loaded 26 | /// 27 | internal static void Finalise() 28 | { 29 | Log.Info($"Enabled outside connections for {count} roads", "[NA57]"); 30 | } 31 | 32 | /// 33 | /// Apply the conversion to roads that don't have the outsideConnection building set 34 | /// 35 | /// The network to check and, if needed, attached outside connection 36 | internal static void Apply(NetInfo info) 37 | { 38 | if (info == null || QCommon.Scene != QCommon.SceneTypes.Game) 39 | { 40 | return; 41 | } 42 | if (info.m_netAI is RoadBaseAI ai) 43 | { 44 | if (ai.m_outsideConnection == null && connectionTemplate == null) 45 | { // If no outsideConnection is set but the template building hasn't been found, queue for later 46 | InfoQueue.Enqueue(ai); 47 | } 48 | else 49 | { 50 | if (ai.m_outsideConnection == null) 51 | { 52 | ai.m_outsideConnection = connectionTemplate; 53 | count++; 54 | } 55 | else 56 | { 57 | if (connectionTemplate == null) 58 | { 59 | connectionTemplate = ai.m_outsideConnection; 60 | } 61 | } 62 | while (InfoQueue.Count > 0) 63 | { 64 | InfoQueue.Dequeue().m_outsideConnection = connectionTemplate; 65 | count++; 66 | } 67 | } 68 | } 69 | } 70 | } 71 | 72 | internal class NetworkTiling 73 | { 74 | /// 75 | /// Search network prefabs for any which have "NetworkTiling" in their segment or node material name 76 | /// Code by Ronyx69 (https://gist.github.com/ronyx69/4f06181c8082188418cd0c224f630a09) 77 | /// 78 | internal static void Apply() 79 | { 80 | int cSeg = 0, cNode = 0; 81 | 82 | for (uint i = 0; i < PrefabCollection.LoadedCount(); i++) 83 | { 84 | var prefab = PrefabCollection.GetLoaded(i); 85 | if (prefab == null) continue; 86 | 87 | if (prefab.m_segments != null) 88 | { 89 | for (uint j = 0; j < prefab.m_segments.Length; j++) 90 | { 91 | if (prefab.m_segments[j].m_material == null) continue; 92 | 93 | if (prefab.m_segments[j].m_material.name.Contains("NetworkTiling")) 94 | { 95 | cSeg++; 96 | string[] floats = prefab.m_segments[j].m_material.name.Split(' '); 97 | var tiling = Convert.ToSingle(floats[1]); 98 | prefab.m_segments[j].m_material.mainTextureScale = new Vector2(1, tiling); 99 | if (prefab.m_segments[j].m_segmentMaterial != null) prefab.m_segments[j].m_segmentMaterial.mainTextureScale = new Vector2(1, tiling); 100 | if (prefab.m_segments[j].m_lodMaterial != null) prefab.m_segments[j].m_lodMaterial.mainTextureScale = new Vector2(1, tiling); 101 | if (prefab.m_segments[j].m_combinedLod.m_material != null) prefab.m_segments[j].m_combinedLod.m_material.mainTextureScale = new Vector2(1, Math.Abs(tiling)); 102 | } 103 | } 104 | } 105 | 106 | if (prefab.m_nodes != null) 107 | { 108 | for (uint j = 0; j < prefab.m_nodes.Length; j++) 109 | { 110 | if (prefab.m_nodes[j].m_material == null) continue; 111 | 112 | if (prefab.m_nodes[j].m_material.name.Contains("NetworkTiling")) 113 | { 114 | cNode++; 115 | string[] floats = prefab.m_nodes[j].m_material.name.Split(' '); 116 | var tiling = Convert.ToSingle(floats[1]); 117 | prefab.m_nodes[j].m_material.mainTextureScale = new Vector2(1, tiling); 118 | if (prefab.m_nodes[j].m_nodeMaterial != null) prefab.m_nodes[j].m_nodeMaterial.mainTextureScale = new Vector2(1, tiling); 119 | if (prefab.m_nodes[j].m_lodMaterial != null) prefab.m_nodes[j].m_lodMaterial.mainTextureScale = new Vector2(1, tiling); 120 | if (prefab.m_nodes[j].m_combinedLod.m_material != null) prefab.m_nodes[j].m_combinedLod.m_material.mainTextureScale = new Vector2(1, Math.Abs(tiling)); 121 | } 122 | } 123 | } 124 | } 125 | 126 | Log.Info($"Applying Network Tiling ({cSeg} segments, {cNode} nodes)", "[NA56]"); 127 | } 128 | } 129 | 130 | internal class UpdateCatenaries 131 | { 132 | /// 133 | /// Set the number of catenaries based on the player's choice 134 | /// 135 | internal static void Apply() 136 | { 137 | int probability = NetworkAnarchy.reduceCatenary.value ? 0 : 100; 138 | 139 | for (uint i = 0; i < PrefabCollection.PrefabCount(); i++) 140 | { 141 | NetInfo info = PrefabCollection.GetPrefab(i); 142 | if (info == null) 143 | { 144 | continue; 145 | } 146 | 147 | for (int j = 0; j < info.m_lanes.Length; j++) 148 | { 149 | if (info.m_lanes[j] != null && info.m_lanes[j].m_laneProps != null) 150 | { 151 | NetLaneProps.Prop[] props = info.m_lanes[j].m_laneProps.m_props; 152 | if (props == null) 153 | { 154 | continue; 155 | } 156 | 157 | for (int k = 0; k < props.Length; k++) 158 | { 159 | if (props[k] != null && props[k].m_prop != null && props[k].m_segmentOffset == 0f && props[k].m_prop.name.ToLower().Contains("powerline")) 160 | { 161 | props[k].m_probability = probability; 162 | } 163 | } 164 | } 165 | } 166 | } 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /NetworkAnarchy/ModInfo.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework; 2 | using ColossalFramework.Globalization; 3 | using ColossalFramework.UI; 4 | using ICities; 5 | using NetworkAnarchy.Lang; 6 | using NetworkAnarchy.Patches; 7 | using NetworkAnarchy.UI; 8 | using QCommonLib; 9 | using QCommonLib.Lang; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Globalization; 13 | using UnityEngine; 14 | 15 | // Error code max: 74 16 | 17 | namespace NetworkAnarchy 18 | { 19 | public class ModInfo : LoadingExtensionBase, IUserMod 20 | { 21 | public ModInfo() 22 | { 23 | try 24 | { 25 | // Creating setting file 26 | if (GameSettings.FindSettingsFileByName(NetworkAnarchy.settingsFileName) == null) 27 | { 28 | GameSettings.AddSettingsFile(new SettingsFile[] { new SettingsFile() { fileName = NetworkAnarchy.settingsFileName } }); 29 | } 30 | } 31 | catch (Exception e) 32 | { 33 | Debug.Log("Couldn't load/create the setting file."); 34 | Debug.LogException(e); 35 | } 36 | } 37 | 38 | private readonly string m_shortName = "Network Anarchy"; 39 | public string Name => m_shortName + " " + QVersion.Version(); 40 | public string Description => Str.mod_Description; 41 | 42 | //internal static GameObject DebugGO; 43 | //internal static DebugPanel s_debugPanel; 44 | 45 | //internal static QLogger Log; 46 | internal static QPatcher Patcher; 47 | internal string HarmonyId = "quboid.csl_mods.networkanarchy"; 48 | 49 | internal static CultureInfo Culture => QCommon.GetCultureInfo(); 50 | protected LocalizeManager LocalizeManager => Str.LocaleManager; 51 | protected LocalizeManager QLocalizeManager => QStr.LocaleManager; 52 | 53 | public void OnSettingsUI(UIHelperBase helper) 54 | { 55 | LocaleManager.eventLocaleChanged -= LocaleChanged; 56 | LocaleChanged(); 57 | LocaleManager.eventLocaleChanged += LocaleChanged; 58 | 59 | ModOptions options = new ModOptions(helper, Name); 60 | } 61 | 62 | /// 63 | /// Executes at main menu 64 | /// 65 | public void OnEnabled() 66 | { 67 | #if DEBUG 68 | Patcher = new QPatcher(HarmonyId, EarlyPatches.Deploy, EarlyPatches.Revert, true); 69 | Log.IsDebug = true; 70 | #else 71 | //Log = new QLogger(true);// NetworkAnarchy.showDebugMessages); 72 | Patcher = new QPatcher(HarmonyId, EarlyPatches.Deploy, EarlyPatches.Revert); 73 | Log.IsDebug = true; // Always log stuff for now 74 | #endif 75 | 76 | AnyRoadOutsideConnection.Initialise(); 77 | 78 | 79 | if (UIView.GetAView() == null) 80 | { // Game loaded to main menu 81 | LoadingManager.instance.m_introLoaded += CheckIncompatibleMods; 82 | } 83 | else 84 | { // Mod enabled in Content Manager 85 | CheckIncompatibleMods(); 86 | } 87 | 88 | // Hot reload 89 | if (LoadingManager.exists && LoadingManager.instance.m_loadingComplete) 90 | { 91 | InitializeMod(); 92 | } 93 | } 94 | 95 | public void OnDisabled() 96 | { 97 | if (LoadingManager.exists && LoadingManager.instance.m_loadingComplete) 98 | { 99 | DestroyMod(); 100 | } 101 | 102 | //Log = null; 103 | } 104 | 105 | public override void OnLevelLoaded(LoadMode mode) 106 | { 107 | InitializeMod(); 108 | } 109 | 110 | public override void OnLevelUnloading() 111 | { 112 | DestroyMod(); 113 | } 114 | 115 | public void InitializeMod() 116 | { 117 | if (NetworkAnarchy.instance == null) 118 | { 119 | // Creating the instance 120 | NetworkAnarchy.instance = new GameObject("NetworkAnarchy").AddComponent(); 121 | 122 | // Don't destroy it 123 | GameObject.DontDestroyOnLoad(NetworkAnarchy.instance); 124 | } 125 | else 126 | { 127 | NetworkAnarchy.instance.Start(); 128 | NetworkAnarchy.instance.enabled = true; 129 | } 130 | 131 | Patcher.PatchAll(); 132 | if (QCommon.Scene != QCommon.SceneTypes.AssetEditor) 133 | { 134 | Mods.CrossTheLine.Initialise(Patcher); 135 | } 136 | else 137 | { 138 | GameAreaManager.instance.m_maxAreaCount = GameAreaManager.AREAGRID_RESOLUTION * GameAreaManager.AREAGRID_RESOLUTION; 139 | for (int i = 0; i < GameAreaManager.instance.m_maxAreaCount; i++) 140 | { 141 | GameAreaManager.instance.m_areaGrid[i] = i + 1; 142 | } 143 | GameAreaManager.instance.m_areaCount = GameAreaManager.instance.m_maxAreaCount; 144 | } 145 | 146 | //DebugGO = new GameObject("NA_DebugPanel"); 147 | //DebugGO.AddComponent(); 148 | //s_debugPanel = DebugGO.GetComponent(); 149 | } 150 | 151 | public void DestroyMod() 152 | { 153 | Mods.CrossTheLine.Deactivate(); 154 | Patcher.UnpatchAll(); 155 | NetworkAnarchy.instance.RestoreDefaultKeys(); 156 | 157 | //if (s_debugPanel != null) 158 | //{ 159 | // GameObject.Destroy(s_debugPanel); 160 | // s_debugPanel = null; 161 | //} 162 | 163 | if (NetworkAnarchy.instance != null) 164 | { 165 | UIView.Find("OptionsBar")?.RemoveUIComponent(NetworkAnarchy.m_toolOptionButton); 166 | GameObject.Destroy(NetworkAnarchy.m_toolOptionButton.m_toolOptionsPanel.gameObject); 167 | GameObject.Destroy(NetworkAnarchy.m_toolOptionButton.m_toolOptionsPanel); 168 | NetworkAnarchy.m_toolOptionButton.m_toolOptionsPanel = null; 169 | GameObject.Destroy(NetworkAnarchy.m_toolOptionButton.gameObject); 170 | GameObject.Destroy(NetworkAnarchy.m_toolOptionButton); 171 | NetworkAnarchy.m_toolOptionButton = null; 172 | NetworkAnarchy.instance.enabled = false; 173 | GameObject.Destroy(NetworkAnarchy.instance.gameObject); 174 | GameObject.Destroy(NetworkAnarchy.instance); 175 | NetworkAnarchy.instance = null; 176 | } 177 | 178 | LocaleManager.eventLocaleChanged -= LocaleChanged; 179 | } 180 | 181 | public void CheckIncompatibleMods() 182 | { 183 | Dictionary incompatbleMods = new Dictionary 184 | { 185 | //{ 2862881785, "Network Anarchy" }, 186 | { 2917150208, "Network Anarchy (beta)" }, 187 | { 1844442251, "Fine Road Tool" }, 188 | { 1844440354, "Fine Road Anarchy" }, 189 | { 2847163882, "Any Road Outside Connections Revisited" }, 190 | { 883332136, "Any Road Outside Connections" }, 191 | { 2558311605, "Left-Hand Network Fix" }, 192 | { 1274199764, "Network Tiling" }, 193 | { 2085018096, "Node Spacer" }, 194 | { 650436109, "Quay Anarchy" }, 195 | { 707759735, "Ship Path Anarchy" }, 196 | { 1586027591, "Tiny Segments - Extra Anarchy" }, 197 | }; 198 | 199 | _ = new QIncompatible(incompatbleMods, Log.instance, m_shortName); 200 | } 201 | 202 | internal static void LocaleChanged() 203 | { 204 | if (NetworkAnarchy.instance != null) 205 | { 206 | if (NetworkAnarchy.m_toolOptionButton != null) 207 | { 208 | NetworkAnarchy.m_toolOptionButton.CreateOptionPanel(true); 209 | } 210 | } 211 | 212 | Log.Info($"Network Anarchy Locale changed {Str.Culture?.Name}->{Culture.Name}", "[NA48]"); 213 | Str.Culture = Culture; 214 | QStr.Culture = Culture; 215 | } 216 | 217 | internal static string GetString(object o) 218 | { 219 | if (o == null) return ""; 220 | return o.ToString(); 221 | } 222 | } 223 | 224 | //internal class DebugPanel : MonoBehaviour 225 | //{ 226 | // internal UIPanel m_panel; 227 | // internal UILabel m_label; 228 | 229 | // internal DebugPanel() 230 | // { 231 | // m_panel = UIView.GetAView().AddUIComponent(typeof(UIPanel)) as UIPanel; 232 | // m_panel.name = "NetworkAnarchy_DebugPanel"; 233 | // m_panel.atlas = QTextures.GetAtlas("Ingame"); 234 | // m_panel.backgroundSprite = "SubcategoriesPanel"; 235 | // m_panel.size = new Vector2(400, 200); 236 | // m_panel.absolutePosition = new Vector3(400, 50); 237 | // m_panel.clipChildren = true; 238 | // m_panel.isVisible = true; 239 | 240 | // m_label = m_panel.AddUIComponent(); 241 | // m_label.text = "Debug"; 242 | // m_label.relativePosition = new Vector3(5, 5); 243 | // m_label.size = m_panel.size - new Vector2(10, 10); 244 | // } 245 | 246 | // internal void Text(string text) 247 | // { 248 | // Singleton.instance.m_ThreadingWrapper.QueueMainThread(() => { 249 | // if (m_label != null) 250 | // { 251 | // m_label.text = text; 252 | // } 253 | // }); 254 | // } 255 | //} 256 | 257 | public class Log : QLoggerStatic { } 258 | } 259 | -------------------------------------------------------------------------------- /NetworkAnarchy/NA_SimulationTick.cs: -------------------------------------------------------------------------------- 1 | using ICities; 2 | using System; 3 | using UnityEngine; 4 | 5 | namespace NetworkAnarchy 6 | { 7 | public partial class NetworkAnarchy : MonoBehaviour 8 | { 9 | public class AfterSimulationTick : ThreadingExtensionBase 10 | { 11 | public override void OnAfterSimulationTick() 12 | { 13 | if (instance == null || !instance.enabled) return; 14 | 15 | try 16 | { 17 | instance.OnAfterSimulationTick(); 18 | } 19 | catch (Exception e) 20 | { 21 | Log.Error(e, "[NA23]"); 22 | } 23 | } 24 | } 25 | 26 | public virtual void OnAfterSimulationTick() 27 | { 28 | if (m_buildingTool == null) 29 | { 30 | return; 31 | } 32 | 33 | // Removes HeightTooHigh & TooShort errors 34 | if (Anarchy && IsBuildingToolEnabled()) 35 | { 36 | var errors = (ToolBase.ToolErrors)m_placementErrorsField.GetValue(m_buildingTool); 37 | if ((errors & ToolBase.ToolErrors.HeightTooHigh) == ToolBase.ToolErrors.HeightTooHigh) 38 | { 39 | errors &= ~ToolBase.ToolErrors.HeightTooHigh; 40 | m_placementErrorsField.SetValue(m_buildingTool, errors); 41 | } 42 | 43 | if ((errors & ToolBase.ToolErrors.TooShort) == ToolBase.ToolErrors.TooShort) 44 | { 45 | errors &= ~ToolBase.ToolErrors.TooShort; 46 | m_placementErrorsField.SetValue(m_buildingTool, errors); 47 | } 48 | 49 | if ((errors & ToolBase.ToolErrors.SlopeTooSteep) == ToolBase.ToolErrors.SlopeTooSteep) 50 | { 51 | errors &= ~ToolBase.ToolErrors.SlopeTooSteep; 52 | m_placementErrorsField.SetValue(m_buildingTool, errors); 53 | } 54 | } 55 | 56 | // Resume fixes 57 | if (m_fixTunnelsCount != 0) 58 | { 59 | FixTunnels(); 60 | } 61 | if (m_fixNodesCount != 0) 62 | { 63 | FixNodes(); 64 | } 65 | 66 | // Stop here if neither active nor bulldozer tool enabled 67 | if (!IsActive && !IsBulldozeToolEnabled()) 68 | { 69 | return; 70 | } 71 | 72 | // Check if segment have been created/deleted/updated 73 | if (m_segmentCount != NetManager.instance.m_segmentCount || (bool)m_upgradingField.GetValue(m_netTool)) 74 | { 75 | m_segmentCount = NetManager.instance.m_segmentCount; 76 | 77 | m_fixTunnelsCount = 0; 78 | m_fixNodesCount = 0; 79 | 80 | FixTunnels(); 81 | FixNodes(); 82 | } 83 | 84 | if (!IsActive) 85 | { 86 | return; 87 | } 88 | 89 | // Fix first control point elevation 90 | int count = (int)m_controlPointCountField.GetValue(m_netTool); 91 | if (count != m_controlPointCount && m_controlPointCount == 0 && count == 1) 92 | { 93 | if (FixControlPoint(0)) 94 | { 95 | m_elevation = Mathf.RoundToInt(Mathf.RoundToInt(m_controlPoints[0].m_elevation / elevationStep) * elevationStep * 256f / 12f); 96 | UpdateElevation(); 97 | 98 | Log.Debug($"OnAfterSimulationTick: m_controlPointCountField:{m_controlPointCountField.GetValue(m_netTool)}, m_controlPointCount:{m_controlPointCount}", "[NA71]"); 99 | m_toolOptionButton?.UpdateButton(); 100 | } 101 | } 102 | // Fix last control point elevation 103 | else if (count == ((m_netTool.m_mode == NetTool.Mode.Curved || m_netTool.m_mode == NetTool.Mode.Freeform) ? 2 : 1)) 104 | { 105 | FixControlPoint(count); 106 | } 107 | m_controlPointCount = count; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /NetworkAnarchy/NetAIWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace NetworkAnarchy 4 | { 5 | public class NetAIWrapper 6 | { 7 | private readonly NetAI m_ai; 8 | 9 | private readonly FieldInfo m_elevated; 10 | private readonly FieldInfo m_bridge; 11 | private readonly FieldInfo m_slope; 12 | private readonly FieldInfo m_tunnel; 13 | private readonly FieldInfo m_invisible; 14 | 15 | public NetAIWrapper(NetAI ai) 16 | { 17 | m_ai = ai; 18 | 19 | try 20 | { 21 | m_elevated = m_ai.GetType().GetField("m_elevatedInfo"); 22 | m_bridge = m_ai.GetType().GetField("m_bridgeInfo"); 23 | m_slope = m_ai.GetType().GetField("m_slopeInfo"); 24 | m_tunnel = m_ai.GetType().GetField("m_tunnelInfo"); 25 | m_invisible = m_ai.GetType().GetField("m_invisible"); 26 | } 27 | catch 28 | { 29 | m_elevated = null; 30 | m_bridge = null; 31 | m_slope = null; 32 | m_tunnel = null; 33 | m_invisible = null; 34 | } 35 | } 36 | 37 | public bool HasElevation 38 | { 39 | get { return m_elevated != null && m_bridge != null && m_slope != null && m_tunnel != null; } 40 | } 41 | 42 | public NetInfo Info 43 | { 44 | get { return m_ai.m_info; } 45 | set { m_ai.m_info = value; } 46 | } 47 | 48 | public NetInfo Elevated 49 | { 50 | get { return HasElevation ? m_elevated.GetValue(m_ai) as NetInfo : null; } 51 | set 52 | { 53 | if (!HasElevation) return; 54 | m_elevated.SetValue(m_ai, value); 55 | } 56 | } 57 | 58 | public NetInfo Bridge 59 | { 60 | get { return HasElevation ? m_bridge.GetValue(m_ai) as NetInfo : null; } 61 | set 62 | { 63 | if (!HasElevation) return; 64 | m_bridge.SetValue(m_ai, value); 65 | } 66 | } 67 | 68 | public NetInfo Slope 69 | { 70 | get { return HasElevation ? m_slope.GetValue(m_ai) as NetInfo : null; } 71 | set 72 | { 73 | if (!HasElevation) return; 74 | m_slope.SetValue(m_ai, value); 75 | } 76 | } 77 | 78 | public NetInfo Tunnel 79 | { 80 | get { return HasElevation ? m_tunnel.GetValue(m_ai) as NetInfo : null; } 81 | set 82 | { 83 | if (!HasElevation) return; 84 | m_tunnel.SetValue(m_ai, value); 85 | } 86 | } 87 | 88 | public bool IsInvisible() 89 | { 90 | if (m_invisible != null) return (bool)m_invisible.GetValue(m_ai); 91 | 92 | return false; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /NetworkAnarchy/NetPrefab.cs: -------------------------------------------------------------------------------- 1 | using QCommonLib; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace NetworkAnarchy 6 | { 7 | public enum Modes 8 | { 9 | Normal, 10 | Ground, 11 | Elevated, 12 | Bridge, 13 | Tunnel, 14 | Single 15 | } 16 | 17 | public class NetPrefab 18 | { 19 | public static Dictionary s_toGroundMap = new Dictionary(); 20 | 21 | protected readonly bool m_hasElevation; 22 | protected readonly NetInfo m_prefab; 23 | protected readonly NetInfo m_elevated; 24 | protected readonly NetInfo m_bridge; 25 | protected readonly NetInfo m_slope; 26 | protected readonly NetInfo m_tunnel; 27 | 28 | protected NetInfo netInfo; 29 | protected NetAIWrapper netAI; 30 | public NetAIWrapper NetAI => netAI; 31 | 32 | // Needs to check if it's elevated/etc and pick ground version 33 | public NetPrefab(NetInfo info) 34 | { 35 | netInfo = GetOnGround(info); 36 | netAI = new NetAIWrapper(netInfo.m_netAI); 37 | 38 | m_hasElevation = netAI.HasElevation; 39 | if (m_hasElevation) 40 | { 41 | m_elevated = netAI.Elevated; 42 | m_bridge = netAI.Bridge; 43 | m_slope = netAI.Slope; 44 | m_tunnel = netAI.Tunnel; 45 | } 46 | } 47 | 48 | public virtual bool HasVariation => (m_elevated != null || m_bridge != null || m_slope != null || m_tunnel != null); 49 | 50 | public static NetPrefab Factory(NetInfo info) 51 | { 52 | return new NetPrefab(info); 53 | } 54 | 55 | public override string ToString() 56 | { 57 | return netInfo.name; 58 | } 59 | 60 | 61 | // Static Prefab managers 62 | 63 | private static readonly Dictionary DefaultMaxAngles = new Dictionary(); 64 | private static readonly Dictionary DefaultMaxAnglesCos = new Dictionary(); 65 | public static void SetMaxTurnAngle(float angle) 66 | { 67 | ResetMaxTurnAngle(); 68 | for (uint i = 0; i < PrefabCollection.PrefabCount(); i++) 69 | { 70 | NetInfo info = PrefabCollection.GetPrefab(i); 71 | if (info == null) continue; 72 | if ((info.m_connectGroup & (NetInfo.ConnectGroup.CenterTram | NetInfo.ConnectGroup.NarrowTram | NetInfo.ConnectGroup.SingleTram | NetInfo.ConnectGroup.WideTram)) != NetInfo.ConnectGroup.None) 73 | { 74 | DefaultMaxAngles.Add(info, info.m_maxTurnAngle); 75 | DefaultMaxAnglesCos.Add(info, Mathf.Cos(Mathf.Deg2Rad * info.m_maxTurnAngle)); 76 | 77 | if (info.m_maxTurnAngle > angle) 78 | { 79 | info.m_maxTurnAngle = angle; 80 | info.m_maxTurnAngleCos = Mathf.Cos(Mathf.Deg2Rad * angle); 81 | } 82 | } 83 | } 84 | } 85 | 86 | public static void ResetMaxTurnAngle() 87 | { 88 | foreach (var pair in DefaultMaxAngles) 89 | { 90 | pair.Key.m_maxTurnAngle = pair.Value; 91 | pair.Key.m_maxTurnAngleCos = DefaultMaxAnglesCos[pair.Key]; 92 | } 93 | } 94 | 95 | /// 96 | /// Is the player placing a single object (rather than a draggable network)? 97 | /// 98 | private static bool m_singleMode; 99 | public static bool SingleMode 100 | { 101 | get { return m_singleMode; } 102 | set 103 | { 104 | if (value == m_singleMode) return; 105 | m_singleMode = value; 106 | } 107 | } 108 | 109 | public static void CreateToGroundMap() 110 | { 111 | s_toGroundMap = new Dictionary(); 112 | //string msg = $"NetInfo: {PrefabCollection.PrefabCount()}, "; 113 | 114 | HashSet allNetInfos = new HashSet(); 115 | for (uint i = 0; i < PrefabCollection.PrefabCount(); i++) 116 | { 117 | allNetInfos.Add(PrefabCollection.GetPrefab(i)); 118 | } 119 | HashSet groundOnly = new HashSet(allNetInfos); 120 | foreach (NetInfo info in allNetInfos) 121 | { 122 | if (info == null || info.m_netAI == null) 123 | { 124 | groundOnly.Remove(info); 125 | continue; 126 | } 127 | NetAIWrapper ai = new NetAIWrapper(info.m_netAI); 128 | 129 | // Stop on-ground segments that aren't at terrain height from being bumpy at nodes 130 | if (info.m_flattenTerrain && !info.m_netAI.IsUnderground() && !ai.IsInvisible() && 131 | info != ai.Elevated && info != ai.Bridge && info != ai.Slope && info != ai.Tunnel) 132 | { 133 | info.m_followTerrain = false; 134 | //msg += $"\n {info.name}"; 135 | } 136 | 137 | if (ai.Tunnel != null) groundOnly.Remove(ai.Tunnel); 138 | if (ai.Slope != null) groundOnly.Remove(ai.Slope); 139 | if (ai.Elevated != null) groundOnly.Remove(ai.Elevated); 140 | if (ai.Bridge != null) groundOnly.Remove(ai.Bridge); 141 | } 142 | 143 | for (uint i = 0; i < PrefabCollection.PrefabCount(); i++) 144 | { 145 | NetInfo info = PrefabCollection.GetPrefab(i); 146 | if (info == null) continue; 147 | if (info.m_netAI == null) continue; 148 | if (!groundOnly.Contains(info)) continue; 149 | NetAIWrapper ai = new NetAIWrapper(info.m_netAI); 150 | 151 | if (ai.Tunnel != null && !s_toGroundMap.ContainsKey(ai.Tunnel)) s_toGroundMap.Add(ai.Tunnel, info); 152 | if (ai.Slope != null && !s_toGroundMap.ContainsKey(ai.Slope)) s_toGroundMap.Add(ai.Slope, info); 153 | if (ai.Elevated != null && !s_toGroundMap.ContainsKey(ai.Elevated)) s_toGroundMap.Add(ai.Elevated, info); 154 | if (ai.Bridge != null && !s_toGroundMap.ContainsKey(ai.Bridge)) s_toGroundMap.Add(ai.Bridge, info); 155 | 156 | //if (info.name.Contains("Pedestrian") && !info.name.Contains("Street")) msg += $" {info.name}\n T:{ai.Tunnel != null}, S:{ai.Slope != null}, E:{ai.Elevated != null}, B:{ai.Bridge != null} ({ai.Elevated?.name})\n"; 157 | } 158 | 159 | //Log.Debug($"groundOnly: {groundOnly.Count}, unbumpified:" + msg); 160 | } 161 | 162 | public static NetInfo GetOnGround(NetInfo info) 163 | { 164 | if (NetworkAnarchy.instance.IsBuildingIntersection()) 165 | { 166 | if (!NetworkAnarchy.instance.IsBuildingGroundIntersection()) 167 | { 168 | NetAIWrapper ai = new NetAIWrapper(s_toGroundMap.ContainsKey(info) ? s_toGroundMap[info].m_netAI : info.m_netAI); 169 | if (info == ai.Info) 170 | { // Switch ground nodes to elevated 171 | info = ai.Elevated ?? ai.Info; 172 | } 173 | } 174 | // Building ground intersection, don't alter info 175 | } 176 | else if (QCommon.Scene == QCommon.SceneTypes.AssetEditor && ToolManager.instance.m_properties.m_editPrefabInfo is NetInfo editPrefab) 177 | { 178 | NetAIWrapper editAI = new NetAIWrapper(editPrefab.m_netAI); 179 | if (info == editPrefab || info == editAI.Elevated || info == editAI.Bridge || info == editAI.Tunnel || info == editAI.Slope) 180 | { 181 | info = editPrefab; 182 | } 183 | } 184 | else if (s_toGroundMap.ContainsKey(info)) 185 | { 186 | info = s_toGroundMap[info]; 187 | } 188 | return info; 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /NetworkAnarchy/NetworkAnarchy.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net35 4 | False 5 | 3.2.4 6 | $(MSBuildProgramFiles32)/Steam/steamapps/common/Cities_Skylines/Cities_Data/Managed/ 7 | 8 | $(AssemblySearchPaths); 9 | $(ManagedDLLPath); 10 | ../../../../Libraries/; 11 | 12 | AnyCPU 13 | False 14 | 3.2.4.* 15 | 3.2.4.0 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | False 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | Always 50 | 51 | 52 | Always 53 | 54 | 55 | Always 56 | 57 | 58 | Always 59 | 60 | 61 | Always 62 | 63 | 64 | Always 65 | 66 | 67 | Always 68 | 69 | 70 | Always 71 | 72 | 73 | Always 74 | 75 | 76 | LocalizeGenerator 77 | Str.cs 78 | Designer 79 | Always 80 | 81 | 82 | Always 83 | 84 | 85 | Always 86 | 87 | 88 | Always 89 | 90 | 91 | True 92 | True 93 | Str.resx 94 | 95 | 96 | True 97 | True 98 | Settings.settings 99 | 100 | 101 | 102 | 103 | SettingsSingleFileGenerator 104 | Settings.Designer.cs 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | $(LOCALAPPDATA)/Colossal Order/Cities_Skylines/Addons/Mods/$(SolutionName)/ 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | $(LOCALAPPDATA)/Colossal Order/Cities_Skylines/Addons/Mods/$(ProjectName)/ 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | QStr.cs 133 | 134 | 135 | 136 | 137 | QStr.cs 138 | 139 | 140 | -------------------------------------------------------------------------------- /NetworkAnarchy/OptionsKeymapping.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework; 2 | using NetworkAnarchy.Lang; 3 | using QCommonLib; 4 | using QCommonLib.Lang; 5 | using System; 6 | using System.Collections.Generic; 7 | using UnifiedUI.Helpers; 8 | using UnityEngine; 9 | 10 | namespace NetworkAnarchy 11 | { 12 | public class OptionsKeymapping : QKeybinding 13 | { 14 | public static readonly SavedInputKey elevationUp = new SavedInputKey(Settings.buildElevationUp, Settings.gameSettingsFile, DefaultSettings.buildElevationUp, true); 15 | public static readonly SavedInputKey elevationDown = new SavedInputKey(Settings.buildElevationDown, Settings.gameSettingsFile, DefaultSettings.buildElevationDown, true); 16 | public static readonly SavedInputKey elevationReset = new SavedInputKey("elevationReset", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.Home, false, false, false), true); 17 | public static readonly SavedInputKey elevationStepUp = new SavedInputKey("elevationStepUp", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.UpArrow, true, false, false), true); 18 | public static readonly SavedInputKey elevationStepDown = new SavedInputKey("elevationStepDown", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.DownArrow, true, false, false), true); 19 | 20 | public static readonly SavedInputKey modesCycleRight = new SavedInputKey("modesCycleRight", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.RightArrow, true, false, false), true); 21 | public static readonly SavedInputKey modesCycleLeft = new SavedInputKey("modesCycleLeft", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.LeftArrow, true, false, false), true); 22 | public static readonly SavedInputKey toggleStraightSlope = new SavedInputKey("toggleStraightSlope", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.S, false, true, false), true); 23 | 24 | public static readonly SavedInputKey toggleAnarchy = new SavedInputKey("toggleAnarchy", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.A, true, false, false), true); 25 | public static readonly SavedInputKey toggleBending = new SavedInputKey("toggleBending", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.B, true, false, false), true); 26 | public static readonly SavedInputKey toggleSnapping = new SavedInputKey("toggleSnapping", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.S, true, false, false), true); 27 | public static readonly SavedInputKey toggleCollision = new SavedInputKey("toggleCollision", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.None, false, false, false), true); 28 | public static readonly SavedInputKey toggleGrid = new SavedInputKey("toggleGrid", NetworkAnarchy.settingsFileName, SavedInputKey.Encode(KeyCode.G, false, false, true), true); 29 | 30 | protected override void Awake() 31 | { 32 | Keybindings = new Dictionary 33 | { 34 | { Str.key_elevationUp, elevationUp }, 35 | { Str.key_elevationDown, elevationDown }, 36 | { Str.key_elevationReset, elevationReset }, 37 | { Str.key_elevationStepUp, elevationStepUp }, 38 | { Str.key_elevationStepDown, elevationStepDown }, 39 | 40 | { Str.key_cycleModesRight, modesCycleRight }, 41 | { Str.key_cycleModesLeft, modesCycleLeft }, 42 | { Str.key_toggleStraightSlopes, toggleStraightSlope }, 43 | 44 | { Str.key_toggleAnarchy, toggleAnarchy }, 45 | { Str.key_toggleBending, toggleBending }, 46 | { Str.key_toggleSnapping, toggleSnapping }, 47 | { Str.ui_toggleCollision, toggleCollision }, 48 | { Str.key_toggleGrid, toggleGrid } 49 | }; 50 | 51 | AddKeymappingsList(); 52 | } 53 | 54 | public static void RegisterUUIHotkeys() 55 | { 56 | bool GetIsActive() => NetworkAnarchy.instance.IsActive; 57 | 58 | Dictionary> intoolKeys = new Dictionary>(); 59 | // use UUI to resolve hotkey collisions 60 | intoolKeys.Add(OptionsKeymapping.elevationUp, GetIsActive); 61 | intoolKeys.Add(OptionsKeymapping.elevationDown, GetIsActive); 62 | intoolKeys.Add(OptionsKeymapping.elevationReset, GetIsActive); 63 | intoolKeys.Add(OptionsKeymapping.elevationStepUp, GetIsActive); 64 | intoolKeys.Add(OptionsKeymapping.elevationStepDown, GetIsActive); 65 | intoolKeys.Add(OptionsKeymapping.modesCycleRight, GetIsActive); 66 | intoolKeys.Add(OptionsKeymapping.modesCycleLeft, GetIsActive); 67 | intoolKeys.Add(OptionsKeymapping.toggleStraightSlope, GetIsActive); 68 | intoolKeys.Add(OptionsKeymapping.toggleBending, GetIsActive); 69 | intoolKeys.Add(OptionsKeymapping.toggleSnapping, GetIsActive); 70 | intoolKeys.Add(OptionsKeymapping.toggleGrid, GetIsActive); 71 | 72 | UUIHelpers.RegisterHotkeys( 73 | onToggle: () => { }, 74 | activationKey: OptionsKeymapping.toggleAnarchy, 75 | activeKeys: intoolKeys); 76 | UUIHelpers.RegisterHotkeys( 77 | onToggle: () => { }, 78 | activationKey: OptionsKeymapping.toggleCollision); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/BuildingTool.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework.Math; 2 | using HarmonyLib; 3 | using System.Diagnostics; 4 | using System.Reflection; 5 | 6 | namespace NetworkAnarchy.Patches 7 | { 8 | [HarmonyPatch(typeof(BuildingTool), "CheckSpace")] 9 | public class BT_CheckSpace 10 | { 11 | public static bool Prefix(ref ToolBase.ToolErrors __result) 12 | { 13 | if (NetworkAnarchy.Anarchy) 14 | { 15 | __result = ToolBase.ToolErrors.None; 16 | return false; 17 | } 18 | 19 | return true; 20 | } 21 | } 22 | 23 | [HarmonyPatch(typeof(BuildingTool), "CheckCollidingBuildings")] 24 | public class BT_CheckCollidingBuildings 25 | { 26 | public static bool Prefix(ref bool __result) 27 | { 28 | if (NetworkAnarchy.Anarchy) 29 | { 30 | __result = false; 31 | return false; 32 | } 33 | 34 | return true; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/Collision.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework.Math; 2 | using HarmonyLib; 3 | using System.Diagnostics; 4 | using System.Reflection; 5 | 6 | namespace NetworkAnarchy.Patches 7 | { 8 | // OverlapQuad(Quad2 quad, float minY, float maxY, ItemClass.CollisionType collisionType, ItemClass.Layer layers, ushort ignoreBuilding, ushort ignoreNode1, ushort ignoreNode2, ulong[] buildingMask) 9 | [HarmonyPatch(typeof(BuildingManager))] 10 | [HarmonyPatch("OverlapQuad")] 11 | [HarmonyPatch(new[] { typeof(Quad2), typeof(float), typeof(float), typeof(ItemClass.CollisionType), typeof(ItemClass.Layer), typeof(ushort), typeof(ushort), typeof(ushort), typeof(ulong[]) })] 12 | public class BM_OverlapQuad 13 | { 14 | public static bool Prefix(ref bool __result) 15 | { 16 | if (!NetworkAnarchy.Collision) 17 | { 18 | __result = false; 19 | return false; 20 | } 21 | 22 | return true; 23 | } 24 | } 25 | 26 | [HarmonyPatch(typeof(NetManager))] 27 | [HarmonyPatch("OverlapQuad")] 28 | [HarmonyPatch(new[] { typeof(Quad2), typeof(float), typeof(float), typeof(ItemClass.CollisionType), typeof(ItemClass.Layer), typeof(ItemClass.Layer), typeof(ushort), typeof(ushort), typeof(ushort), typeof(ulong[]) })] 29 | public class NM_OverlapQuad 30 | { 31 | public static bool Prefix(ref bool __result) 32 | { 33 | if (!NetworkAnarchy.Collision) 34 | { 35 | __result = false; 36 | return false; 37 | } 38 | 39 | return true; 40 | } 41 | } 42 | 43 | [HarmonyPatch(typeof(NetNode))] 44 | [HarmonyPatch("TestNodeBuilding")] 45 | public class NN_TestNodeBuilding 46 | { 47 | public static bool Prefix(ref bool __result) 48 | { 49 | if (!NetworkAnarchy.Collision) 50 | { 51 | __result = true; 52 | return false; 53 | } 54 | 55 | return true; 56 | } 57 | } 58 | 59 | // void CalculateImplementation1(ushort blockID, ushort segmentID, ref NetSegment data, ref ulong valid, float minX, float minZ, float maxX, float maxZ) 60 | [HarmonyPatch(typeof(ZoneBlock))] 61 | [HarmonyPatch("CalculateImplementation1")] 62 | [HarmonyPatch( 63 | new[] { typeof(ushort), typeof(ushort), typeof(NetSegment), typeof(ulong), typeof(float), typeof(float), typeof(float), typeof(float) }, 64 | new[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Ref, ArgumentType.Ref, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal })] 65 | public class ZB_CalculateImplementation1 66 | { 67 | public static bool Prefix(ref NetSegment data) 68 | { 69 | if (NetworkAnarchy.Collision || data.Info.m_flattenTerrain) 70 | { 71 | return true; 72 | } 73 | 74 | return false; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/EarlyPatches.cs: -------------------------------------------------------------------------------- 1 | using QCommonLib; 2 | using System; 3 | using System.Reflection; 4 | 5 | namespace NetworkAnarchy.Patches 6 | { 7 | public static class EarlyPatches 8 | { 9 | public static void Deploy(QPatcher Patcher) 10 | { 11 | Type self = typeof(EarlyPatches); 12 | try 13 | { 14 | Patcher.Postfix(typeof(NetInfo).GetMethod("InitializePrefab", BindingFlags.Public | BindingFlags.Instance), self.GetMethod("NetInfo_InitializePrefab_Postfix")); 15 | Patcher.Postfix(typeof(TransportInfo).GetMethod("InitializePrefab", BindingFlags.Public | BindingFlags.Instance), self.GetMethod("TransportInfo_InitializePrefab_Postfix")); 16 | Patcher.Prefix(typeof(PublicTransportPanel).GetMethod("IsRoadEligibleToPublicTransport", BindingFlags.NonPublic | BindingFlags.Instance), self.GetMethod("PublicTransportPanel_IsRoadEligibleToPublicTransport_Prefix")); 17 | Log.Info($"NetworkAnarchy: Deployed early patches", "[NA13]"); 18 | } 19 | catch (Exception e) 20 | { 21 | Log.Warning($"NetworkAnarchy: Failed to deploy early patches\n{e}", "[NA14]"); 22 | } 23 | } 24 | 25 | public static void Revert(QPatcher Patcher) 26 | { 27 | Type self = typeof(EarlyPatches); 28 | try 29 | { 30 | Patcher.Unpatch(typeof(PublicTransportPanel).GetMethod("IsRoadEligibleToPublicTransport", BindingFlags.NonPublic | BindingFlags.Instance), self.GetMethod("PublicTransportPanel_IsRoadEligibleToPublicTransport_Prefix")); 31 | Patcher.Unpatch(typeof(TransportInfo).GetMethod("InitializePrefab", BindingFlags.Public | BindingFlags.Instance), self.GetMethod("TransportInfo_InitializePrefab_Postfix")); 32 | Patcher.Unpatch(typeof(NetInfo).GetMethod("InitializePrefab", BindingFlags.Public | BindingFlags.Instance), self.GetMethod("NetInfo_InitializePrefab_Postfix")); 33 | Log.Info($"NetworkAnarchy: Reverted early patches", "[NA15]"); 34 | } 35 | catch (Exception e) 36 | { 37 | Log.Warning($"NetworkAnarchy: Failed to revert early patches\n{e}", "[NA16]"); 38 | } 39 | } 40 | 41 | /// 42 | /// Allow any road to make an outside connection, and make ship and airplane paths available in-game 43 | /// 44 | public static void NetInfo_InitializePrefab_Postfix(ref NetInfo __instance) 45 | { 46 | AnyRoadOutsideConnection.Apply(__instance); 47 | 48 | if (QCommon.Scene != QCommon.SceneTypes.Game) return; 49 | 50 | if (__instance.name == "Ship Path" || __instance.name == "Airplane Path") 51 | { 52 | __instance.m_availableIn |= ItemClass.Availability.Game; 53 | } 54 | } 55 | 56 | /// 57 | /// Make Airplane paths visible 58 | /// 59 | public static void TransportInfo_InitializePrefab_Postfix(ref TransportInfo __instance) 60 | { 61 | if (QCommon.Scene != QCommon.SceneTypes.Game) return; 62 | 63 | if (__instance.name == "Airplane") 64 | { 65 | __instance.m_pathVisibility |= ItemClass.Availability.Game; 66 | } 67 | } 68 | 69 | /// 70 | /// Enable the ship and airplane path buttons in-game 71 | /// 72 | public static bool PublicTransportPanel_IsRoadEligibleToPublicTransport_Prefix(ref PublicTransportPanel __instance, ref bool __result, NetInfo info) 73 | { 74 | if (__instance.category == "PublicTransportShip") 75 | { 76 | __result = (info.m_vehicleTypes & (VehicleInfo.VehicleType.Ferry | VehicleInfo.VehicleType.Ship)) != VehicleInfo.VehicleType.None; 77 | return false; 78 | } 79 | if (__instance.category == "PublicTransportPlane") 80 | { 81 | __result = (info.m_vehicleTypes & (VehicleInfo.VehicleType.Helicopter | VehicleInfo.VehicleType.Blimp | VehicleInfo.VehicleType.Plane)) != VehicleInfo.VehicleType.None; 82 | return false; 83 | } 84 | return true; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/GetInfo.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using QCommonLib; 3 | 4 | namespace NetworkAnarchy.Patches 5 | { 6 | // NetInfo GetInfo(float minElevation, float maxElevation, float length, bool incoming, bool outgoing, bool curved, bool enableDouble, ref ToolBase.ToolErrors errors) 7 | [HarmonyPatch(typeof(RoadAI), "GetInfo")] 8 | class RAI_GetInfo 9 | { 10 | public static bool Prefix(ref RoadAI __instance, ref NetInfo __result, ref ToolBase.ToolErrors errors) 11 | { 12 | return !GetInfoUtils.GetEarlyResult(ref __result, __instance.m_info, ref errors); 13 | } 14 | 15 | public static void Postfix(ref ToolBase.ToolErrors errors) 16 | { 17 | GetInfoUtils.GetLateResult(ref errors); 18 | } 19 | } 20 | 21 | [HarmonyPatch(typeof(PedestrianPathAI), "GetInfo")] 22 | class PPAI_GetInfo 23 | { 24 | public static bool Prefix(ref PedestrianPathAI __instance, ref NetInfo __result, ref ToolBase.ToolErrors errors) 25 | { 26 | return !GetInfoUtils.GetEarlyResult(ref __result, __instance.m_info, ref errors); 27 | } 28 | 29 | public static void Postfix(ref ToolBase.ToolErrors errors) 30 | { 31 | GetInfoUtils.GetLateResult(ref errors); 32 | } 33 | } 34 | 35 | [HarmonyPatch(typeof(PedestrianWayAI), "GetInfo")] 36 | class PWAI_GetInfo 37 | { 38 | public static bool Prefix(ref PedestrianWayAI __instance, ref NetInfo __result, ref ToolBase.ToolErrors errors) 39 | { 40 | return !GetInfoUtils.GetEarlyResult(ref __result, __instance.m_info, ref errors); 41 | } 42 | 43 | public static void Postfix(ref ToolBase.ToolErrors errors) 44 | { 45 | GetInfoUtils.GetLateResult(ref errors); 46 | } 47 | } 48 | 49 | [HarmonyPatch(typeof(TrainTrackAI), "GetInfo")] 50 | class TTAI_GetInfo 51 | { 52 | public static bool Prefix(ref TrainTrackAI __instance, ref NetInfo __result, ref ToolBase.ToolErrors errors) 53 | { 54 | return !GetInfoUtils.GetEarlyResult(ref __result, __instance.m_info, ref errors); 55 | } 56 | 57 | public static void Postfix(ref ToolBase.ToolErrors errors) 58 | { 59 | GetInfoUtils.GetLateResult(ref errors); 60 | } 61 | } 62 | 63 | [HarmonyPatch(typeof(MetroTrackAI), "GetInfo")] 64 | class MTAI_GetInfo 65 | { 66 | public static bool Prefix(ref MetroTrackAI __instance, ref NetInfo __result, ref ToolBase.ToolErrors errors) 67 | { 68 | return !GetInfoUtils.GetEarlyResult(ref __result, __instance.m_info, ref errors); 69 | } 70 | 71 | public static void Postfix(ref ToolBase.ToolErrors errors) 72 | { 73 | GetInfoUtils.GetLateResult(ref errors); 74 | } 75 | } 76 | 77 | 78 | 79 | internal static class GetInfoUtils 80 | { 81 | internal static bool GetEarlyResult(ref NetInfo output, NetInfo input, ref ToolBase.ToolErrors errors) 82 | { 83 | output = input; 84 | if (NetworkAnarchy.instance == null) { return false; } 85 | // If in Intersection editor and NA isn't active (i.e. just loaded), force the current prefab 86 | if (QCommon.Scene == QCommon.SceneTypes.AssetEditor && !NetworkAnarchy.instance.IsActive && ToolManager.instance.m_properties.m_editPrefabInfo?.GetAI() is IntersectionAI) { return true; } 87 | if (!NetworkAnarchy.instance.IsActive) { return false; } 88 | if (NetworkAnarchy.instance.IsBuildingGroundIntersection()) { return true; } 89 | NetAIWrapper wrapper = new NetAIWrapper(input.m_netAI); 90 | 91 | if (NetworkAnarchy.Anarchy && (errors & ToolBase.ToolErrors.HeightTooHigh) == ToolBase.ToolErrors.HeightTooHigh) 92 | { 93 | errors ^= ToolBase.ToolErrors.HeightTooHigh; 94 | } 95 | 96 | switch (NetworkAnarchy.instance.mode) 97 | { 98 | case Modes.Normal: 99 | return false; 100 | 101 | case Modes.Ground: 102 | output = wrapper.Info; 103 | return true; 104 | 105 | case Modes.Elevated: 106 | output = wrapper.Elevated ?? wrapper.Info; 107 | return true; 108 | 109 | case Modes.Bridge: 110 | output = wrapper.Bridge ?? wrapper.Info; 111 | return true; 112 | 113 | case Modes.Tunnel: 114 | output = wrapper.Tunnel ?? wrapper.Info; 115 | return true; 116 | } 117 | Log.Debug($"GetInfo result: {input.name} -> {output.name}", "[NA68]"); 118 | 119 | return false; 120 | } 121 | 122 | internal static void GetLateResult(ref ToolBase.ToolErrors errors) 123 | { 124 | if (NetworkAnarchy.Anarchy && (errors & ToolBase.ToolErrors.HeightTooHigh) == ToolBase.ToolErrors.HeightTooHigh) 125 | { 126 | errors ^= ToolBase.ToolErrors.HeightTooHigh; 127 | } 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/LeftHandTraffic.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework; 2 | using HarmonyLib; 3 | using UnityEngine; 4 | 5 | namespace NetworkAnarchy.Patches 6 | { 7 | [HarmonyPatch(typeof(NetTool))] 8 | [HarmonyPatch("RenderSegment")] 9 | class PatchRenderSegment 10 | { 11 | static void Prefix(NetInfo info, NetSegment.Flags flags, ref Vector3 startPosition, ref Vector3 endPosition, ref Vector3 startDirection, ref Vector3 endDirection) 12 | { 13 | if (!isLHT()) 14 | { 15 | return; 16 | } 17 | 18 | // Tunnel entrances shouldn't be inverted 19 | if (info.m_netAI is RoadTunnelAI || info.m_netAI is TrainTrackTunnelAI || info.m_netAI is PedestrianTunnelAI) 20 | { 21 | return; 22 | } 23 | 24 | // Don't flip Sully's Water Park station networks 25 | if (info.m_netAI is TrainTrackBridgeAI && info.name.Contains("Water Slide FT - ST")) 26 | { 27 | return; 28 | } 29 | 30 | Vector3 buffer; 31 | 32 | buffer = endPosition; 33 | endPosition = startPosition; 34 | startPosition = buffer; 35 | 36 | buffer = endDirection; 37 | endDirection = -startDirection; 38 | startDirection = -buffer; 39 | } 40 | 41 | static bool isLHT() 42 | { 43 | return Singleton.instance.m_metaData.m_invertTraffic == SimulationMetaData.MetaBool.True; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/Misc.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework; 2 | using HarmonyLib; 3 | using QCommonLib; 4 | using System; 5 | using System.Diagnostics; 6 | using System.Reflection; 7 | using UnityEngine; 8 | 9 | namespace NetworkAnarchy.Patches 10 | { 11 | class Utils 12 | { 13 | /// 14 | /// Remove building limiting errors for networks 15 | /// 16 | /// The errors generated by the vanilla game 17 | /// The pruned down errors 18 | internal static ToolBase.ToolErrors YeetLimits(ToolBase.ToolErrors errors) 19 | { 20 | if (NetworkAnarchy.Anarchy) 21 | { 22 | errors &= ~ToolBase.ToolErrors.CanalTooClose; 23 | errors &= ~ToolBase.ToolErrors.CannotBuildOnWater; 24 | errors &= ~ToolBase.ToolErrors.HeightTooHigh; 25 | errors &= ~ToolBase.ToolErrors.ShoreNotFound; 26 | errors &= ~ToolBase.ToolErrors.SlopeTooSteep; 27 | errors &= ~ToolBase.ToolErrors.WaterNotFound; 28 | } 29 | return errors; 30 | } 31 | } 32 | 33 | /// 34 | /// Make ship and airplane paths bulldozeable 35 | /// 36 | [HarmonyPatch(typeof(DefaultTool), "GetService")] 37 | public static class DT_GetService 38 | { 39 | public static void Postfix(ref ToolBase.RaycastService __result) 40 | { 41 | if (QCommon.Scene != QCommon.SceneTypes.Game) return; 42 | 43 | if (Singleton.instance.CurrentMode == InfoManager.InfoMode.Transport) 44 | { 45 | __result.m_itemLayers |= ItemClass.Layer.AirplanePaths | ItemClass.Layer.ShipPaths; 46 | } 47 | } 48 | } 49 | 50 | /// 51 | /// Allow ship and airplane paths to be built outside the purchased tiles 52 | /// Patch deployed by Mods.CrossTheLine 53 | /// 54 | public static class GAM_QuadOutOfArea 55 | { 56 | public static bool Prefix(ref bool __result) 57 | { 58 | try 59 | { 60 | if (!(Singleton.instance.CurrentTool is NetTool)) return true; 61 | NetTool netTool = (NetTool)Singleton.instance.CurrentTool; 62 | if (netTool.Prefab == null) return true; 63 | NetInfo prefab = netTool.Prefab; 64 | 65 | if (prefab.name == "Ship Path" || prefab.name == "Airplane Path") 66 | { 67 | __result = false; 68 | return false; 69 | } 70 | } 71 | catch (NullReferenceException e) 72 | { 73 | UnityEngine.Debug.Log($"Failed to enable placing transport paths outside purchased tiles\n{e}"); 74 | } 75 | return true; 76 | } 77 | } 78 | 79 | /// 80 | /// Override the InfoMode underground view 81 | /// 82 | [HarmonyPatch(typeof(InfoManager), "SetCurrentMode")] 83 | public static class IM_SetCurrentMode 84 | { 85 | public static void Prefix(ref InfoManager.InfoMode mode, InfoManager.SubInfoMode subMode) 86 | { 87 | if (NetworkAnarchy.instance == null) return; 88 | NetworkAnarchy inst = NetworkAnarchy.instance; 89 | if (!inst.IsActive || !inst.IsNetToolEnabled()) return; 90 | if (mode != InfoManager.InfoMode.Underground) return; 91 | if (inst.mode == Modes.Tunnel) return; 92 | 93 | if (inst.mode == Modes.Ground) 94 | { 95 | mode = InfoManager.InfoMode.None; 96 | } 97 | else if (inst.mode == Modes.Elevated || inst.mode == Modes.Bridge || inst.mode == Modes.Normal) 98 | { 99 | if (inst.elevation > -8) 100 | { 101 | mode = InfoManager.InfoMode.None; 102 | } 103 | } 104 | 105 | //Log.Debug($"IM_SetCurrentMode: \"{prefab.Prefab.name}\" {inst.elevation} ({inst.mode},{prefab.Mode})"); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/NetTool.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Reflection.Emit; 6 | using UnityEngine; 7 | 8 | namespace NetworkAnarchy.Patches 9 | { 10 | [HarmonyPatch(typeof(NetTool), "CheckStartAndEnd")] 11 | class NT_CheckStartAndEnd 12 | { 13 | public static bool Prefix(ref bool __result) 14 | { 15 | if (NetworkAnarchy.Anarchy) 16 | { 17 | __result = true; 18 | return false; 19 | } 20 | 21 | return true; 22 | } 23 | } 24 | 25 | [HarmonyPatch(typeof(NetTool), "CanAddSegment")] 26 | class NT_CanAddSegment 27 | { 28 | public static bool Prefix(ref bool __result) 29 | { 30 | if (NetworkAnarchy.Anarchy) 31 | { 32 | __result = true; 33 | return false; 34 | } 35 | 36 | return true; 37 | } 38 | } 39 | 40 | //bool CanAddNode(ushort segmentID, Vector3 position, Vector3 direction, bool checkDirection, ulong[] collidingSegmentBuffer) 41 | [HarmonyPatch(typeof(NetTool), "CanAddNode")] 42 | [HarmonyPatch(new[] { typeof(ushort), typeof(Vector3), typeof(Vector3), typeof(bool), typeof(ulong[]) })] 43 | class NT_CanAddNode 44 | { 45 | public static bool Prefix(ref bool __result) 46 | { 47 | if (NetworkAnarchy.Anarchy) 48 | { 49 | __result = true; 50 | return false; 51 | } 52 | 53 | return true; 54 | } 55 | } 56 | 57 | [HarmonyPatch(typeof(NetTool), "CheckCollidingSegments")] 58 | class NT_CheckCollidingSegments 59 | { 60 | public static bool Prefix(ref bool __result) 61 | { 62 | if (NetworkAnarchy.Anarchy) 63 | { 64 | __result = false; 65 | return false; 66 | } 67 | 68 | return true; 69 | } 70 | } 71 | 72 | // ToolBase.ToolErrors CanCreateSegment(NetInfo segmentInfo, ushort startNode, ushort startSegment, ushort endNode, ushort endSegment, 73 | // ushort upgrading, Vector3 startPos, Vector3 endPos, Vector3 startDir, Vector3 endDir, ulong[] collidingSegmentBuffer, bool testEnds) 74 | [HarmonyPatch(typeof(NetTool), "CanCreateSegment")] 75 | [HarmonyPatch(new[] { typeof(NetInfo), typeof(ushort), typeof(ushort), typeof(ushort), typeof(ushort), typeof(ushort), typeof(Vector3), typeof(Vector3), typeof(Vector3), typeof(Vector3), typeof(ulong[]), typeof(bool) })] 76 | class NT_CanCreateSegment 77 | { 78 | public static bool Prefix(ref ToolBase.ToolErrors __result) 79 | { 80 | if (NetworkAnarchy.Anarchy) 81 | { 82 | __result = ToolBase.ToolErrors.None; 83 | return false; 84 | } 85 | 86 | return true; 87 | } 88 | } 89 | 90 | [HarmonyPatch(typeof(NetTool), "TestNodeBuilding")] 91 | class NT_TestNodeBuilding 92 | { 93 | public static bool Prefix(ref ToolBase.ToolErrors __result) 94 | { 95 | if (NetworkAnarchy.Anarchy) 96 | { 97 | __result = ToolBase.ToolErrors.None; 98 | return false; 99 | } 100 | 101 | return true; 102 | } 103 | } 104 | 105 | [HarmonyPatch(typeof(NetTool), "CheckNodeHeights")] 106 | class NT_CheckNodeHeights 107 | { 108 | public static void Postfix(ref ToolBase.ToolErrors __result) 109 | { 110 | if (NetworkAnarchy.Anarchy) 111 | { 112 | __result &= ~ToolBase.ToolErrors.SlopeTooSteep; 113 | } 114 | } 115 | } 116 | 117 | ////ToolBase.ToolErrors CreateNode(NetInfo info, NetTool.ControlPoint startPoint, NetTool.ControlPoint middlePoint, NetTool.ControlPoint endPoint, 118 | //// FastList nodeBuffer, int maxSegments, bool test, bool testEnds, bool visualize, bool autoFix, bool needMoney, bool invert, 119 | //// bool switchDir, ushort relocateBuildingID, out ushort firstNode, out ushort lastNode, out ushort segment, out int cost, out int productionRate) 120 | [HarmonyPatch(typeof(NetTool), "CreateNode")] 121 | [HarmonyPatch(new[] { 122 | typeof(NetInfo), typeof(NetTool.ControlPoint), typeof(NetTool.ControlPoint), typeof(NetTool.ControlPoint), typeof(FastList), typeof(int), 123 | typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), 124 | typeof(ushort), typeof(ushort), typeof(ushort), typeof(ushort), typeof(int), typeof(int) }, 125 | new[] { 126 | ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, 127 | ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, 128 | ArgumentType.Normal, ArgumentType.Out, ArgumentType.Out, ArgumentType.Out, ArgumentType.Out, ArgumentType.Out } 129 | )] 130 | class NT_CreateNode 131 | { 132 | public static void Postfix(ref ToolBase.ToolErrors __result, NetInfo info, ref ushort firstNode, ref ushort lastNode, bool test, bool testEnds, bool visualize, bool autoFix) 133 | { 134 | if (NetworkAnarchy.Anarchy) 135 | { 136 | __result &= ~ToolBase.ToolErrors.InvalidShape; 137 | } 138 | } 139 | 140 | public static IEnumerable Transpiler(IEnumerable instructions) 141 | { 142 | var codes = new List(instructions); 143 | 144 | //DumpCode(codes); 145 | int i; 146 | for (i = 500; i < 700; i++) 147 | { 148 | if (codes[i - 3].opcode == OpCodes.Stind_I2 && codes[i - 2].opcode == OpCodes.Ldarg_S && codes[i - 1].opcode == OpCodes.Ldloc_S) 149 | { 150 | break; 151 | } 152 | } 153 | if (i == 700) 154 | { 155 | throw new Exception("Failed to find ILCode"); 156 | } 157 | codes[i] = new CodeInstruction(OpCodes.Call, typeof(NT_CreateNode).GetMethod("GetMaxLength")); 158 | //DumpCode(codes, "ILCodeAfter.txt"); 159 | 160 | return codes; 161 | } 162 | 163 | public static float GetMaxLength() 164 | { 165 | return NetworkAnarchy.instance.MaxSegmentLength + 2; 166 | } 167 | 168 | private static void DumpCode(IEnumerable instructions, string fileName = "ILCode.txt") 169 | { 170 | string docPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 171 | 172 | using (StreamWriter outputFile = new StreamWriter(Path.Combine(docPath, "Colossal Order\\Cities_Skylines\\" + fileName))) 173 | { 174 | foreach (CodeInstruction ci in instructions) 175 | { 176 | outputFile.WriteLine($"{ci.opcode} - {ci.operand}"); 177 | } 178 | } 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/Networks.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | 3 | namespace NetworkAnarchy.Patches 4 | { 5 | // For straight slope 6 | [HarmonyPatch(typeof(NetAI), "LinearMiddleHeight")] 7 | class NAI_LinearMiddleHeight 8 | { 9 | public static bool Prefix(ref bool __result, NetAI __instance) 10 | { 11 | if (NetworkAnarchy.instance.StraightSlope && !(__instance is WaterPipeAI || __instance is FlightPathAI)) 12 | { 13 | __result = true; 14 | return false; 15 | } 16 | 17 | return true; 18 | } 19 | } 20 | 21 | [HarmonyPatch(typeof(NetAI), "BuildOnWater")] 22 | class NAI_BuildOnWater 23 | { 24 | public static bool Prefix(ref bool __result) 25 | { 26 | if (NetworkAnarchy.Anarchy) 27 | { 28 | __result = true; 29 | return false; 30 | } 31 | 32 | return true; 33 | } 34 | } 35 | 36 | [HarmonyPatch(typeof(NetAI), "GetMinSegmentLength")] 37 | class NAI_GetMinSegmentLength 38 | { 39 | public static void Postfix(ref float __result) 40 | { 41 | if (NetworkAnarchy.Anarchy) 42 | { 43 | __result /= 42; 44 | } 45 | } 46 | } 47 | 48 | [HarmonyPatch(typeof(NetInfo), "GetMinNodeDistance")] 49 | class NI_GetMinNodeDistance 50 | { 51 | public static void Postfix(ref float __result) 52 | { 53 | if (!NetworkAnarchy.NodeSnapping) 54 | { 55 | __result = 3f; 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/RoadAI.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using QCommonLib; 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | namespace NetworkAnarchy.Patches 7 | { 8 | #region RoadAI 9 | // void GetElevationLimits(out int min, out int max) 10 | [HarmonyPatch(typeof(RoadAI), "GetElevationLimits")] 11 | class RAI_GetElevationLimits 12 | { 13 | public static bool Prefix(out int min, out int max) 14 | { 15 | min = -3; 16 | max = 5; 17 | if (NetworkAnarchy.Anarchy) 18 | { 19 | min = -999; // Base-game assumes anything beyond +/- 1000 is unset 20 | max = 999; 21 | 22 | return false; 23 | } 24 | 25 | return true; 26 | } 27 | 28 | public static void Postfix(ref int min) 29 | { 30 | // Override minimum height for tunnels in map editor 31 | if (QCommon.Scene == QCommon.SceneTypes.MapEditor) 32 | { 33 | if (NetworkAnarchy.Anarchy) 34 | { 35 | min = -999; 36 | } 37 | else 38 | { 39 | min = 0; 40 | } 41 | } 42 | } 43 | } 44 | 45 | // ToolBase.ToolErrors CheckBuildPosition(bool test, bool visualize, bool overlay, bool autofix, ref NetTool.ControlPoint startPoint, ref NetTool.ControlPoint middlePoint, ref NetTool.ControlPoint endPoint, out BuildingInfo ownerBuilding, out Vector3 ownerPosition, out Vector3 ownerDirection, out int productionRate) 46 | [HarmonyPatch(typeof(RoadAI), "CheckBuildPosition")] 47 | class RAI_CheckBuildPosition 48 | { 49 | public static bool Prefix(ref ToolBase.ToolErrors __result) 50 | { 51 | if (NetworkAnarchy.Anarchy) 52 | { 53 | __result = ToolBase.ToolErrors.None; 54 | 55 | return false; 56 | } 57 | 58 | return true; 59 | } 60 | } 61 | #endregion 62 | 63 | #region PedestrianPathAI 64 | [HarmonyPatch(typeof(PedestrianPathAI), "GetElevationLimits")] 65 | class PPAI_GetElevationLimits 66 | { 67 | public static bool Prefix(out int min, out int max) 68 | { 69 | min = -3; 70 | max = 5; 71 | if (NetworkAnarchy.Anarchy) 72 | { 73 | min = -999; // Base-game assumes anything beyond +/- 1000 is unset 74 | max = 999; 75 | 76 | return false; 77 | } 78 | 79 | return true; 80 | } 81 | 82 | public static void Postfix(ref int min) 83 | { 84 | // Override minimum height for tunnels in map editor 85 | if (QCommon.Scene == QCommon.SceneTypes.MapEditor) 86 | { 87 | if (NetworkAnarchy.Anarchy) 88 | { 89 | min = -999; 90 | } 91 | else 92 | { 93 | min = 0; 94 | } 95 | } 96 | } 97 | } 98 | 99 | [HarmonyPatch(typeof(PedestrianPathAI), "CheckBuildPosition")] 100 | class PPAI_CheckBuildPosition 101 | { 102 | public static bool Prefix(ref ToolBase.ToolErrors __result) 103 | { 104 | if (NetworkAnarchy.Anarchy) 105 | { 106 | __result = ToolBase.ToolErrors.None; 107 | 108 | return false; 109 | } 110 | 111 | return true; 112 | } 113 | } 114 | #endregion 115 | 116 | #region PedestrianWayAI 117 | [HarmonyPatch(typeof(PedestrianWayAI), "GetElevationLimits")] 118 | class PWAI_GetElevationLimits 119 | { 120 | public static bool Prefix(out int min, out int max) 121 | { 122 | min = -3; 123 | max = 5; 124 | if (NetworkAnarchy.Anarchy) 125 | { 126 | min = -999; // Base-game assumes anything beyond +/- 1000 is unset 127 | max = 999; 128 | 129 | return false; 130 | } 131 | 132 | return true; 133 | } 134 | 135 | public static void Postfix(ref int min) 136 | { 137 | // Override minimum height for tunnels in map editor 138 | if (QCommon.Scene == QCommon.SceneTypes.MapEditor) 139 | { 140 | if (NetworkAnarchy.Anarchy) 141 | { 142 | min = -999; 143 | } 144 | else 145 | { 146 | min = 0; 147 | } 148 | } 149 | } 150 | } 151 | 152 | [HarmonyPatch(typeof(PedestrianWayAI), "CheckBuildPosition")] 153 | class PWAI_CheckBuildPosition 154 | { 155 | public static bool Prefix(ref ToolBase.ToolErrors __result) 156 | { 157 | if (NetworkAnarchy.Anarchy) 158 | { 159 | __result = ToolBase.ToolErrors.None; 160 | 161 | return false; 162 | } 163 | 164 | return true; 165 | } 166 | } 167 | #endregion 168 | 169 | #region TrainTrackAI 170 | [HarmonyPatch(typeof(TrainTrackAI), "GetElevationLimits")] 171 | class TTAI_GetElevationLimits 172 | { 173 | public static bool Prefix(out int min, out int max) 174 | { 175 | min = -3; 176 | max = 5; 177 | if (NetworkAnarchy.Anarchy) 178 | { 179 | min = -999; // Base-game assumes anything beyond +/- 1000 is unset 180 | max = 999; 181 | 182 | return false; 183 | } 184 | 185 | return true; 186 | } 187 | 188 | public static void Postfix(ref int min) 189 | { 190 | // Override minimum height for tunnels in map editor 191 | if (QCommon.Scene == QCommon.SceneTypes.MapEditor) 192 | { 193 | if (NetworkAnarchy.Anarchy) 194 | { 195 | min = -999; 196 | } 197 | else 198 | { 199 | min = 0; 200 | } 201 | } 202 | } 203 | } 204 | 205 | [HarmonyPatch(typeof(TrainTrackAI), "CheckBuildPosition")] 206 | class TTAI_CheckBuildPosition 207 | { 208 | public static bool Prefix(ref ToolBase.ToolErrors __result) 209 | { 210 | if (NetworkAnarchy.Anarchy) 211 | { 212 | __result = ToolBase.ToolErrors.None; 213 | 214 | return false; 215 | } 216 | 217 | return true; 218 | } 219 | } 220 | #endregion 221 | 222 | #region DecorationWallAI 223 | [HarmonyPatch(typeof(DecorationWallAI), "CheckBuildPosition")] 224 | class DWAI_CheckBuildPosition 225 | { 226 | public static bool Prefix(ref ToolBase.ToolErrors __result) 227 | { 228 | if (NetworkAnarchy.Anarchy) 229 | { 230 | __result = ToolBase.ToolErrors.None; 231 | 232 | return false; 233 | } 234 | 235 | return true; 236 | } 237 | } 238 | 239 | [HarmonyPatch(typeof(DecorationWallAI), "GetInfo")] 240 | class DWAI_GetInfo 241 | { 242 | public static void Postfix(ref ToolBase.ToolErrors errors) 243 | { 244 | if (NetworkAnarchy.Anarchy && (errors & ToolBase.ToolErrors.HeightTooHigh) == ToolBase.ToolErrors.HeightTooHigh) 245 | { 246 | errors ^= ToolBase.ToolErrors.HeightTooHigh; 247 | } 248 | } 249 | } 250 | #endregion 251 | } 252 | -------------------------------------------------------------------------------- /NetworkAnarchy/Patches/Water.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | 3 | namespace NetworkAnarchy.Patches 4 | { 5 | [HarmonyPatch(typeof(ShipPathAI))] 6 | [HarmonyPatch("CheckBuildPosition")] 7 | class SPAI_CheckBuildPosition 8 | { 9 | public static void Postfix(ref ToolBase.ToolErrors __result) 10 | { 11 | __result = Utils.YeetLimits(__result); 12 | } 13 | } 14 | 15 | [HarmonyPatch(typeof(QuayAI))] 16 | [HarmonyPatch("GetInfo")] 17 | class QAI_GetInfo 18 | { 19 | public static void Postfix(ref ToolBase.ToolErrors errors) 20 | { 21 | errors = Utils.YeetLimits(errors); 22 | } 23 | } 24 | 25 | [HarmonyPatch(typeof(QuayAI))] 26 | [HarmonyPatch("CheckBuildPosition")] 27 | class QAI_CheckBuildPosition 28 | { 29 | public static void Postfix(ref ToolBase.ToolErrors __result) 30 | { 31 | __result = Utils.YeetLimits(__result); 32 | } 33 | } 34 | 35 | 36 | [HarmonyPatch(typeof(FloodWallAI))] 37 | [HarmonyPatch("CheckBuildPosition")] 38 | class FWAI_CheckBuildPosition 39 | { 40 | public static void Postfix(ref ToolBase.ToolErrors __result) 41 | { 42 | __result = Utils.YeetLimits(__result); 43 | } 44 | } 45 | 46 | [HarmonyPatch(typeof(FloodWallAI))] 47 | [HarmonyPatch("GetInfo")] 48 | class FWAI_GetInfo 49 | { 50 | public static void Postfix(ref ToolBase.ToolErrors errors) 51 | { 52 | errors = Utils.YeetLimits(errors); 53 | } 54 | } 55 | 56 | 57 | [HarmonyPatch(typeof(HarborAI))] 58 | [HarmonyPatch("CheckBuildPosition")] 59 | class HAI_CheckBuildPosition 60 | { 61 | public static void Postfix(ref ToolBase.ToolErrors __result) 62 | { 63 | __result = Utils.YeetLimits(__result); 64 | } 65 | } 66 | 67 | 68 | [HarmonyPatch(typeof(CargoHarborAI))] 69 | [HarmonyPatch("CheckBuildPosition")] 70 | class CHAI_CheckBuildPosition 71 | { 72 | public static void Postfix(ref ToolBase.ToolErrors __result) 73 | { 74 | __result = Utils.YeetLimits(__result); 75 | } 76 | } 77 | 78 | [HarmonyPatch(typeof(FishingHarborAI))] 79 | [HarmonyPatch("CheckBuildPosition")] 80 | class FHAI_CheckBuildPosition 81 | { 82 | public static void Postfix(ref ToolBase.ToolErrors __result) 83 | { 84 | __result = Utils.YeetLimits(__result); 85 | } 86 | } 87 | 88 | [HarmonyPatch(typeof(CanalAI))] 89 | [HarmonyPatch("GetInfo")] 90 | class CAI_GetInfo 91 | { 92 | public static void Postfix(ref ToolBase.ToolErrors errors) 93 | { 94 | errors = Utils.YeetLimits(errors); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /NetworkAnarchy/UI/ModOptions.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework.UI; 2 | using ICities; 3 | using NetworkAnarchy.Lang; 4 | using System; 5 | using UnityEngine; 6 | 7 | namespace NetworkAnarchy.UI 8 | { 9 | public class ModOptions 10 | { 11 | public ModOptions(UIHelperBase helper, string name) 12 | { 13 | try 14 | { 15 | var group = helper.AddGroup(name) as UIHelper; 16 | var panel = group.self as UIPanel; 17 | 18 | //checkBox = (UICheckBox)group.AddCheckbox(Str.options_alwaysVisible, UIToolOptionsButton.alwaysShowPanel.value, (b) => 19 | //{ 20 | // UIToolOptionsButton.alwaysShowPanel.value = b; 21 | // if (NetworkAnarchy.instance != null) 22 | // { 23 | // NetworkAnarchy.m_toolOptionButton.CreateOptionPanel(true); 24 | // } 25 | //}); 26 | 27 | //group.AddSpace(10); 28 | 29 | var checkBox = (UICheckBox)group.AddCheckbox(Str.options_showLabels, UIToolOptionsButton.showLabels.value, (b) => 30 | { 31 | UIToolOptionsButton.showLabels.value = b; 32 | if (NetworkAnarchy.instance != null) 33 | { 34 | NetworkAnarchy.m_toolOptionButton.CreateOptionPanel(true); 35 | } 36 | }); 37 | checkBox.tooltip = Str.options_showLabelsTooltip; 38 | 39 | checkBox = (UICheckBox)group.AddCheckbox(Str.options_showElevationStepSlider, UIToolOptionsButton.showElevationSlider.value, (b) => 40 | { 41 | UIToolOptionsButton.showElevationSlider.value = b; 42 | if (NetworkAnarchy.instance != null) 43 | { 44 | NetworkAnarchy.m_toolOptionButton.CreateOptionPanel(true); 45 | } 46 | }); 47 | checkBox.tooltip = Str.options_showElevationStepSliderTooltip; 48 | 49 | checkBox = (UICheckBox)group.AddCheckbox(Str.options_showMaxSegmentLengthSlider, UIToolOptionsButton.showMaxSegmentLengthSlider.value, (b) => 50 | { 51 | UIToolOptionsButton.showMaxSegmentLengthSlider.value = b; 52 | if (NetworkAnarchy.instance != null) 53 | { 54 | NetworkAnarchy.m_toolOptionButton.CreateOptionPanel(true); 55 | } 56 | }); 57 | checkBox.tooltip = Str.options_showMaxSegmentLengthSliderTooltip; 58 | 59 | group.AddSpace(10); 60 | 61 | checkBox = (UICheckBox)group.AddCheckbox(Str.options_reduceCatenaries, NetworkAnarchy.reduceCatenary.value, (b) => 62 | { 63 | NetworkAnarchy.reduceCatenary.value = b; 64 | if (NetworkAnarchy.instance != null) 65 | { 66 | UpdateCatenaries.Apply(); 67 | } 68 | }); 69 | checkBox.tooltip = Str.options_reduceCatenariesTooltip; 70 | 71 | group.AddSpace(10); 72 | 73 | checkBox = (UICheckBox)group.AddCheckbox(Str.options_tramMaxTurnAngle, NetworkAnarchy.changeMaxTurnAngle.value, (b) => 74 | { 75 | NetworkAnarchy.changeMaxTurnAngle.value = b; 76 | 77 | if (b) 78 | { 79 | NetPrefab.SetMaxTurnAngle(NetworkAnarchy.maxTurnAngle); 80 | } 81 | else 82 | { 83 | NetPrefab.ResetMaxTurnAngle(); 84 | } 85 | }); 86 | checkBox.tooltip = Str.options_tramMaxTurnAngleTooltip; 87 | 88 | group.AddTextfield(Str.options_maxTurnAngle + ": ", NetworkAnarchy.maxTurnAngle.ToString(), (f) => { }, 89 | (s) => 90 | { 91 | float.TryParse(s, out var f); 92 | 93 | NetworkAnarchy.maxTurnAngle.value = Mathf.Clamp(f, 0f, 180f); 94 | 95 | if (NetworkAnarchy.changeMaxTurnAngle.value) 96 | { 97 | NetPrefab.SetMaxTurnAngle(NetworkAnarchy.maxTurnAngle.value); 98 | } 99 | }); 100 | 101 | group.AddSpace(10); 102 | 103 | panel.gameObject.AddComponent(); 104 | 105 | group.AddSpace(10); 106 | 107 | group.AddButton(Str.options_resetToolWindowPosition, () => 108 | { 109 | UIToolOptionsButton.savedWindowX.Delete(); 110 | UIToolOptionsButton.savedWindowY.Delete(); 111 | 112 | if (UIToolOptionsButton.toolOptionsPanel) 113 | { 114 | UIToolOptionsButton.toolOptionsPanel.absolutePosition = new Vector3(-1000, -1000); 115 | } 116 | }); 117 | 118 | group.AddSpace(10); 119 | 120 | checkBox = (UICheckBox)group.AddCheckbox(Str.options_enableDebugLogging, NetworkAnarchy.showDebugMessages.value, (b) => 121 | { 122 | NetworkAnarchy.showDebugMessages.value = b; 123 | #if !DEBUG 124 | Log.IsDebug = b; 125 | #endif 126 | }); 127 | checkBox.tooltip = Str.options_enableDebugLoggingTooltip; 128 | } 129 | catch (Exception e) 130 | { 131 | Debug.Log("NetworkAnarchy OnSettingsUI failed [NA20]"); 132 | Debug.LogException(e); 133 | } 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /NetworkAnarchy/UI/Popups.cs: -------------------------------------------------------------------------------- 1 | using NetworkAnarchy.Lang; 2 | using QCommonLib.UI; 3 | using UnityEngine; 4 | 5 | namespace NetworkAnarchy.UI 6 | { 7 | //internal class ButtonReminderToastPanel : QToast 8 | //{ 9 | // protected override bool ShouldShow 10 | // { 11 | // get 12 | // { 13 | // if (NetworkAnarchy.instance == null) return false; 14 | // if (NetworkAnarchy.instance.m_firstRun) return false; 15 | // if (!NetworkAnarchy.instance.IsActive) return false; 16 | // if (!NetworkAnarchy.showButtonReminder) return false; 17 | // if (NetworkAnarchy.m_toolOptionButton.m_toolOptionsPanel.isVisible) return false; 18 | // return true; 19 | // } 20 | // } 21 | 22 | // public override void Start() 23 | // { 24 | // autoPanelVAlign = PanelVAlignment.Bottom; 25 | // Vector3 btnPos = NetworkAnarchy.m_toolOptionButton.absolutePosition; 26 | // arrowOffset = 40; 27 | // size = new Vector2(400, 50); 28 | // absolutePosition = btnPos + new Vector3(-70, -123, 0); 29 | 30 | // base.Start(); 31 | // SetText("Network Anarchy", Str.popup_buttonReminder); 32 | // isVisible = ShouldShow; 33 | // } 34 | 35 | // public override void Close() 36 | // { 37 | // CloseOnce(); 38 | // NetworkAnarchy.showButtonReminder.value = false; 39 | // } 40 | 41 | // public void CloseOnce() 42 | // { 43 | // base.Close(); 44 | // NetworkAnarchy.instance.ButtonReminderToast = null; 45 | // } 46 | //} 47 | 48 | //internal class CollisionFeatureRemovalPanel : QPopupWindow 49 | //{ 50 | // protected override bool ShouldShow => NetworkAnarchy.showCollisionRemoval; 51 | // protected override bool IncludeBottomButtonGap => true; 52 | 53 | // public override void Start() 54 | // { 55 | // base.Start(); 56 | 57 | // SetSize(new Vector2(430, 220)); 58 | // SetText("Network Anarchy", Str.popup_collisionRemoved); 59 | 60 | // OKButton(); 61 | // } 62 | 63 | // public override void Close() 64 | // { 65 | // base.Close(); 66 | // NetworkAnarchy.showCollisionRemoval.value = false; 67 | // } 68 | //} 69 | } 70 | -------------------------------------------------------------------------------- /NetworkAnarchy/UI/ToolOptionsButton.cs: -------------------------------------------------------------------------------- 1 | using ColossalFramework; 2 | using ColossalFramework.UI; 3 | using System; 4 | using System.Diagnostics; 5 | using UnityEngine; 6 | 7 | namespace NetworkAnarchy 8 | { 9 | public partial class UIToolOptionsButton : UICheckBox 10 | { 11 | private UIButton m_button; 12 | internal UIPanel m_toolOptionsPanel; 13 | private UISlider m_elevationStepSlider; 14 | private UILabel m_elevationStepLabel; 15 | internal UILabel m_maxSegmentLengthLabel; 16 | private UISlider m_maxSegmentLengthSlider; 17 | private UIDragHandle dragHandle; 18 | 19 | private UICheckBox m_normalModeButton; 20 | private UICheckBox m_groundModeButton; 21 | private UICheckBox m_elevatedModeButton; 22 | private UICheckBox m_bridgeModeButton; 23 | private UICheckBox m_tunnelModeButton; 24 | 25 | public UICheckBox m_anarchyBtn; 26 | public UICheckBox m_bendingBtn; 27 | public UICheckBox m_snappingBtn; 28 | public UICheckBox m_collisionBtn; 29 | public UICheckBox m_straightSlopeBtn; 30 | 31 | public UICheckBox m_grid; 32 | 33 | private UITextureAtlas m_atlas; 34 | 35 | private UIComponent m_parent; 36 | 37 | public static readonly SavedInt savedWindowX = new SavedInt("windowX", NetworkAnarchy.settingsFileName, -1000, true); 38 | public static readonly SavedInt savedWindowY = new SavedInt("windowY", NetworkAnarchy.settingsFileName, -1000, true); 39 | 40 | public static readonly SavedBool windowVisible = new SavedBool("windowVisible", NetworkAnarchy.settingsFileName, true, true); 41 | public static readonly SavedBool showElevationSlider = new SavedBool("showElevationSlider", NetworkAnarchy.settingsFileName, true, true); 42 | public static readonly SavedBool showMaxSegmentLengthSlider = new SavedBool("showNodeSpacer", NetworkAnarchy.settingsFileName, false, true); 43 | public static readonly SavedBool showLabels = new SavedBool("showLabels", NetworkAnarchy.settingsFileName, true, true); 44 | public static readonly SavedBool alwaysShowPanel = new SavedBool("alwaysShowPanel", NetworkAnarchy.settingsFileName, false, true); 45 | 46 | public static UIPanel toolOptionsPanel = null; 47 | 48 | public override void Start() 49 | { 50 | LoadResources(); 51 | 52 | CreateButton(); 53 | CreateOptionPanel(); 54 | 55 | isChecked = windowVisible; 56 | } 57 | 58 | public new void Update() 59 | { 60 | //if (parent != null || m_parent != null) Log.Debug($"parent:{(parent == null ? "" : parent.ToString())} m_parent:{(m_parent == null ? "" : m_parent.ToString())}"); 61 | if (parent != m_parent && parent != null) 62 | { 63 | string caller = new StackTrace()?.GetFrame(1)?.GetMethod()?.Name; 64 | Log.Debug($"Tool button parent changed: {ModInfo.GetString(parent)} (was: {ModInfo.GetString(m_parent)})\n Called by:{caller}", "[NA39]"); 65 | m_parent = parent; 66 | 67 | UpdateButton(); 68 | } 69 | 70 | if (m_toolOptionsPanel != null) 71 | { 72 | SetPanelVisible(isVisible && isChecked); 73 | } 74 | } 75 | 76 | public void SetPanelVisible(bool visible) 77 | { 78 | m_toolOptionsPanel.isVisible = visible; 79 | 80 | //if (alwaysShowPanel) 81 | //{ 82 | // m_toolOptionsPanel.isVisible = true; 83 | //} 84 | //else 85 | //{ 86 | // m_toolOptionsPanel.isVisible = visible; 87 | //} 88 | } 89 | 90 | public void UpdateButton() 91 | { 92 | if (NetworkAnarchy.instance == null) return; 93 | 94 | if (parent == null) 95 | { 96 | string caller = new StackTrace()?.GetFrame(1)?.GetMethod()?.Name; 97 | Log.Info($"Button parent is null (m_parent is {ModInfo.GetString(m_parent)})\n Called by:{caller}", "[NA38]"); 98 | isVisible = false; 99 | return; 100 | } 101 | 102 | //if (NetworkAnarchy.instance.IsButtonInOptionsBar) 103 | //{ 104 | // relativePosition = new Vector2(36, 0); 105 | //} 106 | //else 107 | //{ 108 | // relativePosition = Vector2.zero; 109 | // parent.BringToFront(); 110 | //} 111 | 112 | m_button.text = NetworkAnarchy.instance.elevationStep + "m\n"; 113 | if (m_elevationStepSlider != null) 114 | { 115 | m_elevationStepLabel.text = NetworkAnarchy.instance.elevationStep + "m\n"; 116 | m_elevationStepSlider.value = NetworkAnarchy.instance.elevationStep; 117 | } 118 | UpdateSlider(); 119 | 120 | m_button.normalFgSprite = NetworkAnarchy.instance.StraightSlope ? "ToolbarIconGroup1Hovered" : null; 121 | 122 | switch (NetworkAnarchy.instance.mode) 123 | { 124 | case Modes.Normal: 125 | m_button.text += "Nrm\n"; 126 | m_normalModeButton.SimulateClick(); 127 | break; 128 | case Modes.Ground: 129 | m_button.text += "Gnd\n"; 130 | m_groundModeButton.SimulateClick(); 131 | break; 132 | case Modes.Elevated: 133 | m_button.text += "Elv\n"; 134 | m_elevatedModeButton.SimulateClick(); 135 | break; 136 | case Modes.Bridge: 137 | m_button.text += "Bdg\n"; 138 | m_bridgeModeButton.SimulateClick(); 139 | break; 140 | case Modes.Tunnel: 141 | m_button.text += "Tnl\n"; 142 | m_tunnelModeButton.SimulateClick(); 143 | break; 144 | } 145 | 146 | m_button.text += NetworkAnarchy.instance.elevation + "m"; 147 | } 148 | 149 | private void UpdateSlider() 150 | { 151 | if (!showMaxSegmentLengthSlider || m_maxSegmentLengthSlider == null) return; 152 | 153 | NetworkAnarchy.saved_segmentLength.value = NetworkAnarchy.instance.MaxSegmentLength; 154 | try 155 | { 156 | m_maxSegmentLengthLabel.text = NetworkAnarchy.instance.MaxSegmentLength + "m"; 157 | if (NetworkAnarchy.instance.MaxSegmentLength > 128) 158 | { 159 | m_maxSegmentLengthLabel.textColor = new Color32(255, 191, 0, 255); 160 | } 161 | else 162 | { 163 | m_maxSegmentLengthLabel.textColor = Color.white; 164 | } 165 | m_maxSegmentLengthLabel.tooltip = (Mathf.RoundToInt(NetworkAnarchy.instance.MaxSegmentLength / 8f * 100) / 100f).ToString() + "u"; 166 | } 167 | catch (StackOverflowException e) 168 | { 169 | Log.Error(e); 170 | } 171 | } 172 | 173 | private void UpdateMode() 174 | { 175 | if (m_normalModeButton.isChecked) 176 | NetworkAnarchy.instance.mode = Modes.Normal; 177 | if (m_groundModeButton.isChecked) 178 | NetworkAnarchy.instance.mode = Modes.Ground; 179 | if (m_elevatedModeButton.isChecked) 180 | NetworkAnarchy.instance.mode = Modes.Elevated; 181 | if (m_bridgeModeButton.isChecked) 182 | NetworkAnarchy.instance.mode = Modes.Bridge; 183 | if (m_tunnelModeButton.isChecked) 184 | NetworkAnarchy.instance.mode = Modes.Tunnel; 185 | } 186 | 187 | delegate void ToggleAnarchyButton(); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NetworkAnarchy 2 | Combination of Fine Road Tool, Fine Road Anarchy, Tiny Segments, and more 3 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /NetworkAnarchy/Lang/Str.resx 3 | translation: /NetworkAnarchy/Lang/Str.%two_letters_code%.resx 4 | --------------------------------------------------------------------------------