├── .gitattributes ├── .gitignore ├── API ├── EDF.cs └── ModManager.cs ├── Extensions.cs ├── JavascriptHook.cs ├── Map.cs ├── MapEditor.cs ├── MapEditor.csproj ├── MapEditor.sln ├── MapObject.cs ├── MapSerializer.cs ├── Marker.cs ├── MenyooCompatibility.cs ├── ObjectDatabase.cs ├── ObjectList.ini ├── ObjectPreview.cs ├── PropStreamer.cs ├── Properties └── AssemblyInfo.cs ├── Quaternion.cs ├── Settings.cs ├── Translation.cs ├── VectorExtensions.cs ├── converter.py ├── crosshair.png ├── crosshair_blue.png ├── crosshair_yellow.png ├── input.txt └── output.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | # DNX 42 | project.lock.json 43 | artifacts/ 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Chutzpah Test files 71 | _Chutzpah* 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | 86 | # TFS 2012 Local Workspace 87 | $tf/ 88 | 89 | # Guidance Automation Toolkit 90 | *.gpState 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding add-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | ## TODO: Comment the next line if you want to checkin your 137 | ## web deploy settings but do note that will include unencrypted 138 | ## passwords 139 | #*.pubxml 140 | 141 | *.publishproj 142 | 143 | # NuGet Packages 144 | *.nupkg 145 | # The packages folder can be ignored because of Package Restore 146 | **/packages/* 147 | # except build/, which is used as an MSBuild target. 148 | !**/packages/build/ 149 | # Uncomment if necessary however generally it will be regenerated when needed 150 | #!**/packages/repositories.config 151 | 152 | # Windows Azure Build Output 153 | csx/ 154 | *.build.csdef 155 | 156 | # Windows Store app package directory 157 | AppPackages/ 158 | 159 | # Visual Studio cache files 160 | # files ending in .cache can be ignored 161 | *.[Cc]ache 162 | # but keep track of directories ending in .cache 163 | !*.[Cc]ache/ 164 | 165 | # Others 166 | ClientBin/ 167 | [Ss]tyle[Cc]op.* 168 | ~$* 169 | *~ 170 | *.dbmdl 171 | *.dbproj.schemaview 172 | *.pfx 173 | *.publishsettings 174 | node_modules/ 175 | orleans.codegen.cs 176 | 177 | # RIA/Silverlight projects 178 | Generated_Code/ 179 | 180 | # Backup & report files from converting an old project file 181 | # to a newer Visual Studio version. Backup files are not needed, 182 | # because we have git ;-) 183 | _UpgradeReport_Files/ 184 | Backup*/ 185 | UpgradeLog*.XML 186 | UpgradeLog*.htm 187 | 188 | # SQL Server files 189 | *.mdf 190 | *.ldf 191 | 192 | # Business Intelligence projects 193 | *.rdl.data 194 | *.bim.layout 195 | *.bim_*.settings 196 | 197 | # Microsoft Fakes 198 | FakesAssemblies/ 199 | 200 | # Node.js Tools for Visual Studio 201 | .ntvs_analysis.dat 202 | 203 | # Visual Studio 6 build log 204 | *.plg 205 | 206 | # Visual Studio 6 workspace options file 207 | *.opt 208 | 209 | # LightSwitch generated files 210 | GeneratedArtifacts/ 211 | _Pvt_Extensions/ 212 | ModelManifest.xml 213 | -------------------------------------------------------------------------------- /API/EDF.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml.Serialization; 3 | using GTA.Math; 4 | 5 | namespace MapEditor.API 6 | { 7 | 8 | 9 | // XML DEFINITIONS 10 | 11 | [XmlRoot("edf")] 12 | public class EDFDefinition 13 | { 14 | [XmlElement("element")] 15 | public List Elements = new List(); 16 | } 17 | 18 | public class EDFElement 19 | { 20 | [XmlAttribute("name")] 21 | public string Name; 22 | 23 | [XmlAttribute("friendlyname")] 24 | public string FriendlyName; 25 | 26 | [XmlAttribute("instructions")] 27 | public string Instructions; 28 | 29 | [XmlElement("data")] public List Data = new List(); 30 | 31 | // Representation 32 | [XmlAttribute("object")] public List Objects = new List(); 33 | [XmlAttribute("vehicle")] public List Vehicles = new List(); 34 | [XmlAttribute("ped")] public List Peds = new List(); 35 | [XmlAttribute("marker")] public List Markers = new List(); 36 | } 37 | 38 | public enum EDFDatatype 39 | { 40 | posx, 41 | posy, 42 | posz, 43 | rotx, 44 | roty, 45 | rotz, 46 | modelhash, 47 | modelname, 48 | dynamic, 49 | weapon, 50 | id, 51 | } 52 | 53 | public class EDFData 54 | { 55 | [XmlAttribute("name")] 56 | public string Name; 57 | [XmlAttribute("type")] 58 | public EDFDatatype Type; 59 | [XmlAttribute("default")] 60 | public string Default; 61 | } 62 | 63 | public class EDFRepresentationObject 64 | { 65 | [XmlAttribute("posX")] 66 | public float PosX; 67 | [XmlAttribute("posY")] 68 | public float PosY; 69 | [XmlAttribute("posZ")] 70 | public float PosZ; 71 | 72 | [XmlAttribute("rotX")] 73 | public float RotX; 74 | [XmlAttribute("rotY")] 75 | public float RotY; 76 | [XmlAttribute("rotZ")] 77 | public float RotZ; 78 | 79 | [XmlAttribute("model")] 80 | public int Model; 81 | } 82 | 83 | public class EDFRepresentationVehicle 84 | { 85 | [XmlAttribute("posX")] 86 | public float PosX; 87 | [XmlAttribute("posY")] 88 | public float PosY; 89 | [XmlAttribute("posZ")] 90 | public float PosZ; 91 | 92 | 93 | [XmlAttribute("model")] 94 | public int Model; 95 | } 96 | 97 | public class EDFRepresentationPed 98 | { 99 | [XmlAttribute("posX")] 100 | public float PosX; 101 | [XmlAttribute("posY")] 102 | public float PosY; 103 | [XmlAttribute("posZ")] 104 | public float PosZ; 105 | 106 | 107 | [XmlAttribute("model")] 108 | public int Model; 109 | } 110 | 111 | public class EDFRepresentationMarker 112 | { 113 | public EDFRepresentationMarker() 114 | { 115 | Color = "#ffffffff"; 116 | Size = 1f; 117 | } 118 | 119 | [XmlAttribute("posX")] 120 | public float PosX; 121 | [XmlAttribute("posY")] 122 | public float PosY; 123 | [XmlAttribute("posZ")] 124 | public float PosZ; 125 | 126 | 127 | [XmlAttribute("type")] 128 | public int Type; 129 | 130 | [XmlAttribute("color")] 131 | public string Color; 132 | 133 | [XmlAttribute("size")] 134 | public float Size; 135 | } 136 | } -------------------------------------------------------------------------------- /API/ModManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using GTA; 4 | using NativeUI; 5 | 6 | namespace MapEditor.API 7 | { 8 | public delegate void MapSavedEvent(Map currentMap, string filename); 9 | public delegate void ModSelectedEvent(); 10 | 11 | public delegate void ModDisconnectedEvent(); 12 | 13 | public static class ModManager 14 | { 15 | internal static List Mods = new List(); 16 | internal static ModListener CurrentMod; 17 | internal static UIMenu ModMenu; 18 | 19 | internal static void InitMenu() 20 | { 21 | ModMenu = new UIMenu("Map Editor", "~b~" + Translation.Translate("EXTERNAL MODS")); 22 | 23 | ModMenu.DisableInstructionalButtons(true); 24 | ModMenu.OnItemSelect += (menu, item, index) => 25 | { 26 | var tmpMod = Mods[index]; 27 | if (CurrentMod == tmpMod) 28 | { 29 | UI.Notify("~b~~h~Map Editor~h~~n~~w~Mod ~h~" + tmpMod.Name + "~h~ " + Translation.Translate("has been disconnected.")); 30 | CurrentMod.ModDisconnectInvoker(); 31 | CurrentMod = null; 32 | } 33 | else 34 | { 35 | UI.Notify("~b~~h~Map Editor~h~~n~~w~Mod ~h~" + tmpMod.Name + "~h~ " + Translation.Translate("has been connected.")); 36 | tmpMod.ModSelectInvoker(); 37 | CurrentMod = tmpMod; 38 | } 39 | }; 40 | } 41 | 42 | public static void SuscribeMod(ModListener mod) 43 | { 44 | Mods.Add(mod); 45 | ModMenu.AddItem(new UIMenuItem(mod.ButtonString, mod.Description)); 46 | } 47 | } 48 | 49 | public class ModListener 50 | { 51 | public event MapSavedEvent OnMapSaved; 52 | public event ModSelectedEvent OnModSelect; 53 | public event ModDisconnectedEvent OnModDisconnect; 54 | 55 | public string Name; 56 | public string Description; 57 | public string ButtonString; 58 | 59 | internal void MapSavedInvoker(Map map, string filename) 60 | { 61 | OnMapSaved?.Invoke(map, filename); 62 | } 63 | 64 | internal void ModSelectInvoker() 65 | { 66 | OnModSelect?.Invoke(); 67 | } 68 | 69 | internal void ModDisconnectInvoker() 70 | { 71 | OnModDisconnect?.Invoke(); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Extensions.cs: -------------------------------------------------------------------------------- 1 | namespace MapEditor 2 | { 3 | public static class Extensions 4 | { 5 | public static string Limit(this string s, int limit) 6 | { 7 | if (s == null) return null; 8 | if (s.Length > limit) return s.Substring(0, limit); 9 | return s; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /JavascriptHook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Windows.Forms; 7 | using GTA; 8 | using GTA.Math; 9 | using GTA.Native; 10 | using Microsoft.ClearScript; 11 | using Microsoft.ClearScript.Windows; 12 | 13 | namespace MapEditor 14 | { 15 | public class JavascriptHook : Script 16 | { 17 | public JavascriptHook() 18 | { 19 | Tick += OnTick; 20 | KeyDown += OnKeyDown; 21 | KeyUp += OnKeyUp; 22 | } 23 | 24 | public static List ScriptEngines = new List(); 25 | 26 | public void OnTick(object sender, EventArgs e) 27 | { 28 | lock (ScriptEngines) 29 | foreach (var engine in ScriptEngines) 30 | { 31 | try 32 | { 33 | engine.Script.script.InvokeTick(); 34 | } 35 | catch (ScriptEngineException ex) 36 | { 37 | LogException(ex); 38 | } 39 | } 40 | } 41 | 42 | public void OnKeyDown(object sender, KeyEventArgs e) 43 | { 44 | lock (ScriptEngines) 45 | foreach (var engine in ScriptEngines) 46 | { 47 | try 48 | { 49 | engine.Script.script.InvokeKeyDown(e); 50 | } 51 | catch (ScriptEngineException ex) 52 | { 53 | LogException(ex); 54 | } 55 | } 56 | } 57 | 58 | public void OnKeyUp(object sender, KeyEventArgs e) 59 | { 60 | lock (ScriptEngines) 61 | foreach (var engine in ScriptEngines) 62 | { 63 | try 64 | { 65 | engine.Script.script.InvokeKeyUp(e); 66 | } 67 | catch (ScriptEngineException ex) 68 | { 69 | LogException(ex); 70 | } 71 | } 72 | } 73 | 74 | public static void StartScript(string script, List identEnts) 75 | { 76 | var scriptEngine = new JScriptEngine(); 77 | var collection = new HostTypeCollection(Assembly.LoadFrom("scripthookvdotnet.dll"), 78 | Assembly.LoadFrom("scripts\\NativeUI.dll")); 79 | scriptEngine.AddHostObject("API", collection); 80 | scriptEngine.AddHostObject("host", new HostFunctions()); 81 | scriptEngine.AddHostObject("script", new ScriptContext()); 82 | scriptEngine.AddHostType("Enumerable", typeof(Enumerable)); 83 | scriptEngine.AddHostType("List", typeof(IList)); 84 | scriptEngine.AddHostType("KeyEventArgs", typeof(KeyEventArgs)); 85 | scriptEngine.AddHostType("Keys", typeof(Keys)); 86 | 87 | foreach (var obj in identEnts) 88 | { 89 | var name = PropStreamer.Identifications[obj]; 90 | if (MapEditor.IsPed(new Prop(obj))) 91 | scriptEngine.AddHostObject(name, new Ped(obj)); 92 | else if (MapEditor.IsVehicle(new Prop(obj))) 93 | scriptEngine.AddHostObject(name, new Vehicle(obj)); 94 | else if (MapEditor.IsProp(new Prop(obj))) 95 | scriptEngine.AddHostObject(name, new Prop(obj)); 96 | } 97 | 98 | try 99 | { 100 | scriptEngine.Execute(script); 101 | } 102 | catch (ScriptEngineException ex) 103 | { 104 | LogException(ex); 105 | } 106 | finally 107 | { 108 | lock (ScriptEngines) 109 | ScriptEngines.Add(scriptEngine); 110 | } 111 | } 112 | 113 | public static void StopAllScripts() 114 | { 115 | lock (ScriptEngines) 116 | { 117 | foreach (var engine in ScriptEngines) 118 | { 119 | engine.Script.script.InvokeDispose(); 120 | engine.Dispose(); 121 | } 122 | 123 | ScriptEngines.Clear(); 124 | } 125 | } 126 | 127 | private static void LogException(Exception ex) 128 | { 129 | Func splitter = (string input, int everyN) => 130 | { 131 | var list = new List(); 132 | for (int i = 0; i < input.Length; i += everyN) 133 | { 134 | list.Add(input.Substring(i, Math.Min(everyN, input.Length - i))); 135 | } 136 | return list.ToArray(); 137 | }; 138 | 139 | UI.Notify("~r~~h~Map Javascript Error~h~~w~"); 140 | 141 | foreach (var s in splitter(ex.Message, 99)) 142 | { 143 | UI.Notify(s); 144 | } 145 | 146 | if (ex.InnerException != null) 147 | foreach (var s in splitter(ex.InnerException.Message, 99)) 148 | { 149 | UI.Notify(s); 150 | } 151 | } 152 | } 153 | 154 | public class ScriptContext 155 | { 156 | public enum ReturnType 157 | { 158 | Int = 0, 159 | UInt = 1, 160 | Long = 2, 161 | ULong = 3, 162 | String = 4, 163 | Vector3 = 5, 164 | Vector2 = 6, 165 | Float = 7 166 | } 167 | 168 | public void CallNative(string hash, params object[] args) 169 | { 170 | Hash ourHash; 171 | if (!Hash.TryParse(hash, out ourHash)) 172 | return; 173 | Function.Call(ourHash, args.Select(o => new InputArgument(o)).ToArray()); 174 | } 175 | 176 | public object ReturnNative(string hash, int returnType, params object[] args) 177 | { 178 | Hash ourHash; 179 | if (!Hash.TryParse(hash, out ourHash)) 180 | return null; 181 | var fArgs = args.Select(o => new InputArgument(o)).ToArray(); 182 | switch ((ReturnType)returnType) 183 | { 184 | case ReturnType.Int: 185 | return Function.Call(ourHash, fArgs); 186 | case ReturnType.UInt: 187 | return Function.Call(ourHash, fArgs); 188 | case ReturnType.Long: 189 | return Function.Call(ourHash, fArgs); 190 | case ReturnType.ULong: 191 | return Function.Call(ourHash, fArgs); 192 | case ReturnType.String: 193 | return Function.Call(ourHash, fArgs); 194 | case ReturnType.Vector3: 195 | return Function.Call(ourHash, fArgs); 196 | case ReturnType.Vector2: 197 | return Function.Call(ourHash, fArgs); 198 | case ReturnType.Float: 199 | return Function.Call(ourHash, fArgs); 200 | default: 201 | return null; 202 | } 203 | } 204 | 205 | public void MoveProp(Prop prop, Vector3 newPos, Vector3 newRot, int duration) 206 | { 207 | var start = Game.GameTime; 208 | while (Game.GameTime - start <= duration) 209 | { 210 | prop.Position = NativeUI.MiscExtensions.LinearVectorLerp(prop.Position, newPos, Game.GameTime - start, duration); 211 | prop.Rotation = NativeUI.MiscExtensions.LinearVectorLerp(prop.Rotation, newRot, Game.GameTime - start, duration); 212 | Script.Yield(); 213 | } 214 | } 215 | 216 | public bool IsPed(int ent) 217 | { 218 | return Function.Call(Hash.IS_ENTITY_A_PED, ent); 219 | } 220 | 221 | public bool IsVehicle(int ent) 222 | { 223 | return Function.Call(Hash.IS_ENTITY_A_VEHICLE, ent); 224 | } 225 | 226 | public bool IsProp(int ent) 227 | { 228 | return Function.Call(Hash.IS_ENTITY_AN_OBJECT, ent); 229 | } 230 | 231 | public int[] GetCurrentMap() 232 | { 233 | return PropStreamer.GetAllHandles(); 234 | } 235 | 236 | public event EventHandler OnDispose; 237 | public event EventHandler OnTick; 238 | public event KeyEventHandler OnKeyDown; 239 | public event KeyEventHandler OnKeyUp; 240 | 241 | public void InvokeTick() 242 | { 243 | OnTick?.Invoke(this, EventArgs.Empty); 244 | } 245 | 246 | public void InvokeKeyDown(KeyEventArgs e) 247 | { 248 | OnKeyDown?.Invoke(this, e); 249 | } 250 | 251 | public void InvokeKeyUp(KeyEventArgs e) 252 | { 253 | OnKeyUp?.Invoke(this, e); 254 | } 255 | 256 | public void InvokeDispose() 257 | { 258 | OnDispose?.Invoke(this, EventArgs.Empty); 259 | } 260 | } 261 | 262 | } -------------------------------------------------------------------------------- /Map.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using GTA; 4 | using GTA.Math; 5 | 6 | namespace MapEditor 7 | { 8 | public class Map 9 | { 10 | public List Objects = new List(); 11 | public List RemoveFromWorld = new List(); 12 | public List Markers = new List(); 13 | public MapMetadata Metadata; 14 | } 15 | 16 | public class MapMetadata 17 | { 18 | public MapMetadata() 19 | { 20 | Creator = Game.Player.Name; 21 | Name = "Nameless Map"; 22 | Description = ""; 23 | } 24 | 25 | public string Creator { get; set; } 26 | public string Name { get; set; } 27 | public string Description { get; set; } 28 | public string Filename { get; set; } 29 | 30 | public Vector3? LoadingPoint { get; set; } 31 | public Vector3? TeleportPoint { get; set; } 32 | 33 | public bool ShouldSerializeFilename() 34 | { 35 | return false; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /MapEditor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3AD37808-25AE-41CD-BC45-03D7A3C669AB} 8 | Library 9 | Properties 10 | MapEditor 11 | MapEditor 12 | v4.5.2 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | x64 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | x64 34 | false 35 | 36 | 37 | 38 | ..\..\..\..\..\Program Files\Rockstar Games\Grand Theft Auto V\scripts\ClearScript.dll 39 | 40 | 41 | ..\..\..\..\..\Program Files\Rockstar Games\Grand Theft Auto V\scripts\NativeUI.dll 42 | 43 | 44 | False 45 | bin\Release\ScriptHookVDotNet.dll 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 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 | copy /Y "$(TargetPath)" "A:\Program Files\Rockstar Games\Grand Theft Auto V\scripts\$(TargetFileName)" 91 | 92 | 99 | -------------------------------------------------------------------------------- /MapEditor.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapEditor", "MapEditor.csproj", "{3AD37808-25AE-41CD-BC45-03D7A3C669AB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3AD37808-25AE-41CD-BC45-03D7A3C669AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {3AD37808-25AE-41CD-BC45-03D7A3C669AB}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {3AD37808-25AE-41CD-BC45-03D7A3C669AB}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {3AD37808-25AE-41CD-BC45-03D7A3C669AB}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /MapObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Xml.Serialization; 4 | using GTA; 5 | using GTA.Math; 6 | using GTA.Native; 7 | 8 | namespace MapEditor 9 | { 10 | public class MapObject 11 | { 12 | public ObjectTypes Type; 13 | public Vector3 Position; 14 | public Vector3 Rotation; 15 | public int Hash; 16 | public bool Dynamic; 17 | public Quaternion Quaternion; 18 | 19 | // Prop stuff 20 | public bool Door; 21 | 22 | // Ped stuff 23 | public string Action; 24 | public string Relationship; 25 | public WeaponHash? Weapon; 26 | 27 | // Vehicle stuff 28 | public bool SirensActive; 29 | public int PrimaryColor; 30 | public int SecondaryColor; 31 | 32 | // Pickup stuff 33 | public int Amount; 34 | public int RespawnTimer; 35 | public int Flag; 36 | 37 | [XmlAttribute("Id")] 38 | public string Id; 39 | 40 | // XML Stuff 41 | public bool ShouldSerializeDoor() 42 | { 43 | return Type == ObjectTypes.Prop; 44 | } 45 | 46 | public bool ShouldSerializeAction() 47 | { 48 | return Type == ObjectTypes.Ped; 49 | } 50 | 51 | public bool ShouldSerializeRelationship() 52 | { 53 | return Type == ObjectTypes.Ped; 54 | } 55 | 56 | public bool ShouldSerializeWeapon() 57 | { 58 | return Type == ObjectTypes.Ped; 59 | } 60 | 61 | public bool ShouldSerializeSirensActive() 62 | { 63 | return Type == ObjectTypes.Vehicle; 64 | } 65 | 66 | public bool ShouldSerializePrimaryColor() 67 | { 68 | return Type == ObjectTypes.Vehicle; 69 | } 70 | 71 | public bool ShouldSerializeSecondaryColor() 72 | { 73 | return Type == ObjectTypes.Vehicle; 74 | } 75 | 76 | public bool ShouldSerializeAmount() 77 | { 78 | return Type == ObjectTypes.Pickup; 79 | } 80 | 81 | public bool ShouldSerializeRespawnTimer() 82 | { 83 | return Type == ObjectTypes.Pickup; 84 | } 85 | 86 | public bool ShouldSerializeFlag() 87 | { 88 | return Type == ObjectTypes.Pickup; 89 | } 90 | } 91 | 92 | public class PedDrawables 93 | { 94 | public int[] Drawables; 95 | public int[] Textures; 96 | } 97 | 98 | public class DynamicPickup 99 | { 100 | public DynamicPickup(int handle) 101 | { 102 | PickupHandle = handle; 103 | IsInRange = handle != -1; 104 | } 105 | 106 | private int _timeout = -1; 107 | private bool _dynamic = true; 108 | 109 | public bool IsInRange { get; set; } 110 | 111 | public bool Dynamic 112 | { 113 | get { return _dynamic; } 114 | set 115 | { 116 | _dynamic = value; 117 | new Prop(ObjectHandle).FreezePosition = !value; 118 | } 119 | } 120 | 121 | public string PickupName 122 | { 123 | get 124 | { 125 | if (Enum.IsDefined(typeof (ObjectDatabase.PickupHash), PickupHash)) 126 | return ((ObjectDatabase.PickupHash) PickupHash).ToString(); 127 | return ""; 128 | } 129 | } 130 | 131 | public int UID { get; set; } 132 | public int PickupHash { get; set; } 133 | public int PickupHandle { get; set; } 134 | public int Amount { get; set; } 135 | public int Flag { get; set; } 136 | 137 | public bool PickedUp { get; set; } 138 | public DateTime LastPickup { get; set; } 139 | 140 | public int ObjectHandle => Function.Call((Hash) 0x5099BC55630B25AE, PickupHandle); 141 | //public Vector3 Position => Function.Call(Hash.GET_PICKUP_COORDS, PickupHandle); 142 | 143 | 144 | public void UpdatePos() 145 | { 146 | RealPosition = Position; 147 | } 148 | 149 | public Vector3 RealPosition { get; set; } 150 | 151 | public Vector3 Position 152 | { 153 | get { return new Prop(ObjectHandle).Position; } 154 | set 155 | { 156 | new Prop(ObjectHandle).Position = value; 157 | RealPosition = value; 158 | } 159 | } 160 | 161 | public void SetPickupHash(int newHash) 162 | { 163 | PickupHash = newHash; 164 | ReloadPickup(); 165 | } 166 | 167 | public void SetPickupFlag(int newFlag) 168 | { 169 | Flag = newFlag; 170 | ReloadPickup(); 171 | } 172 | 173 | public void SetAmount(int newAmount) 174 | { 175 | Amount = newAmount; 176 | ReloadPickup(); 177 | } 178 | 179 | private void ReloadPickup() 180 | { 181 | var newPickup = Function.Call(Hash.CREATE_PICKUP_ROTATE, PickupHash, RealPosition.X, RealPosition.Y, RealPosition.Z, 0, 0, 0, Flag, Amount, 0, false, 0); 182 | 183 | var tmpDyn = new DynamicPickup(newPickup); 184 | 185 | var start = 0; 186 | while (tmpDyn.ObjectHandle == -1 && start < 20) 187 | { 188 | start++; 189 | Script.Yield(); 190 | tmpDyn.Position = RealPosition; 191 | } 192 | 193 | tmpDyn.Dynamic = Dynamic; 194 | tmpDyn.Timeout = Timeout; 195 | new Prop(tmpDyn.ObjectHandle).IsPersistent = true; 196 | 197 | if (PickupHandle != -1) 198 | Remove(); 199 | 200 | 201 | PickupHandle = newPickup; 202 | } 203 | 204 | public int Timeout 205 | { 206 | get { return _timeout; } 207 | set 208 | { 209 | _timeout = value; 210 | //Function.Call(Hash.SET_PICKUP_REGENERATION_TIME, PickupHandle, value); 211 | } 212 | } 213 | 214 | public bool PickupObjectExists => Function.Call(Hash.DOES_PICKUP_OBJECT_EXIST, PickupHandle); 215 | 216 | public bool PickupExists => Function.Call(Hash.DOES_PICKUP_EXIST, PickupHandle); 217 | 218 | public void Remove() 219 | { 220 | Function.Call(Hash.REMOVE_PICKUP, PickupHandle); 221 | } 222 | 223 | public void Update() 224 | { 225 | var inRange = Game.Player.Character.IsInRangeOf(RealPosition, 20f); 226 | 227 | if (inRange && PickupHandle == -1) 228 | { 229 | ReloadPickup(); 230 | } 231 | 232 | if (PickupHandle != -1) 233 | { 234 | Position = RealPosition; 235 | 236 | if (!inRange) return; 237 | 238 | if (!PickupObjectExists && !PickedUp) 239 | { 240 | PickedUp = true; 241 | LastPickup = DateTime.Now; 242 | Remove(); 243 | } 244 | 245 | if (PickedUp && DateTime.Now.Subtract(LastPickup).TotalSeconds > Timeout && Timeout != 0) 246 | { 247 | PickedUp = false; 248 | ReloadPickup(); 249 | } 250 | } 251 | } 252 | } 253 | 254 | public enum ObjectTypes 255 | { 256 | Prop, 257 | Vehicle, 258 | Ped, 259 | Marker, 260 | Pickup, 261 | } 262 | } -------------------------------------------------------------------------------- /MapSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Xml; 7 | using System.Xml.Serialization; 8 | using GTA; 9 | using GTA.Math; 10 | using GTA.Native; 11 | 12 | namespace MapEditor 13 | { 14 | public class MapSerializer 15 | { 16 | public enum Format 17 | { 18 | NormalXml, 19 | SimpleTrainer, 20 | CSharpCode, 21 | SpoonerLegacy, 22 | Menyoo, 23 | Raw, 24 | } 25 | 26 | public float Parse(string floatVal) 27 | { 28 | return float.Parse(floatVal, CultureInfo.InvariantCulture); 29 | } 30 | 31 | internal Map Deserialize(string path, Format format) 32 | { 33 | string tip = ""; 34 | switch (format) 35 | { 36 | case Format.NormalXml: 37 | XmlSerializer reader = new XmlSerializer(typeof (Map)); 38 | var file = new StreamReader(path); 39 | var map = (Map) reader.Deserialize(file); 40 | file.Close(); 41 | return map; 42 | case Format.Menyoo: 43 | var spReader = new XmlSerializer(typeof(MenyooCompatibility.SpoonerPlacements)); 44 | var spFile = new StreamReader(path); 45 | var spMap = (MenyooCompatibility.SpoonerPlacements) spReader.Deserialize(spFile); 46 | spFile.Close(); 47 | 48 | var outputMap = new Map(); 49 | 50 | foreach (var placement in spMap.Placement) 51 | { 52 | var obj = new MapObject(); 53 | switch (placement.Type) 54 | { 55 | case 3: // Props 56 | { 57 | obj.Type = ObjectTypes.Prop; 58 | } 59 | break; 60 | case 1: // Peds 61 | { 62 | 63 | obj.Type = ObjectTypes.Ped; 64 | } 65 | break; 66 | case 2: // Vehicles 67 | { 68 | obj.Type = ObjectTypes.Vehicle; 69 | } 70 | break; 71 | } 72 | obj.Dynamic = placement.Dynamic; 73 | obj.Hash = Convert.ToInt32(placement.ModelHash, 16); 74 | obj.Position = new Vector3(placement.PositionRotation.X, placement.PositionRotation.Y, placement.PositionRotation.Z); 75 | obj.Rotation = new Vector3(placement.PositionRotation.Pitch, placement.PositionRotation.Roll, placement.PositionRotation.Yaw); 76 | outputMap.Objects.Add(obj); 77 | } 78 | return outputMap; 79 | case Format.SimpleTrainer: 80 | { 81 | var tmpMap = new Map(); 82 | string currentSection = ""; 83 | string oldSection = ""; 84 | Dictionary tmpData = new Dictionary(); 85 | foreach (string line in File.ReadAllLines(path)) 86 | { 87 | if (line.StartsWith("[") && line.EndsWith("]")) 88 | { 89 | oldSection = currentSection; 90 | currentSection = line; 91 | tip = currentSection; 92 | if (oldSection == "" || oldSection == "[Player]") continue; 93 | Vector3 pos = new Vector3(float.Parse(tmpData["x"], CultureInfo.InvariantCulture), 94 | float.Parse(tmpData["y"], CultureInfo.InvariantCulture), 95 | float.Parse(tmpData["z"], CultureInfo.InvariantCulture)); 96 | Vector3 rot = new Vector3(float.Parse(tmpData["qz"]), float.Parse(tmpData["qw"]), float.Parse(tmpData["h"])); 97 | Quaternion q = new Quaternion() 98 | { 99 | X = Parse(tmpData["qx"]), 100 | Y = Parse(tmpData["qy"]), 101 | Z = Parse(tmpData["qz"]), 102 | W = Parse(tmpData["qw"]), 103 | }; 104 | int mod = Convert.ToInt32(tmpData["Model"], CultureInfo.InvariantCulture); 105 | int dyn = Convert.ToInt32(tmpData["Dynamic"], CultureInfo.InvariantCulture); 106 | tmpMap.Objects.Add(new MapObject() 107 | { 108 | Hash = mod, 109 | Position = pos, 110 | Rotation = rot, 111 | Dynamic = dyn == 1, 112 | Quaternion = q 113 | }); 114 | tmpData = new Dictionary(); 115 | continue; 116 | } 117 | if (currentSection == "[Player]") continue; 118 | string[] spl = line.Split('='); 119 | tmpData.Add(spl[0], spl[1]); 120 | } 121 | Vector3 lastPos = new Vector3(float.Parse(tmpData["x"], CultureInfo.InvariantCulture), 122 | float.Parse(tmpData["y"], CultureInfo.InvariantCulture), float.Parse(tmpData["z"], CultureInfo.InvariantCulture)); 123 | Vector3 lastRot = new Vector3(float.Parse(tmpData["qz"]), float.Parse(tmpData["qw"]), float.Parse(tmpData["h"])); 124 | Quaternion lastQ = new Quaternion() 125 | { 126 | X = Parse(tmpData["qx"]), 127 | Y = Parse(tmpData["qy"]), 128 | Z = Parse(tmpData["qz"]), 129 | W = Parse(tmpData["qw"]), 130 | }; 131 | int lastMod = Convert.ToInt32(tmpData["Model"], CultureInfo.InvariantCulture); 132 | int lastDyn = Convert.ToInt32(tmpData["Dynamic"], CultureInfo.InvariantCulture); 133 | tmpMap.Objects.Add(new MapObject() 134 | { 135 | Hash = lastMod, 136 | Position = lastPos, 137 | Rotation = lastRot, 138 | Dynamic = lastDyn == 1, 139 | Quaternion = lastQ 140 | }); 141 | return tmpMap; 142 | } 143 | case Format.SpoonerLegacy: 144 | { 145 | var tmpMap = new Map(); 146 | string currentSection = ""; 147 | string oldSection = ""; 148 | Dictionary tmpData = new Dictionary(); 149 | foreach (string line in File.ReadAllLines(path)) 150 | { 151 | if (line.StartsWith("[") && line.EndsWith("]")) 152 | { 153 | oldSection = currentSection; 154 | currentSection = line; 155 | tip = currentSection; 156 | if (!tmpData.ContainsKey("Type")) continue; 157 | Vector3 pos = new Vector3(float.Parse(tmpData["X"], CultureInfo.InvariantCulture), 158 | float.Parse(tmpData["Y"], CultureInfo.InvariantCulture), 159 | float.Parse(tmpData["Z"], CultureInfo.InvariantCulture)); 160 | Vector3 rot = new Vector3(float.Parse(tmpData["Pitch"]), float.Parse(tmpData["Roll"]), float.Parse(tmpData["Yaw"])); 161 | 162 | int mod = Convert.ToInt32("0x" + tmpData["Hash"], 16); 163 | tmpMap.Objects.Add(new MapObject() 164 | { 165 | Hash = mod, 166 | Position = pos, 167 | Rotation = rot, 168 | Type = tmpData["Type"] == "1" ? ObjectTypes.Ped : tmpData["Type"] == "2" ? ObjectTypes.Vehicle : ObjectTypes.Prop, 169 | }); 170 | tmpData = new Dictionary(); 171 | continue; 172 | } 173 | string[] spl = line.Split('='); 174 | if (spl.Length >= 2) 175 | tmpData.Add(spl[0].Trim(), spl[1].Trim()); 176 | } 177 | return tmpMap; 178 | } 179 | break; 180 | default: 181 | throw new NotImplementedException("This is not implemented yet."); 182 | } 183 | } 184 | 185 | internal void Serialize(string path, Map map, Format format) 186 | { 187 | if(path == null) return; 188 | switch (format) 189 | { 190 | case Format.NormalXml: 191 | XmlSerializer writer = new XmlSerializer(typeof(Map)); 192 | map.Objects.RemoveAll(mo => mo.Position == new Vector3(0, 0, 0)); 193 | var file = new StreamWriter(path); 194 | writer.Serialize(file, map); 195 | file.Close(); 196 | break; 197 | case Format.SimpleTrainer: 198 | string mainOutput = "[Player]\r\n" + 199 | "Teleport=0\r\n" + 200 | "x=0\r\n" + 201 | "y=0\r\n" + 202 | "z=0\r\n"; 203 | int count = 1; 204 | for (int i = 0; i < map.Objects.Count; i++) 205 | { 206 | if(map.Objects[i].Position == new Vector3(0, 0, 0)) continue; 207 | mainOutput += "[" + count + "]\r\n"; 208 | mainOutput += "x=" + map.Objects[i].Position.X.ToString(CultureInfo.InvariantCulture) + "\r\n"; 209 | mainOutput += "y=" + map.Objects[i].Position.Y.ToString(CultureInfo.InvariantCulture) + "\r\n"; 210 | mainOutput += "z=" + map.Objects[i].Position.Z.ToString(CultureInfo.InvariantCulture) + "\r\n"; 211 | mainOutput += "h=" + map.Objects[i].Rotation.Z.ToString(CultureInfo.InvariantCulture) + "\r\n"; 212 | mainOutput += "Model=" + map.Objects[i].Hash + "\r\n"; 213 | mainOutput += "qx=" + map.Objects[i].Quaternion.X.ToString(CultureInfo.InvariantCulture) + "\r\n"; 214 | mainOutput += "qy=" + map.Objects[i].Quaternion.Y.ToString(CultureInfo.InvariantCulture) + "\r\n"; 215 | mainOutput += "qz=" + map.Objects[i].Quaternion.Z.ToString(CultureInfo.InvariantCulture) + "\r\n"; 216 | mainOutput += "qw=" + map.Objects[i].Quaternion.W.ToString(CultureInfo.InvariantCulture) + "\r\n"; 217 | mainOutput += "offz=0\r\n"; 218 | mainOutput += "Dynamic=" + (map.Objects[i].Dynamic ? "1\n" : "0\n"); 219 | count++; 220 | } 221 | File.WriteAllText(path, mainOutput); 222 | break; 223 | case Format.SpoonerLegacy: 224 | string main = ""; 225 | int c = 1; 226 | for (int i = 0; i < map.Objects.Count; i++) 227 | { 228 | if (map.Objects[i].Position == new Vector3(0, 0, 0)) continue; 229 | main += "[" + c + "]\r\n"; 230 | main += "Type = " + (map.Objects[i].Type == ObjectTypes.Ped ? 1 : map.Objects[i].Type == ObjectTypes.Vehicle ? 2 : 3) + "\r\n"; 231 | main += "Hash = " + map.Objects[i].Hash.ToString("x8") + "\r\n"; 232 | main += "X = " + map.Objects[i].Position.X.ToString(CultureInfo.InvariantCulture) + "\r\n"; 233 | main += "Y = " + map.Objects[i].Position.Y.ToString(CultureInfo.InvariantCulture) + "\r\n"; 234 | main += "Z = " + map.Objects[i].Position.Z.ToString(CultureInfo.InvariantCulture) + "\r\n"; 235 | main += "Pitch = " + map.Objects[i].Rotation.X.ToString(CultureInfo.InvariantCulture) + "\r\n"; 236 | main += "Roll = " + map.Objects[i].Rotation.Y.ToString(CultureInfo.InvariantCulture) + "\r\n"; 237 | main += "Yaw = " + map.Objects[i].Rotation.Z.ToString(CultureInfo.InvariantCulture) + "\r\n"; 238 | main += "Opacity = 0x000000ff\r\n"; 239 | c++; 240 | } 241 | File.WriteAllText(path, main); 242 | break; 243 | case Format.CSharpCode: 244 | string vehicles = ""; 245 | string peds = ""; 246 | string props = ""; 247 | string markers = ""; 248 | string pickups = ""; 249 | string removedFromWorld = " Prop returnedProp;\r\n"; 250 | 251 | foreach (var prop in map.Objects) 252 | { 253 | if (prop.Position == new Vector3(0, 0, 0)) continue; 254 | 255 | if (prop.Type == ObjectTypes.Vehicle) 256 | { 257 | vehicles += String.Format(" GTA.World.CreateVehicle(new Model({0}), new GTA.Math.Vector3({1}f, {2}f, {3}f), {4}f);\r\n", 258 | prop.Hash, 259 | prop.Position.X.ToString(CultureInfo.InvariantCulture), 260 | prop.Position.Y.ToString(CultureInfo.InvariantCulture), 261 | prop.Position.Z.ToString(CultureInfo.InvariantCulture), 262 | prop.Rotation.Z.ToString(CultureInfo.InvariantCulture) 263 | ); 264 | } 265 | else if (prop.Type == ObjectTypes.Ped) 266 | { 267 | peds += String.Format(" GTA.World.CreatePed(new Model({0}), new GTA.Math.Vector3({1}f, {2}f, {3}f), {4}f);\r\n", 268 | prop.Hash, 269 | prop.Position.X.ToString(CultureInfo.InvariantCulture), 270 | prop.Position.Y.ToString(CultureInfo.InvariantCulture), 271 | prop.Position.Z.ToString(CultureInfo.InvariantCulture), 272 | prop.Rotation.Z.ToString(CultureInfo.InvariantCulture) 273 | ); 274 | } 275 | else if (prop.Type == ObjectTypes.Prop) 276 | { 277 | props += String.Format(" Props.Add(createProp({0}, new GTA.Math.Vector3({1}f, {2}f, {3}f), new GTA.Math.Vector3({4}f, {5}f, {6}f), {7}));\r\n", 278 | prop.Hash, 279 | prop.Position.X.ToString(CultureInfo.InvariantCulture), 280 | prop.Position.Y.ToString(CultureInfo.InvariantCulture), 281 | prop.Position.Z.ToString(CultureInfo.InvariantCulture), 282 | prop.Rotation.X.ToString(CultureInfo.InvariantCulture), 283 | prop.Rotation.Y.ToString(CultureInfo.InvariantCulture), 284 | prop.Rotation.Z.ToString(CultureInfo.InvariantCulture), 285 | prop.Dynamic.ToString().ToLower() 286 | ); 287 | } 288 | else if (prop.Type == ObjectTypes.Pickup) 289 | { 290 | pickups += string.Format(" Function.Call(Hash.CREATE_PICKUP_ROTATE, {0}, {1}f, {2}f, {3}f, 0, 0, 0, 515, {4}, 0, false, 0);\r\n", 291 | prop.Hash, 292 | prop.Position.X.ToString(CultureInfo.InvariantCulture), 293 | prop.Position.Y.ToString(CultureInfo.InvariantCulture), 294 | prop.Position.Z.ToString(CultureInfo.InvariantCulture), 295 | prop.Amount); 296 | } 297 | } 298 | 299 | foreach (var marker in map.Markers) 300 | { 301 | markers += string.Format(" Function.Call(Hash.DRAW_MARKER, {0}," + 302 | "{1}f, {2}f, {3}f, " + 303 | "0f, 0f, 0f, {4}f, {5}f, {6}f, " + 304 | "{7}f, {8}f, {9}f, " + 305 | "{10}, {11}, {12}, {13}, " + 306 | "{14}, {15}, 2, false, false, false);\r\n", 307 | 308 | (int)marker.Type, marker.Position.X.ToString(CultureInfo.InvariantCulture), marker.Position.Y.ToString(CultureInfo.InvariantCulture), marker.Position.Z.ToString(CultureInfo.InvariantCulture), marker.Rotation.X.ToString(CultureInfo.InvariantCulture), 309 | marker.Rotation.Y.ToString(CultureInfo.InvariantCulture), marker.Rotation.Z.ToString(CultureInfo.InvariantCulture), marker.Scale.X.ToString(CultureInfo.InvariantCulture), marker.Scale.Y.ToString(CultureInfo.InvariantCulture), marker.Scale.Z.ToString(CultureInfo.InvariantCulture), marker.Red, 310 | marker.Green, marker.Blue, marker.Alpha, marker.BobUpAndDown.ToString().ToLower(), 311 | marker.RotateToCamera.ToString().ToLower()); 312 | } 313 | 314 | foreach (var o in map.RemoveFromWorld) 315 | { 316 | removedFromWorld += string.Format( 317 | @" returnedProp = Function.Call(Hash.GET_CLOSEST_OBJECT_OF_TYPE, {0}f, {1}f, {2}f, 1f, {3}, 0); 318 | if (returnedProp != null && returnedProp.Handle != 0 && !Props.Contains(returnedProp.Handle)) 319 | returnedProp.Delete();" + "\r\n", 320 | o.Position.X.ToString(CultureInfo.InvariantCulture), o.Position.Y.ToString(CultureInfo.InvariantCulture), o.Position.Z.ToString(CultureInfo.InvariantCulture), o.Hash); 321 | } 322 | 323 | 324 | 325 | string finalOutput = string.Format(@"using System; 326 | using System.Collections.Generic; 327 | using GTA; 328 | using GTA.Math; 329 | using GTA.Native; 330 | 331 | 332 | public class MapEditorGeneratedMap : GTA.Script 333 | {{ 334 | public MapEditorGeneratedMap() 335 | {{ 336 | List Props = new List(); 337 | int LodDistance = 3000; 338 | 339 | Func createProp = new Func(delegate(int hash, Vector3 pos, Vector3 rot, bool dynamic) 340 | {{ 341 | Model model = new Model(hash); 342 | model.Request(10000); 343 | Prop prop = GTA.World.CreateProp(model, pos, rot, dynamic, false); 344 | prop.Position = pos; 345 | prop.LodDistance = LodDistance; 346 | if (!dynamic) 347 | prop.FreezePosition = true; 348 | return prop.Handle; 349 | }}); 350 | 351 | bool Initialized = false; 352 | 353 | 354 | base.Tick += delegate (object sender, EventArgs args) 355 | {{ 356 | if (!Initialized) 357 | {{ 358 | /* PROPS */ 359 | {0} 360 | 361 | /* VEHICLES */ 362 | {1} 363 | 364 | /* PEDS */ 365 | {2} 366 | 367 | /* PICKUPS */ 368 | {4} 369 | Initialized = true; 370 | }} 371 | 372 | /* MARKERS */ 373 | {3} 374 | 375 | /* WORLD */ 376 | {5} 377 | }}; 378 | }} 379 | }}", props, vehicles, peds, markers, pickups, removedFromWorld); 380 | 381 | using (var stream = new StreamWriter(new FileStream(path, File.Exists(path) ? FileMode.Truncate : FileMode.CreateNew))) 382 | { 383 | stream.Write(finalOutput); 384 | } 385 | break; 386 | case Format.Raw: 387 | string flush = ""; 388 | foreach (var prop in map.Objects) 389 | { 390 | if (prop.Position == new Vector3(0, 0, 0)) continue; 391 | string name = ""; 392 | ObjectTypes thisType = ObjectTypes.Prop; 393 | 394 | if (prop.Type == ObjectTypes.Vehicle) 395 | { 396 | name = ObjectDatabase.VehicleDb.First(pair => pair.Value == prop.Hash).Key; 397 | thisType = ObjectTypes.Vehicle; 398 | } 399 | if (prop.Type == ObjectTypes.Ped) 400 | { 401 | name = ObjectDatabase.PedDb.First(pair => pair.Value == prop.Hash).Key; 402 | thisType = ObjectTypes.Ped; 403 | } 404 | if (prop.Type == ObjectTypes.Prop) 405 | { 406 | name = ObjectDatabase.MainDb.First(pair => pair.Value == prop.Hash).Key; 407 | thisType = ObjectTypes.Prop; 408 | } 409 | flush += String.Format("{8} name = {0}, hash = {7}, x = {1}, y = {2}, z = {3}, rotationx = {4}, rotationy = {5}, rotationz = {6}\r\n", 410 | name, 411 | prop.Position.X, 412 | prop.Position.Y, 413 | prop.Position.Z, 414 | prop.Rotation.X, 415 | prop.Rotation.Y, 416 | prop.Rotation.Z, 417 | prop.Hash, 418 | thisType 419 | ); 420 | } 421 | File.WriteAllText(path, flush); 422 | break; 423 | case Format.Menyoo: 424 | XmlSerializer menSer = new XmlSerializer(typeof(MenyooCompatibility.SpoonerPlacements)); 425 | map.Objects.RemoveAll(mo => mo.Position == new Vector3(0, 0, 0)); 426 | var menObj = new MenyooCompatibility.SpoonerPlacements(); 427 | 428 | foreach (var o in map.Objects) 429 | { 430 | var pl = new MenyooCompatibility.Placement(); 431 | pl.Type = o.Type == ObjectTypes.Ped ? 1 : o.Type == ObjectTypes.Vehicle ? 2 : 3; 432 | pl.Dynamic = o.Dynamic; 433 | pl.ModelHash = "0x" + o.Hash.ToString("x8"); 434 | pl.PositionRotation = new MenyooCompatibility.PositionRotation() 435 | { 436 | X = o.Position.X, 437 | Y = o.Position.Y, 438 | Z = o.Position.Z, 439 | Pitch = o.Rotation.X, 440 | Roll = o.Rotation.Y, 441 | Yaw = o.Rotation.Z, 442 | }; 443 | menObj.Placement.Add(pl); 444 | } 445 | 446 | var menF = new StreamWriter(path); 447 | menSer.Serialize(menF, menObj); 448 | menF.Close(); 449 | break; 450 | } 451 | } 452 | } 453 | } -------------------------------------------------------------------------------- /Marker.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using GTA; 3 | using GTA.Math; 4 | 5 | namespace MapEditor 6 | { 7 | public class Marker 8 | { 9 | public MarkerType Type; 10 | public Vector3 Position; 11 | public Vector3 Rotation; 12 | public Vector3 Scale; 13 | public Vector3? TeleportTarget; 14 | public int Red; 15 | public int Green; 16 | public int Blue; 17 | public int Alpha; 18 | public bool BobUpAndDown; 19 | public bool RotateToCamera; 20 | public bool OnlyVisibleInEditor; 21 | public int Id; 22 | } 23 | } -------------------------------------------------------------------------------- /MenyooCompatibility.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Xml.Serialization; 3 | using GTA; 4 | 5 | namespace MapEditor 6 | { 7 | public class MenyooCompatibility 8 | { 9 | [XmlRoot(ElementName = "ReferenceCoords")] 10 | public class ReferenceCoords 11 | { 12 | [XmlElement(ElementName = "X")] 13 | public float X { get; set; } 14 | [XmlElement(ElementName = "Y")] 15 | public float Y { get; set; } 16 | [XmlElement(ElementName = "Z")] 17 | public float Z { get; set; } 18 | } 19 | 20 | [XmlRoot(ElementName = "PositionRotation")] 21 | public class PositionRotation 22 | { 23 | [XmlElement(ElementName = "X")] 24 | public float X { get; set; } 25 | [XmlElement(ElementName = "Y")] 26 | public float Y { get; set; } 27 | [XmlElement(ElementName = "Z")] 28 | public float Z { get; set; } 29 | [XmlElement(ElementName = "Pitch")] 30 | public float Pitch { get; set; } 31 | [XmlElement(ElementName = "Roll")] 32 | public float Roll { get; set; } 33 | [XmlElement(ElementName = "Yaw")] 34 | public float Yaw { get; set; } 35 | } 36 | 37 | [XmlRoot(ElementName = "Attachment")] 38 | public class Attachment 39 | { 40 | [XmlAttribute(AttributeName = "isAttached")] 41 | public string IsAttached { get; set; } 42 | } 43 | 44 | [XmlRoot(ElementName = "Placement")] 45 | public class Placement 46 | { 47 | [XmlElement(ElementName = "ModelHash")] 48 | public string ModelHash { get; set; } 49 | [XmlElement(ElementName = "Type")] 50 | public int Type { get; set; } 51 | [XmlElement(ElementName = "Dynamic")] 52 | public bool Dynamic { get; set; } 53 | [XmlElement(ElementName = "HashName")] 54 | public string HashName { get; set; } 55 | [XmlElement(ElementName = "InitialHandle")] 56 | public int InitialHandle { get; set; } 57 | [XmlElement(ElementName = "OpacityLevel")] 58 | public int OpacityLevel { get; set; } 59 | [XmlElement(ElementName = "LodDistance")] 60 | public int LodDistance { get; set; } 61 | [XmlElement(ElementName = "IsVisible")] 62 | public bool IsVisible { get; set; } 63 | [XmlElement(ElementName = "Health")] 64 | public int Health { get; set; } 65 | [XmlElement(ElementName = "IsOnFire")] 66 | public bool IsOnFire { get; set; } 67 | [XmlElement(ElementName = "IsInvincible")] 68 | public bool IsInvincible { get; set; } 69 | [XmlElement(ElementName = "IsBulletProof")] 70 | public bool IsBulletProof { get; set; } 71 | [XmlElement(ElementName = "IsCollisionProof")] 72 | public bool IsCollisionProof { get; set; } 73 | [XmlElement(ElementName = "IsExplosionProof")] 74 | public bool IsExplosionProof { get; set; } 75 | [XmlElement(ElementName = "IsFireProof")] 76 | public bool IsFireProof { get; set; } 77 | [XmlElement(ElementName = "IsMeleeProof")] 78 | public bool IsMeleeProof { get; set; } 79 | [XmlElement(ElementName = "IsOnlyDamagedByPlayer")] 80 | public bool IsOnlyDamagedByPlayer { get; set; } 81 | [XmlElement(ElementName = "PositionRotation")] 82 | public PositionRotation PositionRotation { get; set; } 83 | [XmlElement(ElementName = "Attachment")] 84 | public Attachment Attachment { get; set; } 85 | [XmlElement(ElementName = "PedProperties")] 86 | public PedProperties PedProperties { get; set; } 87 | [XmlElement(ElementName = "VehicleProperties")] 88 | public VehicleProperties VehicleProperties { get; set; } 89 | 90 | public Placement() 91 | { 92 | IsOnlyDamagedByPlayer = false; 93 | IsMeleeProof = false; 94 | IsFireProof = false; 95 | IsExplosionProof = false; 96 | IsCollisionProof = false; 97 | IsBulletProof = false; 98 | IsInvincible = false; 99 | IsOnFire = false; 100 | Health = 200; 101 | IsVisible = true; 102 | LodDistance = 2900; 103 | OpacityLevel = 0xff; 104 | HashName = null; 105 | 106 | } 107 | } 108 | 109 | [XmlRoot(ElementName = "PedProps")] 110 | public class PedProps 111 | { 112 | [XmlElement(ElementName = "_0")] 113 | public string _0 { get; set; } 114 | [XmlElement(ElementName = "_1")] 115 | public string _1 { get; set; } 116 | [XmlElement(ElementName = "_2")] 117 | public string _2 { get; set; } 118 | [XmlElement(ElementName = "_3")] 119 | public string _3 { get; set; } 120 | [XmlElement(ElementName = "_4")] 121 | public string _4 { get; set; } 122 | [XmlElement(ElementName = "_5")] 123 | public string _5 { get; set; } 124 | [XmlElement(ElementName = "_6")] 125 | public string _6 { get; set; } 126 | [XmlElement(ElementName = "_7")] 127 | public string _7 { get; set; } 128 | [XmlElement(ElementName = "_8")] 129 | public string _8 { get; set; } 130 | [XmlElement(ElementName = "_9")] 131 | public string _9 { get; set; } 132 | } 133 | 134 | [XmlRoot(ElementName = "PedComps")] 135 | public class PedComps 136 | { 137 | [XmlElement(ElementName = "_0")] 138 | public string _0 { get; set; } 139 | [XmlElement(ElementName = "_1")] 140 | public string _1 { get; set; } 141 | [XmlElement(ElementName = "_2")] 142 | public string _2 { get; set; } 143 | [XmlElement(ElementName = "_3")] 144 | public string _3 { get; set; } 145 | [XmlElement(ElementName = "_4")] 146 | public string _4 { get; set; } 147 | [XmlElement(ElementName = "_5")] 148 | public string _5 { get; set; } 149 | [XmlElement(ElementName = "_6")] 150 | public string _6 { get; set; } 151 | [XmlElement(ElementName = "_7")] 152 | public string _7 { get; set; } 153 | [XmlElement(ElementName = "_8")] 154 | public string _8 { get; set; } 155 | [XmlElement(ElementName = "_9")] 156 | public string _9 { get; set; } 157 | [XmlElement(ElementName = "_10")] 158 | public string _10 { get; set; } 159 | [XmlElement(ElementName = "_11")] 160 | public string _11 { get; set; } 161 | } 162 | 163 | [XmlRoot(ElementName = "PedProperties")] 164 | public class PedProperties 165 | { 166 | [XmlElement(ElementName = "IsStill")] 167 | public string IsStill { get; set; } 168 | [XmlElement(ElementName = "CurrentWeapon")] 169 | public string CurrentWeapon { get; set; } 170 | [XmlElement(ElementName = "PedProps")] 171 | public PedProps PedProps { get; set; } 172 | [XmlElement(ElementName = "PedComps")] 173 | public PedComps PedComps { get; set; } 174 | [XmlElement(ElementName = "RelationshipGroupAltered")] 175 | public string RelationshipGroupAltered { get; set; } 176 | [XmlElement(ElementName = "RelationshipGroup")] 177 | public string RelationshipGroup { get; set; } 178 | [XmlElement(ElementName = "ScenarioActive")] 179 | public string ScenarioActive { get; set; } 180 | [XmlElement(ElementName = "AnimActive")] 181 | public string AnimActive { get; set; } 182 | } 183 | 184 | [XmlRoot(ElementName = "Colours")] 185 | public class Colours 186 | { 187 | [XmlElement(ElementName = "Primary")] 188 | public string Primary { get; set; } 189 | [XmlElement(ElementName = "Secondary")] 190 | public string Secondary { get; set; } 191 | [XmlElement(ElementName = "Pearl")] 192 | public string Pearl { get; set; } 193 | [XmlElement(ElementName = "Rim")] 194 | public string Rim { get; set; } 195 | [XmlElement(ElementName = "Mod1_a")] 196 | public string Mod1_a { get; set; } 197 | [XmlElement(ElementName = "Mod1_b")] 198 | public string Mod1_b { get; set; } 199 | [XmlElement(ElementName = "Mod1_c")] 200 | public string Mod1_c { get; set; } 201 | [XmlElement(ElementName = "Mod2_a")] 202 | public string Mod2_a { get; set; } 203 | [XmlElement(ElementName = "Mod2_b")] 204 | public string Mod2_b { get; set; } 205 | [XmlElement(ElementName = "IsPrimaryColourCustom")] 206 | public string IsPrimaryColourCustom { get; set; } 207 | [XmlElement(ElementName = "IsSecondaryColourCustom")] 208 | public string IsSecondaryColourCustom { get; set; } 209 | [XmlElement(ElementName = "tyreSmoke_R")] 210 | public string TyreSmoke_R { get; set; } 211 | [XmlElement(ElementName = "tyreSmoke_G")] 212 | public string TyreSmoke_G { get; set; } 213 | [XmlElement(ElementName = "tyreSmoke_B")] 214 | public string TyreSmoke_B { get; set; } 215 | [XmlElement(ElementName = "LrInterior")] 216 | public string LrInterior { get; set; } 217 | [XmlElement(ElementName = "LrDashboard")] 218 | public string LrDashboard { get; set; } 219 | } 220 | 221 | [XmlRoot(ElementName = "Neons")] 222 | public class Neons 223 | { 224 | [XmlElement(ElementName = "Left")] 225 | public string Left { get; set; } 226 | [XmlElement(ElementName = "Right")] 227 | public string Right { get; set; } 228 | [XmlElement(ElementName = "Front")] 229 | public string Front { get; set; } 230 | [XmlElement(ElementName = "Back")] 231 | public string Back { get; set; } 232 | [XmlElement(ElementName = "R")] 233 | public string R { get; set; } 234 | [XmlElement(ElementName = "G")] 235 | public string G { get; set; } 236 | [XmlElement(ElementName = "B")] 237 | public string B { get; set; } 238 | } 239 | 240 | [XmlRoot(ElementName = "DoorsOpen")] 241 | public class DoorsOpen 242 | { 243 | [XmlElement(ElementName = "BackLeftDoor")] 244 | public string BackLeftDoor { get; set; } 245 | [XmlElement(ElementName = "BackRightDoor")] 246 | public string BackRightDoor { get; set; } 247 | [XmlElement(ElementName = "FrontLeftDoor")] 248 | public string FrontLeftDoor { get; set; } 249 | [XmlElement(ElementName = "FrontRightDoor")] 250 | public string FrontRightDoor { get; set; } 251 | [XmlElement(ElementName = "Hood")] 252 | public string Hood { get; set; } 253 | [XmlElement(ElementName = "Trunk")] 254 | public string Trunk { get; set; } 255 | [XmlElement(ElementName = "Trunk2")] 256 | public string Trunk2 { get; set; } 257 | } 258 | 259 | [XmlRoot(ElementName = "DoorsBroken")] 260 | public class DoorsBroken 261 | { 262 | [XmlElement(ElementName = "BackLeftDoor")] 263 | public string BackLeftDoor { get; set; } 264 | [XmlElement(ElementName = "BackRightDoor")] 265 | public string BackRightDoor { get; set; } 266 | [XmlElement(ElementName = "FrontLeftDoor")] 267 | public string FrontLeftDoor { get; set; } 268 | [XmlElement(ElementName = "FrontRightDoor")] 269 | public string FrontRightDoor { get; set; } 270 | [XmlElement(ElementName = "Hood")] 271 | public string Hood { get; set; } 272 | [XmlElement(ElementName = "Trunk")] 273 | public string Trunk { get; set; } 274 | [XmlElement(ElementName = "Trunk2")] 275 | public string Trunk2 { get; set; } 276 | } 277 | 278 | [XmlRoot(ElementName = "TyresBursted")] 279 | public class TyresBursted 280 | { 281 | [XmlElement(ElementName = "FrontLeft")] 282 | public string FrontLeft { get; set; } 283 | [XmlElement(ElementName = "FrontRight")] 284 | public string FrontRight { get; set; } 285 | [XmlElement(ElementName = "_2")] 286 | public string _2 { get; set; } 287 | [XmlElement(ElementName = "_3")] 288 | public string _3 { get; set; } 289 | [XmlElement(ElementName = "BackLeft")] 290 | public string BackLeft { get; set; } 291 | [XmlElement(ElementName = "BackRight")] 292 | public string BackRight { get; set; } 293 | [XmlElement(ElementName = "_6")] 294 | public string _6 { get; set; } 295 | [XmlElement(ElementName = "_7")] 296 | public string _7 { get; set; } 297 | [XmlElement(ElementName = "_8")] 298 | public string _8 { get; set; } 299 | } 300 | 301 | [XmlRoot(ElementName = "Mods")] 302 | public class Mods 303 | { 304 | [XmlElement(ElementName = "_0")] 305 | public string _0 { get; set; } 306 | [XmlElement(ElementName = "_1")] 307 | public string _1 { get; set; } 308 | [XmlElement(ElementName = "_2")] 309 | public string _2 { get; set; } 310 | [XmlElement(ElementName = "_3")] 311 | public string _3 { get; set; } 312 | [XmlElement(ElementName = "_4")] 313 | public string _4 { get; set; } 314 | [XmlElement(ElementName = "_5")] 315 | public string _5 { get; set; } 316 | [XmlElement(ElementName = "_6")] 317 | public string _6 { get; set; } 318 | [XmlElement(ElementName = "_7")] 319 | public string _7 { get; set; } 320 | [XmlElement(ElementName = "_8")] 321 | public string _8 { get; set; } 322 | [XmlElement(ElementName = "_9")] 323 | public string _9 { get; set; } 324 | [XmlElement(ElementName = "_10")] 325 | public string _10 { get; set; } 326 | [XmlElement(ElementName = "_11")] 327 | public string _11 { get; set; } 328 | [XmlElement(ElementName = "_12")] 329 | public string _12 { get; set; } 330 | [XmlElement(ElementName = "_13")] 331 | public string _13 { get; set; } 332 | [XmlElement(ElementName = "_14")] 333 | public string _14 { get; set; } 334 | [XmlElement(ElementName = "_15")] 335 | public string _15 { get; set; } 336 | [XmlElement(ElementName = "_16")] 337 | public string _16 { get; set; } 338 | [XmlElement(ElementName = "_17")] 339 | public string _17 { get; set; } 340 | [XmlElement(ElementName = "_18")] 341 | public string _18 { get; set; } 342 | [XmlElement(ElementName = "_19")] 343 | public string _19 { get; set; } 344 | [XmlElement(ElementName = "_20")] 345 | public string _20 { get; set; } 346 | [XmlElement(ElementName = "_21")] 347 | public string _21 { get; set; } 348 | [XmlElement(ElementName = "_22")] 349 | public string _22 { get; set; } 350 | [XmlElement(ElementName = "_23")] 351 | public string _23 { get; set; } 352 | [XmlElement(ElementName = "_24")] 353 | public string _24 { get; set; } 354 | [XmlElement(ElementName = "_25")] 355 | public string _25 { get; set; } 356 | [XmlElement(ElementName = "_26")] 357 | public string _26 { get; set; } 358 | [XmlElement(ElementName = "_27")] 359 | public string _27 { get; set; } 360 | [XmlElement(ElementName = "_28")] 361 | public string _28 { get; set; } 362 | [XmlElement(ElementName = "_29")] 363 | public string _29 { get; set; } 364 | [XmlElement(ElementName = "_30")] 365 | public string _30 { get; set; } 366 | [XmlElement(ElementName = "_31")] 367 | public string _31 { get; set; } 368 | [XmlElement(ElementName = "_32")] 369 | public string _32 { get; set; } 370 | [XmlElement(ElementName = "_33")] 371 | public string _33 { get; set; } 372 | [XmlElement(ElementName = "_34")] 373 | public string _34 { get; set; } 374 | [XmlElement(ElementName = "_35")] 375 | public string _35 { get; set; } 376 | [XmlElement(ElementName = "_36")] 377 | public string _36 { get; set; } 378 | [XmlElement(ElementName = "_37")] 379 | public string _37 { get; set; } 380 | [XmlElement(ElementName = "_38")] 381 | public string _38 { get; set; } 382 | [XmlElement(ElementName = "_39")] 383 | public string _39 { get; set; } 384 | [XmlElement(ElementName = "_40")] 385 | public string _40 { get; set; } 386 | [XmlElement(ElementName = "_41")] 387 | public string _41 { get; set; } 388 | [XmlElement(ElementName = "_42")] 389 | public string _42 { get; set; } 390 | [XmlElement(ElementName = "_43")] 391 | public string _43 { get; set; } 392 | [XmlElement(ElementName = "_44")] 393 | public string _44 { get; set; } 394 | [XmlElement(ElementName = "_45")] 395 | public string _45 { get; set; } 396 | [XmlElement(ElementName = "_46")] 397 | public string _46 { get; set; } 398 | [XmlElement(ElementName = "_47")] 399 | public string _47 { get; set; } 400 | [XmlElement(ElementName = "_48")] 401 | public string _48 { get; set; } 402 | } 403 | 404 | [XmlRoot(ElementName = "VehicleProperties")] 405 | public class VehicleProperties 406 | { 407 | [XmlElement(ElementName = "Colours")] 408 | public Colours Colours { get; set; } 409 | [XmlElement(ElementName = "Livery")] 410 | public string Livery { get; set; } 411 | [XmlElement(ElementName = "NumberPlateText")] 412 | public string NumberPlateText { get; set; } 413 | [XmlElement(ElementName = "NumberPlateIndex")] 414 | public string NumberPlateIndex { get; set; } 415 | [XmlElement(ElementName = "WheelType")] 416 | public string WheelType { get; set; } 417 | [XmlElement(ElementName = "WheelsInvisible")] 418 | public string WheelsInvisible { get; set; } 419 | [XmlElement(ElementName = "WindowTint")] 420 | public string WindowTint { get; set; } 421 | [XmlElement(ElementName = "BulletProofTyres")] 422 | public string BulletProofTyres { get; set; } 423 | [XmlElement(ElementName = "DirtLevel")] 424 | public string DirtLevel { get; set; } 425 | [XmlElement(ElementName = "PaintFade")] 426 | public string PaintFade { get; set; } 427 | [XmlElement(ElementName = "RoofState")] 428 | public string RoofState { get; set; } 429 | [XmlElement(ElementName = "EngineOn")] 430 | public string EngineOn { get; set; } 431 | [XmlElement(ElementName = "EngineHealth")] 432 | public string EngineHealth { get; set; } 433 | [XmlElement(ElementName = "Neons")] 434 | public Neons Neons { get; set; } 435 | [XmlElement(ElementName = "DoorsOpen")] 436 | public DoorsOpen DoorsOpen { get; set; } 437 | [XmlElement(ElementName = "DoorsBroken")] 438 | public DoorsBroken DoorsBroken { get; set; } 439 | [XmlElement(ElementName = "TyresBursted")] 440 | public TyresBursted TyresBursted { get; set; } 441 | [XmlElement(ElementName = "ModExtras")] 442 | public string ModExtras { get; set; } 443 | [XmlElement(ElementName = "Mods")] 444 | public Mods Mods { get; set; } 445 | } 446 | 447 | [XmlRoot(ElementName = "SpoonerPlacements")] 448 | public class SpoonerPlacements 449 | { 450 | [XmlElement(ElementName = "ClearDatabase")] 451 | public bool ClearDatabase { get; set; } 452 | [XmlElement(ElementName = "ClearWorld")] 453 | public bool ClearWorld { get; set; } 454 | [XmlElement(ElementName = "IPLsToLoad")] 455 | public string IPLsToLoad { get; set; } 456 | [XmlElement(ElementName = "IPLsToRemove")] 457 | public string IPLsToRemove { get; set; } 458 | [XmlElement(ElementName = "ReferenceCoords")] 459 | public ReferenceCoords ReferenceCoords { get; set; } 460 | [XmlElement(ElementName = "Placement")] 461 | public List Placement { get; set; } 462 | 463 | public SpoonerPlacements() 464 | { 465 | Placement = new List(); 466 | var gamePos = Game.Player.Character.Position; 467 | ReferenceCoords = new ReferenceCoords() 468 | { 469 | X = gamePos.X, 470 | Y = gamePos.Y, 471 | Z = gamePos.Z, 472 | }; 473 | 474 | 475 | } 476 | } 477 | } 478 | } -------------------------------------------------------------------------------- /ObjectDatabase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Globalization; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using GTA; 9 | using GTA.Native; 10 | using NativeUI; 11 | 12 | namespace MapEditor 13 | { 14 | public static class ObjectDatabase 15 | { 16 | public static Dictionary MainDb; 17 | 18 | public static List InvalidHashes = new List(); 19 | 20 | public static Dictionary VehicleDb; 21 | 22 | public static Dictionary PedDb; 23 | 24 | public static Dictionary RelationshipDb = new Dictionary(); 25 | 26 | public static int BallasGroup; 27 | 28 | public static int GroveGroup; 29 | 30 | public enum PickupHash 31 | { 32 | Pistol = -105925489, 33 | CombatPistol = -1989692173, 34 | APPIstol = 996550793, 35 | MicroSMG = 496339155, 36 | SMG = 978070226, 37 | AssaultRifle = -214137936, 38 | CarbineRifle = -546236071, 39 | AdvancedRifle = -1296747938, 40 | SawnOffShotgun = -1766583645, 41 | PumpShotgun = -1456120371, 42 | AssaultShotgun = -1835415205, 43 | SniperRifle = -30788308, 44 | HeavySniper = 1765114797, 45 | MachineGun = -2050315855, 46 | CombatMachineGun = -1298986476, 47 | GrenadeLauncher = 779501861, 48 | RPG = 1295434569, 49 | Minigun = 792114228, 50 | Grenade = 1577485217, 51 | StickyBomb = 2081529176, 52 | Molotov = 768803961, 53 | PetrolCan = -962731009, 54 | SmokeGrenade = 483787975, 55 | Knife = 663586612, 56 | Bat = -2115084258, 57 | Hammer = 693539241, 58 | Crowbar = -2027042680, 59 | GolfClub = -1997886297, 60 | Nightstick = 1587637620, 61 | Parachute = 1735599485, 62 | Armour = 1274757841, 63 | Health = -1888453608, 64 | VehiclePistol = -1521817673, 65 | VehicleCombatPistol = -794112265, 66 | VehicleAPPistol = -863291131, 67 | VehicleMicroSMG = -1200951717, 68 | VehicleSMG = -864236261, 69 | VehicleSawnOffShotgun = 772217690, 70 | VehicleGrenade = -1491601256, 71 | VehicleMolotov = -2066319660, 72 | VehicleSmokeGrenade = 1705498857, 73 | VehicleStickyGrenade = 746606563, 74 | VehicleHealth = 160266735, 75 | VehicleArmour = 1125567497, 76 | MoneyCase = -831529621, 77 | MoneyBag = 545862290, 78 | MoneyMediumBag = 341217064, 79 | MoneyPaperBag = 1897726628, 80 | CrateUnfixed = 1852930709, 81 | Package = -2136239332, 82 | BulletAmmo = 1426343849, 83 | MissleAmmo = -107080240, 84 | Camera = -482507216, 85 | Snack = 483577702, 86 | Purse = 513448440, 87 | SecurityCase = -562499202, 88 | Money = -31919185, 89 | Wallet = 1575005502, 90 | } 91 | 92 | internal static void LoadEnumDatabases() 93 | { 94 | VehicleDb = new Dictionary(); 95 | PedDb = new Dictionary(); 96 | 97 | // Vehicles. 98 | foreach (string veh in Enum.GetNames(typeof(VehicleHash))) 99 | { 100 | VehicleHash hash; 101 | Enum.TryParse(veh, out hash); 102 | if(VehicleDb.ContainsKey(veh)) continue; 103 | VehicleDb.Add(veh, (int)hash); 104 | } 105 | 106 | // Peds 107 | foreach (string ped in Enum.GetNames(typeof(PedHash))) 108 | { 109 | PedHash hash; 110 | Enum.TryParse(ped, out hash); 111 | if (PedDb.ContainsKey(ped)) continue; 112 | PedDb.Add(ped, (int)hash); 113 | } 114 | 115 | WriteEnumDatabase(); 116 | } 117 | 118 | internal static void WriteEnumDatabase() 119 | { 120 | StringBuilder sb = new StringBuilder(); 121 | foreach (var pair in PedDb) 122 | { 123 | sb.Append(pair.Key + "=" + pair.Value + Environment.NewLine); 124 | } 125 | File.WriteAllText("scripts\\PedList.ini", sb.ToString()); 126 | 127 | sb = new StringBuilder(); 128 | 129 | foreach (var pair in VehicleDb) 130 | { 131 | sb.Append(pair.Key + "=" + pair.Value + Environment.NewLine); 132 | } 133 | File.WriteAllText("scripts\\VehicleList.ini", sb.ToString()); 134 | } 135 | 136 | internal static void LoadFromFile(string path, ref Dictionary dictToLoadto) 137 | { 138 | dictToLoadto = new Dictionary(); 139 | string[] lines = File.ReadAllLines(path); 140 | foreach (string line in lines) 141 | { 142 | string[] s = line.Split('='); 143 | if(dictToLoadto.ContainsKey(s[0])) continue; 144 | 145 | if (s.Length == 1) 146 | { 147 | dictToLoadto.Add(s[0], new Model(s[0]).Hash); 148 | } 149 | else 150 | { 151 | int val = Convert.ToInt32(s[1], CultureInfo.InvariantCulture); 152 | dictToLoadto.Add(s[0], val); 153 | } 154 | } 155 | } 156 | 157 | internal static void SetupRelationships() 158 | { 159 | foreach (var s in Enum.GetNames(typeof(Relationship))) 160 | { 161 | var hash = (Relationship) Enum.Parse(typeof(Relationship), s); 162 | var group = World.AddRelationshipGroup("MAPEDITOR_" + s); 163 | World.SetRelationshipBetweenGroups(hash, group, Game.Player.Character.RelationshipGroup); 164 | World.SetRelationshipBetweenGroups(hash, Game.Player.Character.RelationshipGroup, group); 165 | RelationshipDb.Add(hash, group); 166 | } 167 | 168 | BallasGroup = World.AddRelationshipGroup("MAPEDITOR_BALLAS"); 169 | GroveGroup = World.AddRelationshipGroup("MAPEDITOR_GROVE"); 170 | 171 | World.SetRelationshipBetweenGroups(Relationship.Hate, BallasGroup, GroveGroup); 172 | World.SetRelationshipBetweenGroups(Relationship.Hate, GroveGroup, BallasGroup); 173 | } 174 | 175 | internal static void LoadInvalidHashes() 176 | { 177 | if(!File.Exists("scripts\\InvalidObjects.ini")) return; 178 | string[] lines = File.ReadAllLines("scripts\\InvalidObjects.ini"); 179 | foreach (string line in lines) 180 | { 181 | int val = Convert.ToInt32(line, CultureInfo.InvariantCulture); 182 | InvalidHashes.Add(val); 183 | } 184 | } 185 | 186 | internal static void SaveInvalidHashes() 187 | { 188 | string output = InvalidHashes.Aggregate("", (current, hash) => current + (hash + "\r\n")); 189 | File.WriteAllText("scripts\\InvalidObjects.ini", output); 190 | } 191 | 192 | internal static void SetPedRelationshipGroup(Ped ped, string group) 193 | { 194 | if (group == "Ballas") 195 | { 196 | ped.RelationshipGroup = BallasGroup; 197 | return; 198 | } 199 | if (group == "Grove") 200 | { 201 | ped.RelationshipGroup = GroveGroup; 202 | return; 203 | } 204 | Relationship outHash; 205 | if(!Enum.TryParse(group, out outHash)) return; 206 | ped.RelationshipGroup = RelationshipDb[outHash]; 207 | } 208 | 209 | internal static Dictionary ScrenarioDatabase = new Dictionary 210 | { 211 | {"Drink Coffee", "WORLD_HUMAN_AA_COFFEE"}, 212 | {"Smoke", "WORLD_HUMAN_AA_SMOKE" }, 213 | {"Smoke 2", "WORLD_HUMAN_SMOKING" }, 214 | {"Binoculars", "WORLD_HUMAN_BINOCULARS"}, 215 | {"Bum", "WORLD_HUMAN_BUM_FREEWAY" }, 216 | {"Cheering", "WORLD_HUMAN_CHEERING" }, 217 | {"Clipboard", "WORLD_HUMAN_CLIPBOARD" }, 218 | {"Drilling", "WORLD_HUMAN_CONST_DRILL"}, 219 | {"Drinking", "WORLD_HUMAN_DRINKING" }, 220 | {"Drug Dealer", "WORLD_HUMAN_DRUG_DEALER"}, 221 | {"Drug Dealer Hard", "WORLD_HUMAN_DRUG_DEALER_HARD" }, 222 | {"Traffic Signaling", "WORLD_HUMAN_CAR_PARK_ATTENDANT"}, 223 | {"Filming", "WORLD_HUMAN_MOBILE_FILM_SHOCKING" }, 224 | {"Leaf Blower", "WORLD_HUMAN_GARDENER_LEAF_BLOWER" }, 225 | {"Golf Player", "WORLD_HUMAN_GOLF_PLAYER" }, 226 | {"Guard Patrol", "WORLD_HUMAN_GUARD_PATROL" }, 227 | {"Hammering", "WORLD_HUMAN_HAMMERING" }, 228 | {"Janitor", "WORLD_HUMAN_JANITOR" }, 229 | {"Musician", "WORLD_HUMAN_MUSICIAN" }, 230 | {"Paparazzi", "WORLD_HUMAN_PAPARAZZI" }, 231 | {"Party", "WORLD_HUMAN_PARTYING" }, 232 | {"Picnic", "WORLD_HUMAN_PICNIC" }, 233 | {"Push Ups", "WORLD_HUMAN_PUSH_UPS"}, 234 | {"Shine Torch", "WORLD_HUMAN_SECURITY_SHINE_TORCH" }, 235 | {"Sunbathe", "WORLD_HUMAN_SUNBATHE" }, 236 | {"Sunbathe Back", "WORLD_HUMAN_SUNBATHE_BACK"}, 237 | {"Tourist", "WORLD_HUMAN_TOURIST_MAP" }, 238 | {"Mechanic", "WORLD_HUMAN_VEHICLE_MECHANIC" }, 239 | {"Welding", "WORLD_HUMAN_WELDING" }, 240 | {"Yoga", "WORLD_HUMAN_YOGA" }, 241 | }; 242 | } 243 | } -------------------------------------------------------------------------------- /ObjectPreview.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using GTA; 5 | using GTA.Native; 6 | using NativeUI; 7 | 8 | namespace MapEditor 9 | { 10 | public static class ObjectPreview 11 | { 12 | private static int globalCounter = 0; 13 | 14 | public static Model LoadObject(int hash) 15 | { 16 | int counter = 0; 17 | var res = UIMenu.GetScreenResolutionMantainRatio(); 18 | 19 | var m = new Model(hash); 20 | 21 | if (!m.IsValid || !m.IsInCdImage) 22 | { 23 | if (!ObjectDatabase.InvalidHashes.Contains(hash)) 24 | { 25 | ObjectDatabase.InvalidHashes.Add(hash); 26 | ObjectDatabase.SaveInvalidHashes(); 27 | } 28 | return null; 29 | } 30 | globalCounter++; 31 | var sc = new Scaleform(0); 32 | sc.Load("instructional_buttons"); 33 | sc.CallFunction("CLEAR_ALL"); 34 | sc.CallFunction("TOGGLE_MOUSE_BUTTONS", 0); 35 | sc.CallFunction("CREATE_CONTAINER"); 36 | sc.CallFunction("SET_DATA_SLOT", 0, "b_50", Translation.Translate("Loading Model")); 37 | sc.CallFunction("DRAW_INSTRUCTIONAL_BUTTONS", -1); 38 | while (!m.IsLoaded && counter < 200) 39 | { 40 | m.Request(); 41 | Script.Yield(); 42 | counter++; 43 | sc.Render2D(); 44 | } 45 | return m; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /PropStreamer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Linq; 6 | using GTA; 7 | using GTA.Math; 8 | using GTA.Native; 9 | using NativeUI; 10 | using Font = GTA.Font; 11 | 12 | namespace MapEditor 13 | { 14 | /// 15 | /// Only create the first 200 objects that are in proximity to the player. 16 | /// 17 | public static class PropStreamer 18 | { 19 | public static int MAX_OBJECTS = 2048; 20 | 21 | public static List UsedModels = new List(); 22 | 23 | public static List MemoryObjects = new List(); 24 | 25 | public static List StreamedInHandles = new List(); 26 | 27 | public static List StaticProps = new List(); 28 | 29 | public static List Vehicles = new List(); 30 | 31 | public static List Peds = new List(); 32 | 33 | public static List Pickups = new List(); 34 | 35 | public static Dictionary Identifications = new Dictionary(); 36 | 37 | public static List Markers = new List(); 38 | 39 | public static Dictionary ActiveScenarios = new Dictionary(); 40 | 41 | public static Dictionary ActiveRelationships = new Dictionary(); 42 | 43 | public static Dictionary ActiveWeapons = new Dictionary(); 44 | 45 | public static List Doors = new List(); 46 | 47 | public static List ActiveSirens = new List(); 48 | 49 | public static int PropCount => StreamedInHandles.Count + MemoryObjects.Count; 50 | 51 | public static int EntityCount => StreamedInHandles.Count + MemoryObjects.Count + Vehicles.Count + Peds.Count; 52 | 53 | public static List RemovedObjects = new List(); 54 | 55 | public static MapMetadata CurrentMapMetadata = new MapMetadata(); 56 | 57 | public static Prop CreateProp(Model model, Vector3 position, Vector3 rotation, bool dynamic, Quaternion q = null, bool force = false, int drawDistance = -1) 58 | { 59 | if (StreamedInHandles.Count >= MAX_OBJECTS) 60 | { 61 | UI.Notify("~r~~h~Map Editor~h~~w~\nYou have reached the prop limit. You cannot place any more props."); 62 | return null; 63 | } 64 | 65 | if (PropCount > 0 && PropCount % 249 == 0) 66 | Script.Wait(100); 67 | 68 | var prop = new Prop(Function.Call(Hash.CREATE_OBJECT_NO_OFFSET, model.Hash, position.X, position.Y, position.Z, true, true, dynamic)); 69 | prop.Rotation = rotation; 70 | StreamedInHandles.Add(prop.Handle); 71 | if (!dynamic) 72 | { 73 | StaticProps.Add(prop.Handle); 74 | prop.FreezePosition = true; 75 | } 76 | if (q != null) 77 | Quaternion.SetEntityQuaternion(prop, q); 78 | prop.Position = position; 79 | if (drawDistance != -1) 80 | prop.LodDistance = drawDistance; 81 | UsedModels.Add(model.Hash); 82 | model.MarkAsNoLongerNeeded(); 83 | return prop; 84 | } 85 | 86 | public static Vehicle CreateVehicle(Model model, Vector3 position, float heading, bool dynamic, Quaternion q = null, int drawDistance = -1) 87 | { 88 | Vehicle veh; 89 | int counter = 0; 90 | do 91 | { 92 | veh = World.CreateVehicle(model, position, heading); 93 | counter++; 94 | } while (veh == null && counter < 2000); 95 | 96 | if (veh == null) 97 | { 98 | UI.Notify("~r~~h~Map Editor~h~~w~~n~I tried very hard, but the vehicle failed to load."); 99 | return null; 100 | } 101 | 102 | Vehicles.Add(veh.Handle); 103 | if (!dynamic) 104 | { 105 | StaticProps.Add(veh.Handle); 106 | veh.FreezePosition = true; 107 | } 108 | if(q != null) 109 | Quaternion.SetEntityQuaternion(veh, q); 110 | if (drawDistance != -1) 111 | veh.LodDistance = drawDistance; 112 | UsedModels.Add(model.Hash); 113 | model.MarkAsNoLongerNeeded(); 114 | return veh; 115 | } 116 | 117 | public static Ped CreatePed(Model model, Vector3 position, float heading, bool dynamic, Quaternion q = null, int drawDistance = -1) 118 | { 119 | var veh = World.CreatePed(model, position, heading); 120 | Peds.Add(veh.Handle); 121 | if (!dynamic) 122 | { 123 | StaticProps.Add(veh.Handle); 124 | veh.FreezePosition = true; 125 | } 126 | if (q != null) 127 | Quaternion.SetEntityQuaternion(veh, q); 128 | if (drawDistance != -1) 129 | veh.LodDistance = drawDistance; 130 | UsedModels.Add(model.Hash); 131 | model.MarkAsNoLongerNeeded(); 132 | return veh; 133 | } 134 | 135 | private static int _pickupIds = 0; 136 | public static DynamicPickup CreatePickup(Model model, Vector3 position, float heading, int amount, bool dynamic, Quaternion q = null) 137 | { 138 | var v_4 = 515; 139 | int newPickup = -1; 140 | 141 | if (Game.Player.Character.IsInRangeOf(position, 30f)) 142 | { 143 | newPickup = Function.Call(Hash.CREATE_PICKUP_ROTATE, model.Hash, position.X, position.Y, 144 | position.Z, 0, 0, heading, v_4, amount, 0, false, 0); 145 | } 146 | 147 | var pcObj = new DynamicPickup(newPickup); 148 | pcObj.Flag = v_4; 149 | pcObj.Amount = amount; 150 | pcObj.RealPosition = position; 151 | if (newPickup != -1) 152 | { 153 | var start = 0; 154 | while (pcObj.ObjectHandle == -1 && start < 20) 155 | { 156 | start++; 157 | Script.Yield(); 158 | } 159 | 160 | pcObj.Dynamic = false; 161 | new Prop(pcObj.ObjectHandle).IsPersistent = true; 162 | 163 | 164 | if (q != null) 165 | Quaternion.SetEntityQuaternion(new Prop(pcObj.ObjectHandle), q); 166 | pcObj.UpdatePos(); 167 | } 168 | 169 | Pickups.Add(pcObj); 170 | pcObj.PickupHash = model.Hash; 171 | pcObj.Timeout = 1; 172 | pcObj.UID = _pickupIds++; 173 | return pcObj; 174 | } 175 | 176 | public static DynamicPickup GetPickup(int objectHandle) 177 | { 178 | DynamicPickup pc = null; 179 | foreach (var pickup in Pickups) 180 | { 181 | if (pickup.ObjectHandle == objectHandle) 182 | { 183 | pc = pickup; 184 | break; 185 | } 186 | } 187 | 188 | return pc; 189 | } 190 | 191 | public static DynamicPickup GetPickupByUID(int uid) 192 | { 193 | DynamicPickup pc = null; 194 | foreach (var pickup in Pickups) 195 | { 196 | if (pickup.UID == uid) 197 | { 198 | pc = pickup; 199 | break; 200 | } 201 | } 202 | 203 | return pc; 204 | } 205 | 206 | public static void RemoveVehicle(int handle) 207 | { 208 | UsedModels.Remove(new Vehicle(handle).Model.Hash); 209 | if(!UsedModels.Contains(new Vehicle(handle).Model.Hash)) 210 | new Vehicle(handle).Model.MarkAsNoLongerNeeded(); 211 | 212 | new Vehicle(handle).Delete(); 213 | if (Vehicles.Contains(handle)) Vehicles.Remove(handle); 214 | if (StaticProps.Contains(handle)) StaticProps.Remove(handle); 215 | } 216 | 217 | public static void RemovePed(int handle) 218 | { 219 | UsedModels.Remove(new Ped(handle).Model.Hash); 220 | if (!UsedModels.Contains(new Ped(handle).Model.Hash)) 221 | new Ped(handle).Model.MarkAsNoLongerNeeded(); 222 | 223 | new Ped(handle).Delete(); 224 | if (Peds.Contains(handle)) Peds.Remove(handle); 225 | if (StaticProps.Contains(handle)) StaticProps.Remove(handle); 226 | } 227 | 228 | public static void RemovePickup(int objectHandle) 229 | { 230 | DynamicPickup pc = null; 231 | foreach (var pickup in Pickups) 232 | { 233 | if (pickup.ObjectHandle == objectHandle) 234 | { 235 | pc = pickup; 236 | pc.Remove(); 237 | break; 238 | } 239 | } 240 | 241 | if (pc != null) Pickups.Remove(pc); 242 | } 243 | 244 | public static bool IsPickup(int entity) 245 | { 246 | return Pickups.Any(pickup => pickup.ObjectHandle == entity); 247 | } 248 | 249 | public static void RemoveEntity(int handle) 250 | { 251 | if (handle != 0 && new Prop(handle).Model != null) 252 | { 253 | UsedModels.Remove(new Prop(handle).Model.Hash); 254 | if (!UsedModels.Contains(new Prop(handle).Model.Hash)) 255 | new Prop(handle).Model.MarkAsNoLongerNeeded(); 256 | } 257 | if (IsPickup(handle)) 258 | { 259 | var ourPickup = GetPickup(handle); 260 | if (Pickups.Contains(ourPickup)) Pickups.Remove(ourPickup); 261 | ourPickup.Remove(); 262 | } 263 | else 264 | { 265 | new Prop(handle).Delete(); 266 | } 267 | if (Peds.Contains(handle)) Peds.Remove(handle); 268 | if (Vehicles.Contains(handle)) Vehicles.Remove(handle); 269 | if (StreamedInHandles.Contains(handle)) StreamedInHandles.Remove(handle); 270 | } 271 | 272 | internal static void AddProp(Prop prop, bool dynamic) 273 | { 274 | if (StreamedInHandles.Count > MAX_OBJECTS) 275 | { 276 | MemoryObjects.Add(new MapObject() {Dynamic = dynamic, Hash = prop.Model.Hash, Position = prop.Position, Quaternion = Quaternion.GetEntityQuaternion(prop), Rotation = prop.Rotation, Type = ObjectTypes.Prop}); 277 | prop.Delete(); 278 | return; 279 | } 280 | StreamedInHandles.Add(prop.Handle); 281 | if(!dynamic) 282 | StaticProps.Add(prop.Handle); 283 | } 284 | 285 | internal static void RemoveProp(Prop prop, bool dynamic) 286 | { 287 | if(StreamedInHandles.Contains(prop.Handle)) StreamedInHandles.Remove(prop.Handle); 288 | if(StaticProps.Contains(prop.Handle)) StaticProps.Remove(prop.Handle); 289 | if(MemoryObjects.Contains(new MapObject() { Dynamic = dynamic, Hash = prop.Model.Hash, Position = prop.Position, Quaternion = Quaternion.GetEntityQuaternion(prop), Rotation = prop.Rotation, Type = ObjectTypes.Prop })) 290 | MemoryObjects.Remove(new MapObject() { Dynamic = dynamic, Hash = prop.Model.Hash, Position = prop.Position, Quaternion = Quaternion.GetEntityQuaternion(prop), Rotation = prop.Rotation, Type = ObjectTypes.Prop }); 291 | } 292 | 293 | public static void RemoveAll() 294 | { 295 | StreamedInHandles.ForEach(i => new Prop(i).Delete()); 296 | StreamedInHandles.Clear(); 297 | MemoryObjects.Clear(); 298 | StaticProps.Clear(); 299 | Vehicles.ForEach(v => new Vehicle(v).Delete()); 300 | Peds.ForEach(v => new Ped(v).Delete()); 301 | Pickups.ForEach(p => p.Remove()); 302 | Vehicles.Clear(); 303 | Peds.Clear(); 304 | Pickups.Clear(); 305 | } 306 | 307 | public static MapObject[] GetAllEntities() 308 | { 309 | List outList = 310 | StreamedInHandles.Select( 311 | handle => 312 | new MapObject() 313 | { 314 | Dynamic = !StaticProps.Contains(handle), 315 | Hash = new Prop(handle).Model.Hash, 316 | Position = new Prop(handle).Position, 317 | Quaternion = Quaternion.GetEntityQuaternion(new Prop(handle)), 318 | Rotation = new Prop(handle).Rotation, 319 | Type = ObjectTypes.Prop, 320 | Door = Doors.Contains(handle), 321 | Id = (Identifications.ContainsKey(handle) && !string.IsNullOrWhiteSpace(Identifications[handle])) ? Identifications[handle] : null, 322 | }).ToList(); 323 | 324 | outList.AddRange(MemoryObjects); 325 | Vehicles.ForEach( 326 | v => 327 | outList.Add(new MapObject() 328 | { 329 | Dynamic = !StaticProps.Contains(v), 330 | Hash = new Vehicle(v).Model.Hash, 331 | Position = new Vehicle(v).Position, 332 | Quaternion = Quaternion.GetEntityQuaternion(new Vehicle(v)), 333 | Rotation = new Vehicle(v).Rotation, 334 | Type = ObjectTypes.Vehicle, 335 | Id = (Identifications.ContainsKey(v) && !string.IsNullOrWhiteSpace(Identifications[v])) ? Identifications[v] : null, 336 | SirensActive = ActiveSirens.Contains(v), 337 | PrimaryColor = (int)new Vehicle(v).PrimaryColor, 338 | SecondaryColor = (int)new Vehicle(v).SecondaryColor, 339 | })); 340 | 341 | Peds.ForEach(v => outList.Add(new MapObject() 342 | { 343 | Dynamic = !StaticProps.Contains(v), 344 | Hash = new Ped(v).Model.Hash, 345 | Position = new Ped(v).Position, 346 | Quaternion = Quaternion.GetEntityQuaternion(new Ped(v)), 347 | Rotation = new Ped(v).Rotation, 348 | Type = ObjectTypes.Ped, 349 | Action = ActiveScenarios[v], 350 | Id = (Identifications.ContainsKey(v) && !string.IsNullOrWhiteSpace(Identifications[v])) ? Identifications[v] : null, 351 | Relationship = ActiveRelationships[v], 352 | Weapon = ActiveWeapons[v], 353 | })); 354 | 355 | Pickups.ForEach(p => outList.Add(new MapObject() 356 | { 357 | Dynamic = p.Dynamic, 358 | Hash = p.PickupHash, 359 | Position = p.RealPosition, 360 | Quaternion = Quaternion.GetEntityQuaternion(new Prop(p.ObjectHandle)), 361 | Rotation = new Prop(p.ObjectHandle).Rotation, 362 | Type = ObjectTypes.Pickup, 363 | Amount = p.Amount, 364 | RespawnTimer = p.Timeout, 365 | Flag = p.Flag, 366 | })); 367 | 368 | return outList.ToArray(); 369 | } 370 | 371 | public static int[] GetAllHandles() 372 | { 373 | List outHandles = new List(); 374 | outHandles.AddRange(StreamedInHandles); 375 | outHandles.AddRange(Vehicles); 376 | outHandles.AddRange(Peds); 377 | outHandles.AddRange(Pickups.Select(p => p.ObjectHandle)); 378 | return outHandles.ToArray(); 379 | } 380 | 381 | [Obsolete("Prop streaming has been disabled since the object limit is 2048.")] 382 | public static void MoveToMemory(Entity i) 383 | { 384 | var obj = new MapObject() 385 | { 386 | Dynamic = !StaticProps.Contains(i.Handle), 387 | Hash = i.Model.Hash, 388 | Position = i.Position, 389 | Quaternion = Quaternion.GetEntityQuaternion(i), 390 | Rotation = i.Rotation, 391 | Type = ObjectTypes.Prop, 392 | }; 393 | MemoryObjects.Add(obj); 394 | StreamedInHandles.Remove(i.Handle); 395 | StaticProps.Remove(i.Handle); 396 | i.Delete(); 397 | } 398 | 399 | [Obsolete("Prop streaming has been disabled since the object limit is 2048.")] 400 | public static void MoveFromMemory(MapObject obj) 401 | { 402 | var prop = obj; 403 | Prop newProp = World.CreateProp(new Model(prop.Hash), prop.Position, prop.Rotation, false, false); 404 | newProp.FreezePosition = !prop.Dynamic; 405 | StreamedInHandles.Add(newProp.Handle); 406 | if (!prop.Dynamic) 407 | { 408 | StaticProps.Add(newProp.Handle); 409 | newProp.FreezePosition = true; 410 | } 411 | if (prop.Quaternion != null) 412 | Quaternion.SetEntityQuaternion(newProp, prop.Quaternion); 413 | newProp.Position = prop.Position; 414 | MemoryObjects.Remove(prop); 415 | } 416 | 417 | 418 | private static bool _justTeleported; 419 | public static void Tick() 420 | { 421 | foreach (MapObject o in RemovedObjects) 422 | { 423 | Prop returnedProp = Function.Call(Hash.GET_CLOSEST_OBJECT_OF_TYPE, o.Position.X, o.Position.Y, o.Position.Z, 1f, o.Hash, 0); 424 | if (returnedProp == null || returnedProp.Handle == 0 || StreamedInHandles.Contains(returnedProp.Handle)) continue; 425 | returnedProp.Delete(); 426 | } 427 | 428 | foreach (Marker marker in Markers) 429 | { 430 | if (!marker.OnlyVisibleInEditor || marker.OnlyVisibleInEditor && MapEditor.IsInFreecam) 431 | Function.Call(Hash.DRAW_MARKER, (int) marker.Type, marker.Position.X, marker.Position.Y, marker.Position.Z, 0f, 0f, 0f, 432 | marker.Rotation.X, marker.Rotation.Y, marker.Rotation.Z, marker.Scale.X, marker.Scale.Y, marker.Scale.Z, 433 | marker.Red, marker.Green, marker.Blue, marker.Alpha, marker.BobUpAndDown, marker.RotateToCamera, 2, false, false, false); 434 | 435 | if (marker.TeleportTarget.HasValue && Game.Player.Character.IsInRangeOf(marker.Position, Math.Max(2f, marker.Scale.X)) && !_justTeleported) 436 | { 437 | if (!Game.Player.Character.IsInVehicle()) 438 | Game.Player.Character.Position = marker.TeleportTarget.Value; 439 | else 440 | Game.Player.Character.CurrentVehicle.Position = marker.TeleportTarget.Value; 441 | _justTeleported = true; 442 | } 443 | } 444 | 445 | if (_justTeleported) 446 | { 447 | var isInRangeOfAny = Markers.Any(m => 448 | { 449 | if (!m.TeleportTarget.HasValue) return false; 450 | return Game.Player.Character.IsInRangeOf(m.Position, Math.Max(2f, m.Scale.X)); 451 | }); 452 | 453 | if (!isInRangeOfAny) _justTeleported = false; 454 | } 455 | 456 | foreach (DynamicPickup pickup in Pickups) 457 | { 458 | pickup.Update(); 459 | } 460 | 461 | /* 462 | if(_lastPos == Game.Player.Character.Position) 463 | return; 464 | _lastPos = Game.Player.Character.Position; 465 | 466 | if (PropCount < MAX_OBJECTS) 467 | { 468 | if (MemoryObjects.Count != 0) 469 | { 470 | for (int i = MemoryObjects.Count - 1; i >= 0; i--) 471 | { 472 | var prop = MemoryObjects[i]; 473 | Prop newProp = World.CreateProp(ObjectPreview.LoadObject(prop.Hash), prop.Position, prop.Rotation, false, false); 474 | newProp.FreezePosition = !prop.Dynamic; 475 | StreamedInHandles.Add(newProp.Handle); 476 | if (!prop.Dynamic) 477 | { 478 | StaticProps.Add(newProp.Handle); 479 | newProp.FreezePosition = true; 480 | } 481 | if (prop.Quaternion != null) 482 | Quaternion.SetEntityQuaternion(newProp, prop.Quaternion); 483 | MemoryObjects.Remove(prop); 484 | } 485 | } 486 | return; 487 | } 488 | 489 | MapObject[] propsToRemove = StreamedInHandles.Select(i => new MapObject() 490 | { 491 | Dynamic = !StaticProps.Contains(i), Hash = new Prop(i).Model.Hash, Position = new Prop(i).Position, Quaternion = Quaternion.GetEntityQuaternion(new Prop(i)), Rotation = new Prop(i).Rotation, Type = ObjectTypes.Prop, Id = i 492 | }).OrderBy(obj => (obj.Position - Game.Player.Character.Position).Length()).ToArray(); 493 | 494 | MapObject[] propsToReAdd = MemoryObjects.OrderBy(obj => (obj.Position - Game.Player.Character.Position).Length()).ToArray(); 495 | 496 | 497 | int lastPropToRemove = 0; 498 | int lastPropToReAdd = 0; 499 | for (int i = 0; i < MAX_OBJECTS; i++) 500 | { 501 | if (propsToReAdd.Length <= lastPropToReAdd) 502 | { 503 | lastPropToRemove = MAX_OBJECTS - lastPropToReAdd; 504 | break; 505 | } 506 | if (propsToRemove.Length <= lastPropToRemove) 507 | { 508 | lastPropToReAdd = MAX_OBJECTS - lastPropToRemove; 509 | break; 510 | } 511 | float readdLen = (propsToReAdd[lastPropToReAdd].Position - Game.Player.Character.Position).Length(); 512 | float removeLen = (propsToRemove[lastPropToRemove].Position - Game.Player.Character.Position).Length(); 513 | if (readdLen < removeLen) 514 | lastPropToReAdd++; 515 | else 516 | lastPropToRemove++; 517 | } 518 | 519 | for (var i = lastPropToRemove; i < propsToRemove.Length; i++) 520 | { 521 | MoveToMemory(new Prop(propsToRemove[i].Id)); 522 | } 523 | 524 | for (int i = 0; i < lastPropToReAdd; i++) // Have to spawn it in 525 | { 526 | var prop = propsToReAdd[i]; 527 | MoveFromMemory(prop); 528 | } 529 | // */ 530 | } 531 | } 532 | } -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MapEditor")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MapEditor")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3ad37808-25ae-41cd-bc45-03d7a3c669ab")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Quaternion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GTA; 3 | using GTA.Native; 4 | 5 | namespace MapEditor 6 | { 7 | public class Quaternion 8 | { 9 | public float X; 10 | public float Y; 11 | public float Z; 12 | public float W; 13 | 14 | public static void SetEntityQuaternion(Entity ent, Quaternion q) 15 | { 16 | Function.Call(Hash.SET_ENTITY_QUATERNION, ent.Handle, q.X, q.Y, q.Z, q.W); 17 | } 18 | 19 | public static void SetEntityQuaternion(Entity ent, GTA.Math.Quaternion q) 20 | { 21 | Function.Call(Hash.SET_ENTITY_QUATERNION, ent.Handle, q.X, q.Y, q.Z, q.W); 22 | } 23 | 24 | public static Quaternion GetEntityQuaternion(Entity e) 25 | { 26 | var xg = new OutputArgument(); 27 | var yg = new OutputArgument(); 28 | var zg = new OutputArgument(); 29 | var wg = new OutputArgument(); 30 | 31 | Function.Call(Hash.GET_ENTITY_QUATERNION, e.Handle, xg, yg, zg, wg); 32 | return new Quaternion() 33 | { 34 | X = xg.GetResult(), 35 | Y = yg.GetResult(), 36 | Z = zg.GetResult(), 37 | W = wg.GetResult() 38 | }; 39 | } 40 | 41 | public static Quaternion RotationYawPitchRoll(float pitch, float roll, float yaw) 42 | { 43 | Quaternion result = new Quaternion(); 44 | 45 | pitch = (float)VectorExtensions.DegToRad(pitch); 46 | roll = (float)VectorExtensions.DegToRad(roll); 47 | yaw = (float)VectorExtensions.DegToRad(yaw); 48 | 49 | float halfRoll = roll*0.5f; 50 | float sinRoll = (float) Math.Sin((double) halfRoll); 51 | float cosRoll = (float) Math.Cos((double) halfRoll); 52 | 53 | float halfPitch = pitch*0.5f; 54 | float sinPitch = (float) Math.Sin((double) halfPitch); 55 | float cosPitch = (float) Math.Cos((double) halfPitch); 56 | 57 | float halfYaw = yaw*0.5f; 58 | float sinYaw = (float) Math.Sin((double) halfYaw); 59 | float cosYaw = (float) Math.Cos((double) halfYaw); 60 | 61 | result.X = (cosYaw*sinPitch*cosRoll) + (sinYaw*cosPitch*sinRoll); 62 | result.Y = (sinYaw*cosPitch*cosRoll) - (cosYaw*sinPitch*sinRoll); 63 | result.Z = (cosYaw*cosPitch*sinRoll) - (sinYaw*sinPitch*cosRoll); 64 | result.W = (cosYaw*cosPitch*cosRoll) + (sinYaw*sinPitch*sinRoll); 65 | 66 | return result; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Settings.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace MapEditor 4 | { 5 | public class Settings 6 | { 7 | public Settings() 8 | { 9 | CameraSensivity = 30; 10 | GamepadCameraSensitivity = 5; 11 | KeyboardMovementSensitivity = 30; 12 | GamepadMovementSensitivity = 15; 13 | Gamepad = true; 14 | InstructionalButtons = true; 15 | CrosshairType = MapEditor.CrosshairType.Crosshair; 16 | PropCounterDisplay = true; 17 | SnapCameraToSelectedObject = true; 18 | ActivationKey = Keys.F7; 19 | AutosaveInterval = 5; 20 | DrawDistance = -1; 21 | LoadScripts = true; 22 | Translation = "Auto"; 23 | OmitInvalidObjects = true; 24 | } 25 | 26 | public string Translation; 27 | public bool Gamepad; 28 | public MapEditor.CrosshairType CrosshairType; 29 | public int CameraSensivity; 30 | public int GamepadCameraSensitivity; 31 | public int KeyboardMovementSensitivity; 32 | public int GamepadMovementSensitivity; 33 | public bool InstructionalButtons; 34 | public bool PropCounterDisplay; 35 | public bool SnapCameraToSelectedObject; 36 | public Keys ActivationKey; 37 | public int AutosaveInterval; 38 | public int DrawDistance; 39 | public bool LoadScripts; 40 | public bool? BoundingBox; 41 | public bool OmitInvalidObjects; 42 | } 43 | } -------------------------------------------------------------------------------- /Translation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Xml.Serialization; 6 | using GTA; 7 | 8 | namespace MapEditor 9 | { 10 | public static class Translation 11 | { 12 | public static List Translations; 13 | public static string CurrentTranslation { get; set; } 14 | 15 | private static TranslationRoot _currenTranslationFile; 16 | private static List _stringList; 17 | 18 | public static void Load(string folder, string translation) 19 | { 20 | Translations = new List(); 21 | XmlSerializer serializer = new XmlSerializer(typeof (TranslationRoot)); 22 | 23 | foreach (var path in Directory.GetFiles(folder, "*.xml")) 24 | { 25 | try 26 | { 27 | using (var stream = System.IO.File.OpenRead(path)) 28 | { 29 | var trans = (TranslationRoot) serializer.Deserialize(stream); 30 | if (trans == null) throw new NullReferenceException(); 31 | trans.SetPath(path); 32 | Translations.Add(trans); 33 | } 34 | } 35 | catch (Exception) { } 36 | } 37 | 38 | SetLanguage(translation); 39 | } 40 | 41 | public static void SetLanguage(string newLanguage) 42 | { 43 | if (newLanguage == "Auto") 44 | { 45 | CurrentTranslation = Game.Language.ToString(); 46 | _currenTranslationFile = Translations.FirstOrDefault(t => t.Language == newLanguage); 47 | } 48 | else 49 | { 50 | CurrentTranslation = newLanguage; 51 | _currenTranslationFile = Translations.FirstOrDefault(t => t.Language == newLanguage); 52 | } 53 | } 54 | 55 | public static void Save() 56 | { 57 | System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof (TranslationRoot)); 58 | foreach (var trans in Translations) 59 | { 60 | using (var stream = File.OpenWrite(trans.GetPath())) 61 | serializer.Serialize(stream, trans); 62 | } 63 | } 64 | 65 | public static string Translate(string original) 66 | { 67 | if (_currenTranslationFile == null) return original; 68 | 69 | if (_currenTranslationFile.Translations.All(ts => ts.Original != original)) 70 | { 71 | _currenTranslationFile.Translations.Add(new StringPair() 72 | { 73 | Original = original, 74 | Translation = original, 75 | }); 76 | Save(); 77 | return original; 78 | } 79 | 80 | return _currenTranslationFile.Translations.First(ts => ts.Original == original).Translation.Replace("~n~", "\n"); 81 | } 82 | } 83 | 84 | public class TranslationRoot 85 | { 86 | private string _path; 87 | 88 | internal void SetPath(string path) 89 | { 90 | _path = path; 91 | } 92 | 93 | internal string GetPath() 94 | { 95 | return _path; 96 | } 97 | 98 | public string Language { get; set; } 99 | public string Translator { get; set; } 100 | 101 | public List Translations { get; set; } 102 | } 103 | 104 | public class StringPair 105 | { 106 | public string Original { get; set; } 107 | public string Translation { get; set; } 108 | } 109 | } -------------------------------------------------------------------------------- /VectorExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GTA; 3 | using GTA.Math; 4 | using GTA.Native; 5 | 6 | namespace MapEditor 7 | { 8 | public static class VectorExtensions 9 | { 10 | public static float Denormalize(this float h) 11 | { 12 | return h < 0f ? h + 360f : h; 13 | } 14 | 15 | public static Vector3 Denormalize(this Vector3 v) 16 | { 17 | return new Vector3(v.X.Denormalize(), v.Y.Denormalize(), v.Z.Denormalize()); 18 | } 19 | 20 | public static float ToRadians(this float val) 21 | { 22 | return (float)(Math.PI / 180) * val; 23 | } 24 | 25 | public static float ToDegrees(this float val) 26 | { 27 | return (float) (val*(180/Math.PI)); 28 | } 29 | 30 | public static Vector3 TransformVector(this Vector3 i, Func method) 31 | { 32 | return new Vector3() 33 | { 34 | X = method(i.X), 35 | Y = method(i.Y), 36 | Z = method(i.Z), 37 | }; 38 | } 39 | 40 | public static Vector3 ToEuler(this GTA.Math.Quaternion q) 41 | { 42 | var pitchYawRoll = new Vector3(); 43 | 44 | double sqw = q.W * q.W; 45 | double sqx = q.X * q.X; 46 | double sqy = q.Y * q.Y; 47 | double sqz = q.Z * q.Z; 48 | 49 | pitchYawRoll.Y = (float)Math.Atan2(2f * q.X * q.W + 2f * q.Y * q.Z, 1 - 2f * (sqz + sqw)); // Yaw 50 | pitchYawRoll.X = (float)Math.Asin(2f * (q.X * q.Z - q.W * q.Y)); // Pitch 51 | pitchYawRoll.Z = (float)Math.Atan2(2f * q.X * q.Y + 2f * q.Z * q.W, 1 - 2f * (sqy + sqz)); 52 | 53 | pitchYawRoll = pitchYawRoll.TransformVector(ToDegrees); 54 | 55 | pitchYawRoll = pitchYawRoll.Denormalize(); 56 | 57 | pitchYawRoll = new Vector3() 58 | { 59 | Y = pitchYawRoll.Y * -1f + 180f, 60 | X = pitchYawRoll.X, 61 | Z = pitchYawRoll.Z, 62 | }; 63 | 64 | return pitchYawRoll; 65 | } 66 | 67 | public static GTA.Math.Quaternion ToQuaternion(this Vector3 vect) 68 | { 69 | vect = new Vector3() 70 | { 71 | X = vect.X.Denormalize() * -1f, 72 | Y = vect.Y.Denormalize() - 180f, 73 | Z = vect.Z.Denormalize() - 180f, 74 | }; 75 | 76 | vect = vect.TransformVector(ToRadians); 77 | 78 | float rollOver2 = vect.Z * 0.5f; 79 | float sinRollOver2 = (float)Math.Sin((double)rollOver2); 80 | float cosRollOver2 = (float)Math.Cos((double)rollOver2); 81 | float pitchOver2 = vect.Y * 0.5f; 82 | float sinPitchOver2 = (float)Math.Sin((double)pitchOver2); 83 | float cosPitchOver2 = (float)Math.Cos((double)pitchOver2); 84 | float yawOver2 = vect.X * 0.5f; // pitch 85 | float sinYawOver2 = (float)Math.Sin((double)yawOver2); 86 | float cosYawOver2 = (float)Math.Cos((double)yawOver2); 87 | GTA.Math.Quaternion result = new GTA.Math.Quaternion(); 88 | result.X = cosYawOver2 * cosPitchOver2 * cosRollOver2 + sinYawOver2 * sinPitchOver2 * sinRollOver2; 89 | result.Y = cosYawOver2 * cosPitchOver2 * sinRollOver2 - sinYawOver2 * sinPitchOver2 * cosRollOver2; 90 | result.Z = cosYawOver2 * sinPitchOver2 * cosRollOver2 + sinYawOver2 * cosPitchOver2 * sinRollOver2; 91 | result.W = sinYawOver2 * cosPitchOver2 * cosRollOver2 - cosYawOver2 * sinPitchOver2 * sinRollOver2; 92 | return result; 93 | } 94 | 95 | public static Vector3 ForwardVector(this Vector3 vector, float yaw) 96 | { 97 | Vector3 right; 98 | float cos = (float)Math.Cos(yaw + Math.PI/2.0f); 99 | right.X = (180f/(float)Math.PI)*cos; 100 | right.Y = 0f; 101 | float sin = (float) Math.Sin(yaw + Math.PI/2.0f); 102 | right.Z = (180f/(float) Math.PI)*sin; 103 | return CrossWith(vector, right); 104 | } 105 | 106 | public static Vector3 CrossWith(Vector3 left, Vector3 right) 107 | { 108 | Vector3 result; 109 | result.X = left.Y*right.Z - left.Z*right.Y; 110 | result.Y = left.Z*right.X - left.X*right.Z; 111 | result.Z = left.X*right.Y - left.Y*right.X; 112 | return result; 113 | } 114 | 115 | public static bool WorldToScreenRel(Vector3 worldCoords, out Vector2 screenCoords) 116 | { 117 | OutputArgument num1 = new OutputArgument(); 118 | OutputArgument num2 = new OutputArgument(); 119 | if (!Function.Call(Hash._WORLD3D_TO_SCREEN2D, worldCoords.X, worldCoords.Y, worldCoords.Z, num1, num2)) 120 | { 121 | screenCoords = new Vector2(); 122 | return false; 123 | } 124 | screenCoords = new Vector2((num1.GetResult() - 0.5f) * 2, (num2.GetResult() - 0.5f) * 2); 125 | return true; 126 | } 127 | 128 | public static Vector3 ScreenRelToWorld(Vector3 camPos, Vector3 camRot, Vector2 coord) 129 | { 130 | var camForward = RotationToDirection(camRot); 131 | var rotUp = camRot + new Vector3(10, 0, 0); 132 | var rotDown = camRot + new Vector3(-10, 0, 0); 133 | var rotLeft = camRot + new Vector3(0, 0, -10); 134 | var rotRight = camRot + new Vector3(0, 0, 10); 135 | 136 | var camRight = RotationToDirection(rotRight) - RotationToDirection(rotLeft); 137 | var camUp = RotationToDirection(rotUp) - RotationToDirection(rotDown); 138 | 139 | var rollRad = -DegToRad(camRot.Y); 140 | 141 | var camRightRoll = camRight * (float)Math.Cos(rollRad) - camUp * (float)Math.Sin(rollRad); 142 | var camUpRoll = camRight * (float)Math.Sin(rollRad) + camUp * (float)Math.Cos(rollRad); 143 | 144 | var point3D = camPos + camForward * 10.0f + camRightRoll + camUpRoll; 145 | Vector2 point2D; 146 | if (!WorldToScreenRel(point3D, out point2D)) return camPos + camForward * 10.0f; 147 | var point3DZero = camPos + camForward * 10.0f; 148 | Vector2 point2DZero; 149 | if (!WorldToScreenRel(point3DZero, out point2DZero)) return camPos + camForward * 10.0f; 150 | 151 | const double eps = 0.001; 152 | if (Math.Abs(point2D.X - point2DZero.X) < eps || Math.Abs(point2D.Y - point2DZero.Y) < eps) return camPos + camForward * 10.0f; 153 | var scaleX = (coord.X - point2DZero.X) / (point2D.X - point2DZero.X); 154 | var scaleY = (coord.Y - point2DZero.Y) / (point2D.Y - point2DZero.Y); 155 | var point3Dret = camPos + camForward * 10.0f + camRightRoll * scaleX + camUpRoll * scaleY; 156 | return point3Dret; 157 | } 158 | 159 | public static Vector3 RotationToDirection(Vector3 rotation) 160 | { 161 | var z = DegToRad(rotation.Z); 162 | var x = DegToRad(rotation.X); 163 | var num = Math.Abs(Math.Cos(x)); 164 | return new Vector3 165 | { 166 | X = (float)(-Math.Sin(z) * num), 167 | Y = (float)(Math.Cos(z) * num), 168 | Z = (float)Math.Sin(x) 169 | }; 170 | } 171 | 172 | public static Vector3 DirectionToRotation(Vector3 direction) 173 | { 174 | direction.Normalize(); 175 | 176 | var x = Math.Atan2(direction.Z, direction.Y); 177 | var y = 0; 178 | var z = -Math.Atan2(direction.X, direction.Y); 179 | 180 | return new Vector3 181 | { 182 | X = (float)RadToDeg(x), 183 | Y = (float)RadToDeg(y), 184 | Z = (float)RadToDeg(z) 185 | }; 186 | } 187 | 188 | public static double DegToRad(double deg) 189 | { 190 | return deg * Math.PI / 180.0; 191 | } 192 | 193 | public static double RadToDeg(double deg) 194 | { 195 | return deg * 180.0 / Math.PI; 196 | } 197 | 198 | public static double BoundRotationDeg(double angleDeg) 199 | { 200 | var twoPi = (int)(angleDeg / 360); 201 | var res = angleDeg - twoPi * 360; 202 | if (res < 0) res += 360; 203 | return res; 204 | } 205 | 206 | public static Vector3 RaycastEverything(Vector2 screenCoord) 207 | { 208 | var camPos = GameplayCamera.Position; 209 | var camRot = GameplayCamera.Rotation; 210 | const float raycastToDist = 100.0f; 211 | const float raycastFromDist = 1f; 212 | 213 | var target3D = ScreenRelToWorld(camPos, camRot, screenCoord); 214 | var source3D = camPos; 215 | 216 | Entity ignoreEntity = Game.Player.Character; 217 | if (Game.Player.Character.IsInVehicle()) 218 | { 219 | ignoreEntity = Game.Player.Character.CurrentVehicle; 220 | } 221 | 222 | var dir = (target3D - source3D); 223 | dir.Normalize(); 224 | var raycastResults = World.Raycast(source3D + dir * raycastFromDist, 225 | source3D + dir * raycastToDist, 226 | (IntersectOptions)(1 | 16 | 256 | 2 | 4 | 8)// | peds + vehicles 227 | , ignoreEntity); 228 | 229 | if (raycastResults.DitHitAnything) 230 | { 231 | return raycastResults.HitCoords; 232 | } 233 | 234 | return camPos + dir * raycastToDist; 235 | } 236 | 237 | public static Vector3 RaycastEverything(Vector2 screenCoord, Vector3 camPos, Vector3 camRot, Entity toIgnore) 238 | { 239 | const float raycastToDist = 100.0f; 240 | const float raycastFromDist = 1f; 241 | 242 | var target3D = ScreenRelToWorld(camPos, camRot, screenCoord); 243 | var source3D = camPos; 244 | 245 | Entity ignoreEntity = toIgnore; 246 | 247 | var dir = (target3D - source3D); 248 | dir.Normalize(); 249 | var raycastResults = World.Raycast(source3D + dir * raycastFromDist, 250 | source3D + dir * raycastToDist, 251 | (IntersectOptions)(1 | 16 | 256 | 2 | 4 | 8)// | peds + vehicles 252 | , ignoreEntity); 253 | 254 | if (raycastResults.DitHitAnything) 255 | { 256 | return raycastResults.HitCoords; 257 | } 258 | 259 | return camPos + dir * raycastToDist; 260 | } 261 | 262 | public static Entity RaycastEntity(Vector2 screenCoord, Vector3 camPos, Vector3 camRot) 263 | { 264 | const float raycastToDist = 100.0f; 265 | const float raycastFromDist = 1f; 266 | 267 | var target3D = ScreenRelToWorld(camPos, camRot, screenCoord); 268 | var source3D = camPos; 269 | 270 | Entity ignoreEntity = Game.Player.Character; 271 | 272 | var dir = (target3D - source3D); 273 | dir.Normalize(); 274 | var raycastResults = World.Raycast(source3D + dir * raycastFromDist, 275 | source3D + dir * raycastToDist, 276 | (IntersectOptions)(1 | 16 | 256 | 2 | 4 | 8)// | peds + vehicles 277 | , ignoreEntity); 278 | 279 | if (raycastResults.DitHitEntity) 280 | { 281 | return raycastResults.HitEntity; 282 | } 283 | 284 | return null; 285 | } 286 | } 287 | } -------------------------------------------------------------------------------- /converter.py: -------------------------------------------------------------------------------- 1 | lines = [] 2 | with open('input.txt', 'r') as inputFile: 3 | lines = inputFile.read().splitlines() 4 | 5 | output = "" 6 | 7 | for line in lines: 8 | line = line.replace(" ", "") 9 | split = line.split('=') 10 | integer = int(split[1], 16) 11 | if(integer > 0x7FFFFFFF): 12 | integer -= 0x100000000 13 | output += split[0] + "=" + str(integer) + "\n" 14 | 15 | with open('output.txt', 'w') as outputFile: 16 | outputFile.write(output) -------------------------------------------------------------------------------- /crosshair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guad/MapEditor/04a2c3216bb0cd40c121e5f8f8305d64811d732f/crosshair.png -------------------------------------------------------------------------------- /crosshair_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guad/MapEditor/04a2c3216bb0cd40c121e5f8f8305d64811d732f/crosshair_blue.png -------------------------------------------------------------------------------- /crosshair_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guad/MapEditor/04a2c3216bb0cd40c121e5f8f8305d64811d732f/crosshair_yellow.png --------------------------------------------------------------------------------