groups.pwn 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399
  1. // Group objects
  2. new Text3D:GroupObjectText[MAX_PLAYERS][MAX_TEXTURE_OBJECTS];
  3. new bool:GroupedObjects[MAX_PLAYERS][MAX_TEXTURE_OBJECTS];
  4. new Float:PivotOffset[MAX_PLAYERS][XYZ];
  5. new Float:LastPivot[MAX_PLAYERS][XYZR];
  6. new Float:LastGroupPosition[MAX_PLAYERS][XYZ];
  7. new bool:PivotReset[MAX_PLAYERS];
  8. public OnFilterScriptInit()
  9. {
  10. for(new i = 0; i < MAX_PLAYERS; i++)
  11. {
  12. for(new j = 0; j < MAX_TEXTURE_OBJECTS; j++)
  13. {
  14. GroupObjectText[i][j] = Text3D:-1;
  15. }
  16. }
  17. #if defined GR_OnFilterScriptInit
  18. GR_OnFilterScriptInit();
  19. #endif
  20. return 1;
  21. }
  22. #if defined _ALS_OnFilterScriptInit
  23. #undef OnFilterScriptInit
  24. #else
  25. #define _ALS_OnFilterScriptInit
  26. #endif
  27. #define OnFilterScriptInit GR_OnFilterScriptInit
  28. #if defined GR_OnFilterScriptInit
  29. forward GR_OnFilterScriptInit();
  30. #endif
  31. public OnPlayerDisconnect(playerid, reason)
  32. {
  33. for(new i = 0; i < MAX_TEXTURE_OBJECTS; i++)
  34. {
  35. if(_:GroupObjectText[playerid][i])
  36. {
  37. DestroyDynamic3DTextLabel(GroupObjectText[playerid][i]);
  38. GroupObjectText[playerid][i] = Text3D:-1;
  39. }
  40. }
  41. ClearGroup(playerid);
  42. #if defined GR_OnPlayerDisconnect
  43. GR_OnPlayerDisconnect(playerid, reason);
  44. #endif
  45. return 1;
  46. }
  47. #if defined _ALS_OnPlayerDisconnect
  48. #undef OnPlayerDisconnect
  49. #else
  50. #define _ALS_OnPlayerDisconnect
  51. #endif
  52. #define OnPlayerDisconnect GR_OnPlayerDisconnect
  53. #if defined GR_OnPlayerDisconnect
  54. forward GR_OnPlayerDisconnect(playerid, reason);
  55. #endif
  56. HideGroupLabels(playerid)
  57. {
  58. for(new i = 0; i < MAX_TEXTURE_OBJECTS; i++)
  59. {
  60. if(_:GroupObjectText[playerid][i])
  61. {
  62. UpdateDynamic3DTextLabelText(GroupObjectText[playerid][i], 0, "");
  63. }
  64. }
  65. }
  66. ShowGroupLabels(playerid)
  67. {
  68. for(new i = 0; i < MAX_TEXTURE_OBJECTS; i++)
  69. {
  70. if(_:GroupObjectText[playerid][i])
  71. {
  72. UpdateDynamic3DTextLabelText(GroupObjectText[playerid][i], 0x7D26CDFF, "Grouped");
  73. }
  74. }
  75. }
  76. public OnUpdateGroup3DText(index)
  77. {
  78. foreach(new i : Player)
  79. {
  80. if(_:GroupObjectText[i][index] != -1)
  81. {
  82. DestroyDynamic3DTextLabel(GroupObjectText[i][index]);
  83. GroupObjectText[i][index] = Text3D:-1;
  84. }
  85. if(TextOption[tShowText] && TextOption[tShowGrouped] && GroupedObjects[i][index])
  86. {
  87. // 3D Text Label (To identify objects)
  88. new line[32];
  89. format(line, sizeof(line), "Grouped");
  90. // Shows the models index
  91. GroupObjectText[i][index] = CreateDynamic3DTextLabel(line, 0x7D26CDFF, ObjectData[index][oX], ObjectData[index][oY], ObjectData[index][oZ]+0.5, TEXT3D_DRAW_DIST, INVALID_PLAYER_ID, INVALID_VEHICLE_ID, 0, -1, -1, i);
  92. Streamer_Update(i);
  93. }
  94. }
  95. return 1;
  96. }
  97. public OnDeleteGroup3DText(index)
  98. {
  99. foreach(new i : Player)
  100. {
  101. if(GroupedObjects[i][index])
  102. {
  103. DestroyDynamic3DTextLabel(GroupObjectText[i][index]);
  104. GroupObjectText[i][index] = Text3D:-1;
  105. }
  106. }
  107. return 1;
  108. }
  109. public OnPlayerSelectDynamicObject(playerid, objectid, modelid, Float:x, Float:y, Float:z)
  110. {
  111. if(GetEditMode(playerid) == EDIT_MODE_GROUP)
  112. {
  113. new Keys,ud,lr,index;
  114. GetPlayerKeys(playerid,Keys,ud,lr);
  115. // Find edit object
  116. foreach(new i : Objects)
  117. {
  118. // Object found
  119. if(ObjectData[i][oID] == objectid)
  120. {
  121. index = i;
  122. break;
  123. }
  124. }
  125. if(!CanSelectObject(playerid, index))
  126. SendClientMessage(playerid, STEALTH_YELLOW, "You can not select objects in this object's group");
  127. else
  128. {
  129. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  130. // Try and add to group
  131. if(Keys & KEY_CTRL_BACK || (InFlyMode(playerid) && (Keys & KEY_SECONDARY_ATTACK)))
  132. {
  133. if(GroupedObjects[playerid][index]) SendClientMessage(playerid, STEALTH_YELLOW, "Object is already in your group selection");
  134. else
  135. {
  136. SendClientMessage(playerid, STEALTH_GREEN, "Object added to your group selection");
  137. GroupedObjects[playerid][index] = true;
  138. OnUpdateGroup3DText(index);
  139. }
  140. }
  141. // Try and remove from group
  142. else if(Keys & KEY_WALK)
  143. {
  144. if(!GroupedObjects[playerid][index]) SendClientMessage(playerid, STEALTH_YELLOW, "Object is not in your group selection");
  145. else
  146. {
  147. SendClientMessage(playerid, STEALTH_GREEN, "Object removed from your group selection");
  148. GroupedObjects[playerid][index] = false;
  149. OnUpdateGroup3DText(index);
  150. }
  151. }
  152. else
  153. {
  154. SendClientMessage(playerid, STEALTH_YELLOW, "Hold the 'H' ('Enter' in /flymode) key and click a object to select it");
  155. SendClientMessage(playerid, STEALTH_YELLOW, "Hold the 'Walk' key and click a object to deselect it");
  156. }
  157. }
  158. }
  159. #if defined GR_OnPlayerSelectDynamicObject
  160. GR_OnPlayerSelectDynamicObject(playerid, objectid, modelid, Float:x, Float:y, Float:z);
  161. #endif
  162. return 1;
  163. }
  164. #if defined _ALS_OnPlayerSelectDynamicObj
  165. #undef OnPlayerSelectDynamicObject
  166. #else
  167. #define _ALS_OnPlayerSelectDynamicObj
  168. #endif
  169. #define OnPlayerSelectDynamicObject GR_OnPlayerSelectDynamicObject
  170. #if defined GR_OnPlayerSelectDynamicObject
  171. forward GR_OnPlayerSelectDynamicObject(playerid, objectid, modelid, Float:x, Float:y, Float:z);
  172. #endif
  173. OnPlayerKeyStateGroupChange(playerid, newkeys, oldkeys)
  174. {
  175. #pragma unused newkeys
  176. if(GetEditMode(playerid) == EDIT_MODE_OBJECTGROUP)
  177. {
  178. if(oldkeys & KEY_WALK)
  179. {
  180. if(PivotReset[playerid] == false) return 1;
  181. SendClientMessage(playerid, STEALTH_GREEN, "Pivot has been set");
  182. PivotReset[playerid] = false;
  183. return 1;
  184. }
  185. }
  186. return 0;
  187. }
  188. OnPlayerEditDOGroup(playerid, objectid, response, Float:x, Float:y, Float:z, Float:rx, Float:ry, Float:rz)
  189. {
  190. #pragma unused objectid
  191. if(response == EDIT_RESPONSE_FINAL)
  192. {
  193. // Get the center (never changes)
  194. new Float:gCenterX, Float:gCenterY, Float:gCenterZ;
  195. GetGroupCenter(playerid, gCenterX, gCenterY, gCenterZ);
  196. new time = GetTickCount();
  197. db_begin_transaction(EditMap);
  198. foreach(new i : Objects)
  199. {
  200. if(GroupedObjects[playerid][i])
  201. {
  202. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  203. new Float:offx, Float:offy, Float:offz;
  204. offx = (ObjectData[i][oX] + (LastGroupPosition[playerid][xPos] - gCenterX)) - PivotOffset[playerid][xPos];
  205. offy = (ObjectData[i][oY] + (LastGroupPosition[playerid][yPos] - gCenterY)) - PivotOffset[playerid][yPos];
  206. offz = (ObjectData[i][oZ] + (LastGroupPosition[playerid][zPos] - gCenterZ)) - PivotOffset[playerid][zPos];
  207. AttachObjectToPoint_GroupEdit(i, offx, offy, offz, x, y, z, rx, ry, rz, ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  208. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  209. SetDynamicObjectRot(ObjectData[i][oID], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  210. sqlite_UpdateObjectPos(i);
  211. UpdateObject3DText(i);
  212. }
  213. }
  214. db_end_transaction(EditMap);
  215. EditingMode[playerid] = false;
  216. SetEditMode(playerid, EDIT_MODE_NONE);
  217. DestroyDynamicObject(PivotObject[playerid]);
  218. }
  219. else if(response == EDIT_RESPONSE_UPDATE)
  220. {
  221. // Get the center (never changes)
  222. new Float:gCenterX, Float:gCenterY, Float:gCenterZ;
  223. GetGroupCenter(playerid, gCenterX, gCenterY, gCenterZ);
  224. new Keys,ud,lr;
  225. GetPlayerKeys(playerid,Keys,ud,lr);
  226. if(Keys & KEY_WALK)
  227. {
  228. if(!PivotReset[playerid])
  229. {
  230. SetDynamicObjectPos(PivotObject[playerid], LastGroupPosition[playerid][xPos], LastGroupPosition[playerid][yPos], LastGroupPosition[playerid][zPos]);
  231. SendClientMessage(playerid, STEALTH_YELLOW, "Save your object before changing the pivot again");
  232. }
  233. else
  234. {
  235. PivotOffset[playerid][xPos] = x - LastPivot[playerid][xPos];
  236. PivotOffset[playerid][yPos] = y - LastPivot[playerid][yPos];
  237. PivotOffset[playerid][zPos] = z - LastPivot[playerid][zPos];
  238. SetDynamicObjectRot(PivotObject[playerid], 0.0, 0.0, 0.0);
  239. }
  240. }
  241. else
  242. {
  243. foreach(new i : Objects)
  244. {
  245. if(GroupedObjects[playerid][i])
  246. {
  247. new Float:offx, Float:offy, Float:offz, Float:newx, Float:newy, Float:newz, Float:newrx, Float:newry, Float:newrz;
  248. offx = (ObjectData[i][oX] + (x - gCenterX)) - PivotOffset[playerid][xPos];
  249. offy = (ObjectData[i][oY] + (y - gCenterY)) - PivotOffset[playerid][yPos];
  250. offz = (ObjectData[i][oZ] + (z - gCenterZ)) - PivotOffset[playerid][zPos];
  251. AttachObjectToPoint_GroupEdit(i, offx, offy, offz, x, y, z, rx, ry, rz, newx, newy, newz, newrx, newry, newrz);
  252. SetDynamicObjectPos(ObjectData[i][oID], newx, newy, newz);
  253. SetDynamicObjectRot(ObjectData[i][oID], newrx, newry, newrz);
  254. }
  255. }
  256. LastGroupPosition[playerid][xPos] = x - PivotOffset[playerid][xPos];
  257. LastGroupPosition[playerid][yPos] = y - PivotOffset[playerid][yPos];
  258. LastGroupPosition[playerid][zPos] = z - PivotOffset[playerid][zPos];
  259. LastPivot[playerid][xPos] = x;
  260. LastPivot[playerid][yPos] = y;
  261. LastPivot[playerid][zPos] = z;
  262. LastPivot[playerid][xPos] = rx;
  263. LastPivot[playerid][yPos] = ry;
  264. LastPivot[playerid][zPos] = rz;
  265. PivotReset[playerid] = false;
  266. }
  267. }
  268. else if(response == EDIT_RESPONSE_CANCEL)
  269. {
  270. foreach(new i : Objects)
  271. {
  272. if(GroupedObjects[playerid][i])
  273. {
  274. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  275. SetDynamicObjectRot(ObjectData[i][oID], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  276. EditingMode[playerid] = false;
  277. SetEditMode(playerid, EDIT_MODE_NONE);
  278. DestroyDynamicObject(PivotObject[playerid]);
  279. }
  280. }
  281. }
  282. return 1;
  283. }
  284. tsfunc ClearGroup(playerid)
  285. {
  286. for(new i = 0; i < MAX_TEXTURE_OBJECTS; i++)
  287. {
  288. GroupedObjects[playerid][i] = false;
  289. OnUpdateGroup3DText(i);
  290. }
  291. return 1;
  292. }
  293. tsfunc GroupUpdate(index)
  294. {
  295. foreach(new i : Player)
  296. {
  297. GroupedObjects[i][index] = false;
  298. }
  299. return 1;
  300. }
  301. #if defined COMPILE_MANGLE
  302. tsfunc GroupRotate(playerid, Float:rx, Float:ry, Float:rz, update = true)
  303. {
  304. new Float:gCenterX, Float:gCenterY, Float:gCenterZ;
  305. GetGroupCenter(playerid, gCenterX, gCenterY, gCenterZ);
  306. // Loop through all objects and perform rotation calculations
  307. db_begin_transaction(EditMap);
  308. foreach(new i : Objects)
  309. {
  310. if(GroupedObjects[playerid][i])
  311. {
  312. AttachObjectToPoint(i, gCenterX, gCenterY, gCenterZ, rx, ry, rz, ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  313. if(update)
  314. {
  315. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  316. SetDynamicObjectRot(ObjectData[i][oID], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  317. UpdateObject3DText(i);
  318. sqlite_UpdateObjectPos(i);
  319. }
  320. }
  321. }
  322. db_end_transaction(EditMap);
  323. }
  324. #endif
  325. YCMD:ginfront(playerid, arg[], help)
  326. {
  327. if(help)
  328. {
  329. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  330. SendClientMessage(playerid, STEALTH_GREEN, "Move all grouped objects in front of the player.");
  331. return 1;
  332. }
  333. MapOpenCheck();
  334. new Float:radius;
  335. if(GetGroupRadius(playerid, radius))
  336. {
  337. radius += 1.0;
  338. new Float:x, Float:y, Float:z, Float:gcx, Float:gcy, Float:gcz, count, line[128];
  339. GetPlayerPos(playerid, x, y, z);
  340. GetPosFaInFrontOfPlayer(playerid, radius, x, y, z, gcz);
  341. GetGroupCenter(playerid, gcx, gcy, gcz);
  342. x -= gcx;
  343. y -= gcy;
  344. z -= gcz;
  345. new time = GetTickCount();
  346. db_begin_transaction(EditMap);
  347. foreach(new i : Objects)
  348. {
  349. if(GroupedObjects[playerid][i])
  350. {
  351. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  352. ObjectData[i][oX] += x;
  353. ObjectData[i][oY] += y;
  354. ObjectData[i][oZ] += z;
  355. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  356. UpdateObject3DText(i);
  357. sqlite_UpdateObjectPos(i);
  358. count++;
  359. }
  360. }
  361. db_end_transaction(EditMap);
  362. format(line, sizeof(line), "Moved %i grouped objects to in front", count);
  363. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  364. SendClientMessage(playerid, STEALTH_GREEN, line);
  365. }
  366. else
  367. {
  368. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  369. SendClientMessage(playerid, STEALTH_YELLOW, "You do not have any objects grouped");
  370. }
  371. return 1;
  372. }
  373. GetGroupRadius(playerid, &Float:radius)
  374. {
  375. new Float:highX = -9999999.0;
  376. new Float:highY = -9999999.0;
  377. new Float:highZ = -9999999.0;
  378. new Float:lowX = 9999999.0;
  379. new Float:lowY = 9999999.0;
  380. new Float:lowZ = 9999999.0;
  381. new count;
  382. foreach(new i : Objects)
  383. {
  384. if(GroupedObjects[playerid][i])
  385. {
  386. if(ObjectData[i][oX] > highX) highX = ObjectData[i][oX];
  387. if(ObjectData[i][oY] > highY) highY = ObjectData[i][oY];
  388. if(ObjectData[i][oZ] > highZ) highZ = ObjectData[i][oZ];
  389. if(ObjectData[i][oX] < lowX) lowX = ObjectData[i][oX];
  390. if(ObjectData[i][oY] < lowY) lowY = ObjectData[i][oY];
  391. if(ObjectData[i][oZ] < lowZ) lowZ = ObjectData[i][oZ];
  392. count++;
  393. }
  394. }
  395. // Not enough objects grouped
  396. if(count < 1) return 0;
  397. radius = floatdiv(getdist3d(highX, highY, highZ, lowX, lowY, lowZ), 2);
  398. return 1;
  399. }
  400. tsfunc GetGroupCenter(playerid, &Float:X, &Float:Y, &Float:Z)
  401. {
  402. new Float:highX = -9999999.0;
  403. new Float:highY = -9999999.0;
  404. new Float:highZ = -9999999.0;
  405. new Float:lowX = 9999999.0;
  406. new Float:lowY = 9999999.0;
  407. new Float:lowZ = 9999999.0;
  408. new count;
  409. foreach(new i : Objects)
  410. {
  411. if(GroupedObjects[playerid][i])
  412. {
  413. if(ObjectData[i][oX] > highX) highX = ObjectData[i][oX];
  414. if(ObjectData[i][oY] > highY) highY = ObjectData[i][oY];
  415. if(ObjectData[i][oZ] > highZ) highZ = ObjectData[i][oZ];
  416. if(ObjectData[i][oX] < lowX) lowX = ObjectData[i][oX];
  417. if(ObjectData[i][oY] < lowY) lowY = ObjectData[i][oY];
  418. if(ObjectData[i][oZ] < lowZ) lowZ = ObjectData[i][oZ];
  419. count++;
  420. }
  421. }
  422. // Not enough objects grouped
  423. if(count < 1) return 0;
  424. X = (highX + lowX) / 2;
  425. Y = (highY + lowY) / 2;
  426. Z = (highZ + lowZ) / 2;
  427. return 1;
  428. }
  429. YCMD:setgroup(playerid, arg[], help)
  430. {
  431. if(help)
  432. {
  433. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  434. SendClientMessage(playerid, STEALTH_GREEN, "Sets the group ID of currently selected objects.");
  435. return 1;
  436. }
  437. MapOpenCheck();
  438. NoEditingMode(playerid);
  439. if (!(0 <= strval(arg) < MAX_GROUPS))
  440. return SendClientMessage(playerid, STEALTH_YELLOW, sprintf("The group id must be from 0 to %d", MAX_GROUPS - 1));
  441. new groupid = strval(arg);
  442. new time = GetTickCount();
  443. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  444. if(PlayerHasGroup(playerid))
  445. {
  446. db_begin_transaction(EditMap);
  447. foreach(new i : Objects)
  448. {
  449. if(GroupedObjects[playerid][i])
  450. {
  451. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  452. ObjectData[i][oGroup] = groupid;
  453. OnUpdateGroup3DText(i);
  454. UpdateObject3DText(i);
  455. sqlite_ObjGroup(i);
  456. }
  457. }
  458. db_end_transaction(EditMap);
  459. new line[128];
  460. format(line, sizeof(line), "Set all objects in your group to group: %i", groupid);
  461. SendClientMessage(playerid, STEALTH_GREEN, line);
  462. }
  463. else SendClientMessage(playerid, STEALTH_YELLOW, "You have no objects to set to group!");
  464. return 1;
  465. }
  466. YCMD:selectgroup(playerid, arg[], help)
  467. {
  468. if(help)
  469. {
  470. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  471. SendClientMessage(playerid, STEALTH_GREEN, "Select a group of objects by group ID.");
  472. return 1;
  473. }
  474. MapOpenCheck();
  475. NoEditingMode(playerid);
  476. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  477. new groupid = strval(arg);
  478. if(!CanSelectGroup(playerid, groupid))
  479. return SendClientMessage(playerid, STEALTH_YELLOW, "You can not select this group");
  480. if(PlayerHasGroup(playerid)) ClearGroup(playerid);
  481. new count;
  482. foreach(new i : Objects)
  483. {
  484. if(ObjectData[i][oGroup] == groupid)
  485. {
  486. GroupedObjects[playerid][i] = true;
  487. OnUpdateGroup3DText(i);
  488. UpdateObject3DText(i);
  489. count++;
  490. }
  491. }
  492. if(count)
  493. {
  494. new line[128];
  495. // Update the Group GUI
  496. UpdatePlayerGSelText(playerid);
  497. format(line, sizeof(line), "Selected group %i Objects: %i", groupid, count);
  498. SendClientMessage(playerid, STEALTH_GREEN, line);
  499. }
  500. else SendClientMessage(playerid, STEALTH_YELLOW, "There are no objects with this group id");
  501. return 1;
  502. }
  503. YCMD:gselmodel(playerid, arg[], help)
  504. {
  505. if(help)
  506. {
  507. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  508. SendClientMessage(playerid, STEALTH_GREEN, "Select a group of objects by model ID.");
  509. return 1;
  510. }
  511. MapOpenCheck();
  512. NoEditingMode(playerid);
  513. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  514. new modelid = strval(arg);
  515. if(PlayerHasGroup(playerid)) ClearGroup(playerid);
  516. new count;
  517. foreach(new i : Objects)
  518. {
  519. if(!CanSelectObject(playerid, i))
  520. continue;
  521. if(ObjectData[i][oModel] == modelid)
  522. {
  523. GroupedObjects[playerid][i] = true;
  524. OnUpdateGroup3DText(i);
  525. UpdateObject3DText(i);
  526. count++;
  527. }
  528. }
  529. if(count)
  530. {
  531. new line[128];
  532. // Update the Group GUI
  533. UpdatePlayerGSelText(playerid);
  534. format(line, sizeof(line), "Selected model %i Objects: %i", modelid, count);
  535. SendClientMessage(playerid, STEALTH_GREEN, line);
  536. }
  537. else SendClientMessage(playerid, STEALTH_YELLOW, "There are no objects with this model id");
  538. return 1;
  539. }
  540. PlayerHasGroup(playerid)
  541. {
  542. foreach(new i : Objects)
  543. {
  544. if(GroupedObjects[playerid][i])
  545. {
  546. return 1;
  547. }
  548. }
  549. return 0;
  550. }
  551. // Edit a group
  552. YCMD:editgroup(playerid, arg[], help)
  553. {
  554. if(help)
  555. {
  556. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  557. SendClientMessage(playerid, STEALTH_GREEN, "Edit currently edited objects simultaneously.");
  558. SendClientMessage(playerid, STEALTH_GREEN, "Hold 'Walk Key' to set the group rotation pivot, you can only do this once per edit.");
  559. return 1;
  560. }
  561. MapOpenCheck();
  562. NoEditingMode(playerid);
  563. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  564. if(PlayerHasGroup(playerid))
  565. {
  566. GetGroupCenter(playerid, LastPivot[playerid][xPos], LastPivot[playerid][yPos], LastPivot[playerid][zPos]);
  567. LastGroupPosition[playerid][xPos] = LastPivot[playerid][xPos];
  568. LastGroupPosition[playerid][yPos] = LastPivot[playerid][yPos];
  569. LastGroupPosition[playerid][zPos] = LastPivot[playerid][zPos];
  570. PivotOffset[playerid][xPos] = 0.0;
  571. PivotOffset[playerid][yPos] = 0.0;
  572. PivotOffset[playerid][zPos] = 0.0;
  573. PivotObject[playerid] = CreateDynamicObject(1974, LastPivot[playerid][xPos], LastPivot[playerid][yPos], LastPivot[playerid][zPos], 0.0, 0.0, 0.0, -1, -1, playerid);
  574. Streamer_SetFloatData(STREAMER_TYPE_OBJECT, PivotObject[playerid], E_STREAMER_DRAW_DISTANCE, 3000.0);
  575. SetDynamicObjectMaterial(PivotObject[playerid], 0, 10765, "airportgnd_sfse", "white", -256);
  576. Streamer_Update(playerid);
  577. EditingMode[playerid] = true;
  578. PivotReset[playerid] = true;
  579. SetEditMode(playerid, EDIT_MODE_OBJECTGROUP);
  580. EditDynamicObject(playerid, PivotObject[playerid]);
  581. SendClientMessage(playerid, STEALTH_GREEN, "Editing your group");
  582. }
  583. else SendClientMessage(playerid, STEALTH_YELLOW, "You must have at least one object grouped");
  584. return 1;
  585. }
  586. YCMD:gmtset(playerid, arg[], help)
  587. {
  588. if(help)
  589. {
  590. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  591. SendClientMessage(playerid, STEALTH_GREEN, "Set the material of all currently selected objects.");
  592. return 1;
  593. }
  594. MapOpenCheck();
  595. EditCheck(playerid);
  596. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  597. if(PlayerHasGroup(playerid))
  598. {
  599. new mindex;
  600. new tref;
  601. new time = GetTickCount();
  602. if(GetMaterials(playerid, arg, mindex, tref))
  603. {
  604. db_begin_transaction(EditMap);
  605. foreach(new i : Objects)
  606. {
  607. if(GroupedObjects[playerid][i])
  608. {
  609. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  610. SetMaterials(i, mindex, tref);
  611. UpdateObjectText(i);
  612. if(ObjectData[i][oAttachedVehicle] > -1)
  613. UpdateAttachedVehicleObject(ObjectData[i][oAttachedVehicle], i, VEHICLE_REATTACH_UPDATE);
  614. }
  615. }
  616. db_end_transaction(EditMap);
  617. SendClientMessage(playerid, STEALTH_GREEN, "Changed All Materials");
  618. foreach(new i : Player)
  619. Streamer_Update(i);
  620. UpdateTextureSlot(playerid, mindex);
  621. }
  622. }
  623. else SendClientMessage(playerid, STEALTH_YELLOW, "You must have at least one object grouped");
  624. return 1;
  625. }
  626. YCMD:gmtcolor(playerid, arg[], help)
  627. {
  628. if(help)
  629. {
  630. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  631. SendClientMessage(playerid, STEALTH_GREEN, "Set the material of all currently selected objects.");
  632. return 1;
  633. }
  634. MapOpenCheck();
  635. EditCheck(playerid);
  636. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  637. if(PlayerHasGroup(playerid))
  638. {
  639. new mindex;
  640. new time = GetTickCount();
  641. new HexColor[12];
  642. sscanf(arg, "is[12]", mindex, HexColor);
  643. if(mindex < 0 || mindex > MAX_MATERIALS - 1)
  644. {
  645. new line[128];
  646. format(line, sizeof(line), "The material selection must be between <0 - %i>", MAX_MATERIALS - 1);
  647. return SendClientMessage(playerid, STEALTH_YELLOW, line);
  648. }
  649. if(IsHexValue(HexColor))
  650. {
  651. new hcolor;
  652. sscanf(HexColor, "h", hcolor);
  653. db_begin_transaction(EditMap);
  654. foreach(new i : Objects)
  655. {
  656. if(GroupedObjects[playerid][i])
  657. {
  658. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  659. ObjectData[i][oColorIndex][mindex] = hcolor;
  660. // Destroy the object
  661. DestroyDynamicObject(ObjectData[i][oID]);
  662. // Re-create object
  663. ObjectData[i][oID] = CreateDynamicObject(ObjectData[i][oModel], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ], MapSetting[mVirtualWorld], MapSetting[mInterior], -1, 300.0);
  664. Streamer_SetFloatData(STREAMER_TYPE_OBJECT, ObjectData[i][oID], E_STREAMER_DRAW_DISTANCE, 300.0);
  665. // Update the materials
  666. UpdateMaterial(i);
  667. UpdateObjectText(i);
  668. if(ObjectData[i][oAttachedVehicle] > -1)
  669. UpdateAttachedVehicleObject(ObjectData[i][oAttachedVehicle], i, VEHICLE_REATTACH_UPDATE);
  670. // Save this material index to the data base
  671. sqlite_SaveColorIndex(i);
  672. }
  673. }
  674. db_end_transaction(EditMap);
  675. SendClientMessage(playerid, STEALTH_GREEN, "Changed All Color");
  676. }
  677. else
  678. {
  679. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  680. SendClientMessage(playerid, STEALTH_YELLOW, "Invalid hex color.");
  681. return 1;
  682. }
  683. foreach(new i : Player)
  684. Streamer_Update(i);
  685. UpdateTextureSlot(playerid, mindex);
  686. }
  687. else SendClientMessage(playerid, STEALTH_YELLOW, "You must have at least one object grouped");
  688. return 1;
  689. }
  690. YCMD:gsel(playerid, arg[], help)
  691. {
  692. if(help)
  693. {
  694. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  695. SendClientMessage(playerid, STEALTH_GREEN, "Select/deselect objects using the cursor.");
  696. SendClientMessage(playerid, STEALTH_YELLOW, "Hold the 'H' ('Enter' in /flymode) key and click a object to select it");
  697. SendClientMessage(playerid, STEALTH_YELLOW, "Hold the 'Walk' key and click a object to deselect it");
  698. return 1;
  699. }
  700. NoEditingMode(playerid);
  701. MapOpenCheck();
  702. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  703. if(Iter_Count(Objects))
  704. {
  705. SetEditMode(playerid, EDIT_MODE_GROUP);
  706. SelectObject(playerid);
  707. SendClientMessage(playerid, STEALTH_GREEN, "Entered Group Selection Mode");
  708. }
  709. else SendClientMessage(playerid, STEALTH_YELLOW, "There are no objects right now");
  710. return 1;
  711. }
  712. YCMD:gadd(playerid, arg[], help)
  713. {
  714. if(help)
  715. {
  716. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  717. SendClientMessage(playerid, STEALTH_GREEN, "Add an object to current selection.");
  718. return 1;
  719. }
  720. MapOpenCheck();
  721. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  722. if(isnull(arg)) return SendClientMessage(playerid, STEALTH_YELLOW, "You must supply an object index to group");
  723. new index, range;
  724. sscanf(arg, "iI(-1)", index, range);
  725. if(range == -1 && !CanSelectObject(playerid, index))
  726. return SendClientMessage(playerid, STEALTH_YELLOW, "You can not select objects in this object's group");
  727. if(index < 0 || (range != -1 && range < 0)) return SendClientMessage(playerid, STEALTH_YELLOW, "Index can not be less than 0");
  728. if(index >= MAX_TEXTURE_OBJECTS || range >= MAX_TEXTURE_OBJECTS)
  729. {
  730. new line[128];
  731. format(line, sizeof(line), "Index can not be greater than %i", MAX_TEXTURE_OBJECTS - 1);
  732. return SendClientMessage(playerid, STEALTH_YELLOW, line);
  733. }
  734. if(range != -1 && range <= index) return SendClientMessage(playerid, STEALTH_YELLOW, "The range can not be more than the index.");
  735. if(range != -1)
  736. {
  737. new count;
  738. for(new i = index; i <= range; i++)
  739. {
  740. if(CanSelectObject(playerid, i) && Iter_Contains(Objects, i) && !GroupedObjects[playerid][i])
  741. {
  742. // Update the Group GUI
  743. UpdatePlayerGSelText(playerid);
  744. GroupedObjects[playerid][i] = true;
  745. OnUpdateGroup3DText(i);
  746. count++;
  747. }
  748. }
  749. if(count) SendClientMessage(playerid, STEALTH_GREEN, sprintf("Added %i objects to your group selection", count));
  750. else SendClientMessage(playerid, STEALTH_YELLOW, "No objects in that range are in your group selection");
  751. }
  752. else
  753. {
  754. if(Iter_Contains(Objects, index))
  755. {
  756. if(GroupedObjects[playerid][index]) SendClientMessage(playerid, STEALTH_YELLOW, "Object is already in your group selection");
  757. else
  758. {
  759. // Update the Group GUI
  760. UpdatePlayerGSelText(playerid);
  761. SendClientMessage(playerid, STEALTH_GREEN, "Object added to your group selection");
  762. GroupedObjects[playerid][index] = true;
  763. OnUpdateGroup3DText(index);
  764. }
  765. }
  766. else SendClientMessage(playerid, STEALTH_YELLOW, "No object exists on that index");
  767. }
  768. return 1;
  769. }
  770. YCMD:grem(playerid, arg[], help)
  771. {
  772. if(help)
  773. {
  774. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  775. SendClientMessage(playerid, STEALTH_GREEN, "Remove an object from your current selection.");
  776. return 1;
  777. }
  778. MapOpenCheck();
  779. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  780. if(isnull(arg)) return SendClientMessage(playerid, STEALTH_YELLOW, "You must supply an object index to group");
  781. new index, range;
  782. sscanf(arg, "iI(-1)", index, range);
  783. if(index < 0 || (range != -1 && range < 0)) return SendClientMessage(playerid, STEALTH_YELLOW, "Index can not be less than 0");
  784. if(index >= MAX_TEXTURE_OBJECTS || range >= MAX_TEXTURE_OBJECTS)
  785. {
  786. new line[128];
  787. format(line, sizeof(line), "Index can not be greater than %i", MAX_TEXTURE_OBJECTS - 1);
  788. return SendClientMessage(playerid, STEALTH_YELLOW, line);
  789. }
  790. if(range != -1 && range <= index) return SendClientMessage(playerid, STEALTH_YELLOW, "The range can not be more than the index.");
  791. if(range != -1)
  792. {
  793. new count;
  794. for(new i = index; i <= range; i++)
  795. {
  796. if(Iter_Contains(Objects, i) && GroupedObjects[playerid][i])
  797. {
  798. // Update the Group GUI
  799. UpdatePlayerGSelText(playerid);
  800. GroupedObjects[playerid][i] = false;
  801. OnUpdateGroup3DText(i);
  802. count++;
  803. }
  804. }
  805. if(count) SendClientMessage(playerid, STEALTH_GREEN, sprintf("Removed %i objects from your group selection", count));
  806. else SendClientMessage(playerid, STEALTH_YELLOW, "No objects in that range are in your group selection");
  807. }
  808. else
  809. {
  810. if(Iter_Contains(Objects, index))
  811. {
  812. if(!GroupedObjects[playerid][index]) SendClientMessage(playerid, STEALTH_YELLOW, "Object is not in your group selection");
  813. else
  814. {
  815. // Update the Group GUI
  816. UpdatePlayerGSelText(playerid);
  817. SendClientMessage(playerid, STEALTH_GREEN, "Object removed from your group selection");
  818. GroupedObjects[playerid][index] = false;
  819. OnUpdateGroup3DText(index);
  820. }
  821. }
  822. else SendClientMessage(playerid, STEALTH_YELLOW, "No object exists on that index");
  823. }
  824. return 1;
  825. }
  826. YCMD:gclear(playerid, arg[], help)
  827. {
  828. if(help)
  829. {
  830. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  831. SendClientMessage(playerid, STEALTH_GREEN, "Clears the current selection.");
  832. return 1;
  833. }
  834. MapOpenCheck();
  835. ClearGroup(playerid);
  836. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  837. SendClientMessage(playerid, STEALTH_GREEN, "Your group selection has been cleared");
  838. // Update the Group GUI
  839. UpdatePlayerGSelText(playerid);
  840. return 1;
  841. }
  842. new bool:tmpgrp[MAX_TEXTURE_OBJECTS];
  843. YCMD:gclone(playerid, arg[], help)
  844. {
  845. if(help)
  846. {
  847. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  848. SendClientMessage(playerid, STEALTH_GREEN, "Clone all currently selected objects.");
  849. return 1;
  850. }
  851. MapOpenCheck();
  852. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  853. new index;
  854. new count;
  855. new time = GetTickCount();
  856. for(new i = 0; i < MAX_TEXTURE_OBJECTS; i++) { tmpgrp[i] = false; }
  857. db_begin_transaction(EditMap);
  858. foreach(new i : Objects)
  859. {
  860. if(GroupedObjects[playerid][i])
  861. {
  862. index = CloneObject(i, time);
  863. GroupedObjects[playerid][i] = false;
  864. tmpgrp[index] = true;
  865. OnUpdateGroup3DText(i);
  866. count++;
  867. }
  868. }
  869. db_end_transaction(EditMap);
  870. // Update grouped objects
  871. for(new i = 0; i < MAX_TEXTURE_OBJECTS; i++)
  872. {
  873. GroupedObjects[playerid][i] = tmpgrp[i];
  874. if(GroupedObjects[playerid][i] == true)
  875. OnUpdateGroup3DText(i);
  876. }
  877. if(count)
  878. {
  879. // Update the Group GUI
  880. UpdatePlayerGSelText(playerid);
  881. new line[128];
  882. format(line, sizeof(line), "Cloned group selection Objects: %i", count);
  883. SendClientMessage(playerid, STEALTH_GREEN, line);
  884. }
  885. else SendClientMessage(playerid, STEALTH_YELLOW, "No group objects to clone");
  886. return 1;
  887. }
  888. YCMD:gdelete(playerid, arg[], help)
  889. {
  890. if(help)
  891. {
  892. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  893. SendClientMessage(playerid, STEALTH_GREEN, "Destroy all currently selected objects.");
  894. return 1;
  895. }
  896. MapOpenCheck();
  897. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  898. new count;
  899. new time = GetTickCount();
  900. db_begin_transaction(EditMap);
  901. foreach(new i : Objects)
  902. {
  903. if(GroupedObjects[playerid][i])
  904. {
  905. SaveUndoInfo(i, UNDO_TYPE_DELETED, time);
  906. i = DeleteDynamicObject(i);
  907. count++;
  908. }
  909. }
  910. db_end_transaction(EditMap);
  911. if(count)
  912. {
  913. // Update the Group GUI
  914. UpdatePlayerGSelText(playerid);
  915. new line[128];
  916. format(line, sizeof(line), "Deleted group selection Objects: %i", count);
  917. SendClientMessage(playerid, STEALTH_GREEN, line);
  918. }
  919. else SendClientMessage(playerid, STEALTH_YELLOW, "No group objects to delete");
  920. return 1;
  921. }
  922. YCMD:gall(playerid, arg[], help)
  923. {
  924. if(help)
  925. {
  926. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  927. SendClientMessage(playerid, STEALTH_GREEN, "Add all loaded objects to current selection.");
  928. return 1;
  929. }
  930. MapOpenCheck();
  931. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  932. new count;
  933. foreach(new i : Objects)
  934. {
  935. if(!CanSelectObject(playerid, i))
  936. continue;
  937. GroupedObjects[playerid][i] = true;
  938. OnUpdateGroup3DText(i);
  939. count++;
  940. }
  941. if(count)
  942. {
  943. // Update the Group GUI
  944. UpdatePlayerGSelText(playerid);
  945. new line[128];
  946. format(line, sizeof(line), "Grouped All Objects", count);
  947. SendClientMessage(playerid, STEALTH_GREEN, line);
  948. }
  949. else SendClientMessage(playerid, STEALTH_YELLOW, "There are no objects to group");
  950. return 1;
  951. }
  952. YCMD:ginvert(playerid, arg[], help)
  953. {
  954. if(help)
  955. {
  956. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  957. SendClientMessage(playerid, STEALTH_GREEN, "Invert all currently selected objects the selected axis.");
  958. return 1;
  959. }
  960. MapOpenCheck();
  961. // NoEditingMode(playerid);
  962. // EditCheck(playerid);
  963. inline Mirror(mxpid, mxdialogid, mxresponse, mxlistitem, string:mxtext[])
  964. {
  965. #pragma unused mxpid, mxdialogid, mxtext
  966. if(!mxresponse)
  967. return 1;
  968. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  969. new Float:gcx, Float:gcy, Float:gcz;
  970. GetGroupCenter(playerid, gcx, gcy, gcz);
  971. new time = GetTickCount();
  972. db_begin_transaction(EditMap);
  973. foreach(new i: Objects)
  974. {
  975. if(GroupedObjects[playerid][i])
  976. {
  977. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  978. switch(mxlistitem) {
  979. case 0: {
  980. ObjectData[i][oX] = -ObjectData[i][oX] + (2.0 * gcx);
  981. // ObjectData[i][oRY] = -ObjectData[i][oRY];
  982. // ObjectData[i][oRZ] = -ObjectData[i][oRZ];
  983. // ObjectData[i][oRY] += 180.0;
  984. // ObjectData[i][oRZ] += 180.0;
  985. // ObjectData[i][oRX] += 180.0;
  986. }
  987. case 1: {
  988. ObjectData[i][oY] = -ObjectData[i][oY] + (2.0 * gcy);
  989. // ObjectData[i][oRX] = -ObjectData[i][oRX];
  990. // ObjectData[i][oRZ] = -ObjectData[i][oRZ];
  991. // ObjectData[i][oRX] += 180.0;
  992. // ObjectData[i][oRZ] += 180.0;
  993. // ObjectData[i][oRY] += 180.0;
  994. }
  995. case 2: {
  996. ObjectData[i][oZ] = -ObjectData[i][oZ] + (2.0 * gcz);
  997. // ObjectData[i][oRX] = -ObjectData[i][oRX];
  998. // ObjectData[i][oRY] = -ObjectData[i][oRY];
  999. // ObjectData[i][oRX] += 180.0;
  1000. // ObjectData[i][oRY] += 180.0;
  1001. // ObjectData[i][oRZ] += 180.0;
  1002. }
  1003. }
  1004. EDIT_FloatGetRemainder(ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  1005. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  1006. SetDynamicObjectRot(ObjectData[i][oID], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  1007. UpdateObject3DText(i);
  1008. sqlite_UpdateObjectPos(i);
  1009. }
  1010. }
  1011. db_end_transaction(EditMap);
  1012. //(Not added to GUI yet)
  1013. // Update the Group GUI
  1014. //UpdatePlayerGSelText(playerid);
  1015. new c = mxlistitem == 0 ? 'X' : mxlistitem == 1 ? 'Y' : 'Z';
  1016. SendClientMessage(playerid, STEALTH_GREEN, sprintf("Inverted all currently selected along the %c axis.", c));
  1017. }
  1018. Dialog_ShowCallback(playerid, using inline Mirror, DIALOG_STYLE_LIST, "Texture Studio - Select Mirror Axis", "X\nY\nZ", "Select", "");
  1019. return 1;
  1020. }
  1021. // Move all grouped objects on X axis
  1022. YCMD:gox(playerid, arg[], help)
  1023. {
  1024. if(help)
  1025. {
  1026. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1027. SendClientMessage(playerid, STEALTH_GREEN, "Move all currently selected objects along the X axis.");
  1028. return 1;
  1029. }
  1030. MapOpenCheck();
  1031. new Float:dist;
  1032. new time = GetTickCount();
  1033. dist = floatstr(arg);
  1034. if(dist == 0) dist = 1.0;
  1035. db_begin_transaction(EditMap);
  1036. foreach(new i : Objects)
  1037. {
  1038. if(GroupedObjects[playerid][i])
  1039. {
  1040. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  1041. ObjectData[i][oX] += dist;
  1042. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  1043. UpdateObject3DText(i);
  1044. sqlite_UpdateObjectPos(i);
  1045. }
  1046. }
  1047. db_end_transaction(EditMap);
  1048. // Update the Group GUI
  1049. UpdatePlayerGSelText(playerid);
  1050. return 1;
  1051. }
  1052. // Move all grouped objects on Y axis
  1053. YCMD:goy(playerid, arg[], help)
  1054. {
  1055. if(help)
  1056. {
  1057. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1058. SendClientMessage(playerid, STEALTH_GREEN, "Move all currently selected objects along the Y axis.");
  1059. return 1;
  1060. }
  1061. MapOpenCheck();
  1062. new Float:dist;
  1063. new time = GetTickCount();
  1064. dist = floatstr(arg);
  1065. if(dist == 0) dist = 1.0;
  1066. db_begin_transaction(EditMap);
  1067. foreach(new i : Objects)
  1068. {
  1069. if(GroupedObjects[playerid][i])
  1070. {
  1071. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  1072. ObjectData[i][oY] += dist;
  1073. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  1074. UpdateObject3DText(i);
  1075. sqlite_UpdateObjectPos(i);
  1076. }
  1077. }
  1078. db_end_transaction(EditMap);
  1079. // Update the Group GUI
  1080. UpdatePlayerGSelText(playerid);
  1081. return 1;
  1082. }
  1083. // Move all grouped objects on Z axis
  1084. YCMD:goz(playerid, arg[], help)
  1085. {
  1086. if(help)
  1087. {
  1088. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1089. SendClientMessage(playerid, STEALTH_GREEN, "Move all currently selected objects along the Z axis.");
  1090. return 1;
  1091. }
  1092. MapOpenCheck();
  1093. new Float:dist;
  1094. new time = GetTickCount();
  1095. dist = floatstr(arg);
  1096. if(dist == 0) dist = 1.0;
  1097. db_begin_transaction(EditMap);
  1098. foreach(new i : Objects)
  1099. {
  1100. if(GroupedObjects[playerid][i])
  1101. {
  1102. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  1103. ObjectData[i][oZ] += dist;
  1104. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  1105. UpdateObject3DText(i);
  1106. sqlite_UpdateObjectPos(i);
  1107. }
  1108. }
  1109. db_end_transaction(EditMap);
  1110. // Update the Group GUI
  1111. UpdatePlayerGSelText(playerid);
  1112. return 1;
  1113. }
  1114. // Rotate map on RX
  1115. YCMD:grx(playerid, arg[], help)
  1116. {
  1117. if(help)
  1118. {
  1119. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1120. SendClientMessage(playerid, STEALTH_GREEN, "Rotate all currently selected objects around the X axis.");
  1121. return 1;
  1122. }
  1123. MapOpenCheck();
  1124. new time = GetTickCount();
  1125. new Float:Delta;
  1126. if(sscanf(arg, "f", Delta))
  1127. {
  1128. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1129. SendClientMessage(playerid, STEALTH_YELLOW, "Usage: /grx <rotation> ");
  1130. return 1;
  1131. }
  1132. // We need to get the map center as the rotation node
  1133. new bool:value, Float:gCenterX, Float:gCenterY, Float:gCenterZ;
  1134. if(PivotPointOn[playerid])
  1135. {
  1136. new bool:hasgroup;
  1137. foreach(new i : Objects)
  1138. {
  1139. if(GroupedObjects[playerid][i])
  1140. {
  1141. gCenterX = PivotPoint[playerid][xPos];
  1142. gCenterY = PivotPoint[playerid][yPos];
  1143. gCenterZ = PivotPoint[playerid][zPos];
  1144. value = true;
  1145. hasgroup = true;
  1146. break;
  1147. }
  1148. }
  1149. if(!hasgroup)
  1150. {
  1151. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1152. SendClientMessage(playerid, STEALTH_YELLOW, "There is not enough objects for this command to work");
  1153. }
  1154. }
  1155. else if(GetGroupCenter(playerid, gCenterX, gCenterY, gCenterZ)) value = true;
  1156. if(value)
  1157. {
  1158. // Loop through all objects and perform rotation calculations
  1159. db_begin_transaction(EditMap);
  1160. foreach(new i : Objects)
  1161. {
  1162. if(GroupedObjects[playerid][i])
  1163. {
  1164. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  1165. AttachObjectToPoint(i, gCenterX, gCenterY, gCenterZ, Delta, 0.0, 0.0, ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  1166. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  1167. SetDynamicObjectRot(ObjectData[i][oID], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  1168. UpdateObject3DText(i);
  1169. sqlite_UpdateObjectPos(i);
  1170. }
  1171. }
  1172. db_end_transaction(EditMap);
  1173. // Update the Group GUI
  1174. UpdatePlayerGSelText(playerid);
  1175. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1176. SendClientMessage(playerid, STEALTH_GREEN, "Group RX rotation complete ");
  1177. }
  1178. else
  1179. {
  1180. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1181. SendClientMessage(playerid, STEALTH_YELLOW, "There is not enough objects for this command to work");
  1182. }
  1183. return 1;
  1184. }
  1185. // Rotate map on RX
  1186. YCMD:gry(playerid, arg[], help)
  1187. {
  1188. if(help)
  1189. {
  1190. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1191. SendClientMessage(playerid, STEALTH_GREEN, "Rotate all currently selected objects around the Y axis.");
  1192. return 1;
  1193. }
  1194. MapOpenCheck();
  1195. new time = GetTickCount();
  1196. new Float:Delta;
  1197. if(sscanf(arg, "f", Delta))
  1198. {
  1199. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1200. SendClientMessage(playerid, STEALTH_YELLOW, "Usage: /gry <rotation> ");
  1201. return 1;
  1202. }
  1203. // We need to get the map center as the rotation node
  1204. new bool:value, Float:gCenterX, Float:gCenterY, Float:gCenterZ;
  1205. if(PivotPointOn[playerid])
  1206. {
  1207. new bool:hasgroup;
  1208. foreach(new i : Objects)
  1209. {
  1210. if(GroupedObjects[playerid][i])
  1211. {
  1212. gCenterX = PivotPoint[playerid][xPos];
  1213. gCenterY = PivotPoint[playerid][yPos];
  1214. gCenterZ = PivotPoint[playerid][zPos];
  1215. value = true;
  1216. hasgroup = true;
  1217. break;
  1218. }
  1219. }
  1220. if(!hasgroup)
  1221. {
  1222. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1223. SendClientMessage(playerid, STEALTH_YELLOW, "There is not enough objects for this command to work");
  1224. }
  1225. }
  1226. else if(GetGroupCenter(playerid, gCenterX, gCenterY, gCenterZ)) value = true;
  1227. if(value)
  1228. {
  1229. // Loop through all objects and perform rotation calculations
  1230. db_begin_transaction(EditMap);
  1231. foreach(new i : Objects)
  1232. {
  1233. if(GroupedObjects[playerid][i])
  1234. {
  1235. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  1236. AttachObjectToPoint(i, gCenterX, gCenterY, gCenterZ, 0.0, Delta, 0.0, ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  1237. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  1238. SetDynamicObjectRot(ObjectData[i][oID], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  1239. UpdateObject3DText(i);
  1240. sqlite_UpdateObjectPos(i);
  1241. }
  1242. }
  1243. db_end_transaction(EditMap);
  1244. // Update the Group GUI
  1245. UpdatePlayerGSelText(playerid);
  1246. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1247. SendClientMessage(playerid, STEALTH_GREEN, "Group RY rotation complete ");
  1248. }
  1249. else
  1250. {
  1251. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1252. SendClientMessage(playerid, STEALTH_YELLOW, "There is not enough objects for this command to work");
  1253. }
  1254. return 1;
  1255. }
  1256. // Rotate map on RX
  1257. YCMD:grz(playerid, arg[], help)
  1258. {
  1259. if(help)
  1260. {
  1261. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1262. SendClientMessage(playerid, STEALTH_GREEN, "Rotate all currently selected objects around the Z axis.");
  1263. return 1;
  1264. }
  1265. MapOpenCheck();
  1266. new time = GetTickCount();
  1267. new Float:Delta;
  1268. if(sscanf(arg, "f", Delta))
  1269. {
  1270. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1271. SendClientMessage(playerid, STEALTH_YELLOW, "Usage: /grz <rotation> ");
  1272. return 1;
  1273. }
  1274. // We need to get the map center as the rotation node
  1275. new bool:value, Float:gCenterX, Float:gCenterY, Float:gCenterZ;
  1276. if(PivotPointOn[playerid])
  1277. {
  1278. new bool:hasgroup;
  1279. foreach(new i : Objects)
  1280. {
  1281. if(GroupedObjects[playerid][i])
  1282. {
  1283. gCenterX = PivotPoint[playerid][xPos];
  1284. gCenterY = PivotPoint[playerid][yPos];
  1285. gCenterZ = PivotPoint[playerid][zPos];
  1286. value = true;
  1287. hasgroup = true;
  1288. break;
  1289. }
  1290. }
  1291. if(!hasgroup)
  1292. {
  1293. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1294. SendClientMessage(playerid, STEALTH_YELLOW, "There is not enough objects for this command to work");
  1295. }
  1296. }
  1297. else if(GetGroupCenter(playerid, gCenterX, gCenterY, gCenterZ)) value = true;
  1298. if(value)
  1299. {
  1300. // Loop through all objects and perform rotation calculations
  1301. db_begin_transaction(EditMap);
  1302. foreach(new i : Objects)
  1303. {
  1304. if(GroupedObjects[playerid][i])
  1305. {
  1306. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  1307. AttachObjectToPoint(i, gCenterX, gCenterY, gCenterZ, 0.0, 0.0, Delta, ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  1308. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  1309. SetDynamicObjectRot(ObjectData[i][oID], ObjectData[i][oRX], ObjectData[i][oRY], ObjectData[i][oRZ]);
  1310. UpdateObject3DText(i);
  1311. sqlite_UpdateObjectPos(i);
  1312. }
  1313. }
  1314. db_end_transaction(EditMap);
  1315. // Update the Group GUI
  1316. UpdatePlayerGSelText(playerid);
  1317. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1318. SendClientMessage(playerid, STEALTH_GREEN, "Group RZ rotation complete ");
  1319. }
  1320. else
  1321. {
  1322. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1323. SendClientMessage(playerid, STEALTH_YELLOW, "There is not enough objects for this command to work");
  1324. }
  1325. return 1;
  1326. }
  1327. YCMD:gdd(playerid, arg[], help)
  1328. {
  1329. if(help)
  1330. {
  1331. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1332. SendClientMessage(playerid, STEALTH_GREEN, "Set a group's draw distance.");
  1333. return 1;
  1334. }
  1335. MapOpenCheck();
  1336. new time = GetTickCount();
  1337. new Float:dd;
  1338. sscanf(arg, "F(300.0)", dd);
  1339. db_begin_transaction(EditMap);
  1340. foreach(new i : Objects)
  1341. {
  1342. if(GroupedObjects[playerid][i])
  1343. {
  1344. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  1345. ObjectData[i][oDD] = dd;
  1346. Streamer_SetFloatData(STREAMER_TYPE_OBJECT, ObjectData[i][oID], E_STREAMER_DRAW_DISTANCE, dd);
  1347. Streamer_SetFloatData(STREAMER_TYPE_OBJECT, ObjectData[i][oID], E_STREAMER_STREAM_DISTANCE, dd);
  1348. sqlite_UpdateObjectDD(i);
  1349. }
  1350. }
  1351. db_end_transaction(EditMap);
  1352. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1353. SendClientMessage(playerid, STEALTH_GREEN, sprintf("Groups draw distance set to %.2f", dd));
  1354. return 1;
  1355. }
  1356. // Export group of objects as an attached object
  1357. YCMD:gaexport(playerid, arg[], help)
  1358. {
  1359. if(help)
  1360. {
  1361. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1362. SendClientMessage(playerid, STEALTH_GREEN, "Export all currently selected objects as an attached object.");
  1363. return 1;
  1364. }
  1365. MapOpenCheck();
  1366. new count;
  1367. foreach(new i : Objects)
  1368. {
  1369. if(GroupedObjects[playerid][i])
  1370. {
  1371. count++;
  1372. break;
  1373. }
  1374. }
  1375. if(count)
  1376. {
  1377. inline CreateAttachExport(cpid, cdialogid, cresponse, clistitem, string:ctext[])
  1378. {
  1379. #pragma unused clistitem, cdialogid, cpid
  1380. if(cresponse)
  1381. {
  1382. if(!isnull(ctext))
  1383. {
  1384. inline DrawDist(dpid, ddialogid, dresponse, dlistitem, string:dtext[])
  1385. {
  1386. #pragma unused dlistitem, ddialogid, dpid
  1387. new Float:dist;
  1388. // Set the drawdistance
  1389. if(dresponse)
  1390. {
  1391. if(sscanf(dtext, "f", dist)) dist = 300.0;
  1392. }
  1393. else dist = 300.0;
  1394. new mapname[128];
  1395. if(strlen(ctext) >= 20)
  1396. {
  1397. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1398. SendClientMessage(playerid, STEALTH_YELLOW, "Choose a shorter map name to export to...");
  1399. return 1;
  1400. }
  1401. format(mapname, sizeof(mapname), "tstudio/AttachExport/%s.txt", ctext);
  1402. if(!fexist(mapname)) AttachExport(playerid, mapname, dist);
  1403. else
  1404. {
  1405. inline OverwriteAttachExport(opid, odialogid, oresponse, olistitem, string:otext[])
  1406. {
  1407. #pragma unused olistitem, odialogid, opid, otext
  1408. if(oresponse)
  1409. {
  1410. fremove(mapname);
  1411. AttachExport(playerid, mapname, dist);
  1412. }
  1413. }
  1414. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1415. SendClientMessage(playerid, STEALTH_YELLOW, "A attached object export with that name already exists");
  1416. Dialog_ShowCallback(playerid, using inline OverwriteAttachExport, DIALOG_STYLE_MSGBOX, "Texture Studio", "Attached file exists overwrite?", "Ok", "Cancel");
  1417. }
  1418. }
  1419. Dialog_ShowCallback(playerid, using inline DrawDist, DIALOG_STYLE_INPUT, "Texture Studio (Map Export)", "Enter the draw distance for objects\n(Note: Default draw distance is 300.0)", "Ok", "Cancel");
  1420. }
  1421. else
  1422. {
  1423. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1424. SendClientMessage(playerid, STEALTH_YELLOW, "You must give your attached export a filename");
  1425. Dialog_ShowCallback(playerid, using inline CreateAttachExport, DIALOG_STYLE_INPUT, "Texture Studio", "Enter attached object export file", "Ok", "Cancel");
  1426. }
  1427. }
  1428. }
  1429. Dialog_ShowCallback(playerid, using inline CreateAttachExport, DIALOG_STYLE_INPUT, "Texture Studio", "Enter attached object export file", "Ok", "Cancel");
  1430. }
  1431. else
  1432. {
  1433. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1434. SendClientMessage(playerid, STEALTH_YELLOW, "No object to save to prefab");
  1435. }
  1436. return 1;
  1437. }
  1438. AttachExport(playerid, mapname[], Float:drawdist)
  1439. {
  1440. // Choose a object as a center node
  1441. inline SelectObjectCenterNode(spid, sdialogid, sresponse, slistitem, string:stext[])
  1442. {
  1443. #pragma unused slistitem, sdialogid, spid
  1444. if(sresponse)
  1445. {
  1446. if(isnull(stext))
  1447. {
  1448. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1449. SendClientMessage(playerid, STEALTH_YELLOW, "You must provide an index as center object");
  1450. Dialog_ShowCallback(playerid, using inline SelectObjectCenterNode, DIALOG_STYLE_INPUT, "Texture Studio", "Enter object index of attach object center", "Ok", "Cancel");
  1451. return 1;
  1452. }
  1453. new centerindex = strval(stext);
  1454. if(centerindex < 0 || centerindex > MAX_TEXTURE_OBJECTS - 1)
  1455. {
  1456. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1457. SendClientMessage(playerid, STEALTH_YELLOW, "Invalid index");
  1458. Dialog_ShowCallback(playerid, using inline SelectObjectCenterNode, DIALOG_STYLE_INPUT, "Texture Studio", "Enter object index of attach object center", "Ok", "Cancel");
  1459. return 1;
  1460. }
  1461. if(!GroupedObjects[playerid][centerindex])
  1462. {
  1463. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1464. SendClientMessage(playerid, STEALTH_YELLOW, "That object is not in your group selection");
  1465. Dialog_ShowCallback(playerid, using inline SelectObjectCenterNode, DIALOG_STYLE_INPUT, "Texture Studio", "Enter object index of attach object center", "Ok", "Cancel");
  1466. return 1;
  1467. }
  1468. // Get Offsets
  1469. new Float:offx, Float:offy, Float:offz;
  1470. offx = ObjectData[centerindex][oX];
  1471. offy = ObjectData[centerindex][oY];
  1472. offz = ObjectData[centerindex][oZ];
  1473. new exportmap[256];
  1474. format(exportmap, sizeof(exportmap), "%s", mapname);
  1475. new mobjects;
  1476. new templine[256];
  1477. new File:f;
  1478. new syncrot = 1;
  1479. f = fopen(exportmap,io_write);
  1480. if(!f) {
  1481. SendClientMessage(playerid, -1, "For some reason this file isn't being created.");
  1482. SendClientMessage(playerid, -1, "Trying to highjack the existing blank.txt instead (temporary solution).");
  1483. f = fopen("tstudio/AttachExport/blank.txt",io_write);
  1484. if(!f) {
  1485. SendClientMessage(playerid, -1, "Failed to highjack...");
  1486. }
  1487. }
  1488. fwrite(f,"//Attached Object Map Exported with Texture Studio By: [uL]Pottus////////////////////////////////////////////////\r\n");
  1489. fwrite(f,"//////////////////////////////////////////////////////////////and Crayder////////////////////////////////////////\r\n");
  1490. fwrite(f,"/////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n");
  1491. // Temp object for setting materials
  1492. format(templine,sizeof(templine),"new centobjid, tmpobjid;\r\n");
  1493. fwrite(f,templine);
  1494. format(templine,sizeof(templine),"centobjid = CreateObject(%i,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f);\r\n",ObjectData[centerindex][oModel],ObjectData[centerindex][oX],ObjectData[centerindex][oY],ObjectData[centerindex][oZ],ObjectData[centerindex][oRX],ObjectData[centerindex][oRY],ObjectData[centerindex][oRZ],drawdist);
  1495. fwrite(f,templine);
  1496. // Write all objects with materials first
  1497. foreach(new i : Objects)
  1498. {
  1499. if(ObjectData[i][oAttachedVehicle] > -1 || !GroupedObjects[playerid][i] || centerindex == i) continue;
  1500. new bool:writeobject;
  1501. // Does the object have materials?
  1502. for(new j = 0; j < MAX_MATERIALS; j++)
  1503. {
  1504. if(ObjectData[i][oTexIndex][j] != 0 || ObjectData[i][oColorIndex][j] != 0 || ObjectData[i][ousetext])
  1505. {
  1506. writeobject = true;
  1507. break;
  1508. }
  1509. }
  1510. // Object had materials we will write them to the export file
  1511. if(writeobject)
  1512. {
  1513. mobjects++;
  1514. // Write the create object line
  1515. format(templine,sizeof(templine),"tmpobjid = CreateObject(%i,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f);\r\n",ObjectData[i][oModel],ObjectData[i][oX],ObjectData[i][oY],ObjectData[i][oZ],ObjectData[i][oRX],ObjectData[i][oRY],ObjectData[i][oRZ],drawdist);
  1516. fwrite(f,templine);
  1517. // Write all materials and colors
  1518. for(new j = 0; j < MAX_MATERIALS; j++)
  1519. {
  1520. // Does object have a texture set?
  1521. if(ObjectData[i][oTexIndex][j] != 0)
  1522. {
  1523. format(templine,sizeof(templine),"SetObjectMaterial(tmpobjid, %i, %i, %c%s%c, %c%s%c, %i);\r\n", j, GetTModel(ObjectData[i][oTexIndex][j]), 34, GetTXDName(ObjectData[i][oTexIndex][j]), 34, 34,GetTextureName(ObjectData[i][oTexIndex][j]), 34, ObjectData[i][oColorIndex][j]);
  1524. fwrite(f,templine);
  1525. }
  1526. // No texture how about a color?
  1527. else if(ObjectData[i][oColorIndex][j] != 0)
  1528. {
  1529. format(templine,sizeof(templine),"SetObjectMaterial(tmpobjid, %i, -1, %c%s%c, %c%s%c, %i);\r\n", j, 34, "none", 34, 34,"none", 34, ObjectData[i][oColorIndex][j]);
  1530. fwrite(f,templine);
  1531. }
  1532. }
  1533. // Write any text
  1534. if(ObjectData[i][ousetext])
  1535. {
  1536. format(templine,sizeof(templine),"SetObjectMaterialText(tmpobjid, %c%s%c, 0, %i, %c%s%c, %i, %i, %i, %i, %i);\r\n",
  1537. 34, ObjectData[i][oObjectText], 34,
  1538. FontSizes[ObjectData[i][oFontSize]],
  1539. 34, FontNames[ObjectData[i][oFontFace]], 34,
  1540. ObjectData[i][oTextFontSize],
  1541. ObjectData[i][oFontBold],
  1542. ObjectData[i][oFontColor],
  1543. ObjectData[i][oBackColor],
  1544. ObjectData[i][oAlignment]
  1545. );
  1546. fwrite(f,templine);
  1547. }
  1548. // Attach the object
  1549. format(templine,sizeof(templine),"AttachObjectToObject(tmpobjid,centobjid,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%i);\r\n",
  1550. offx - ObjectData[i][oX],
  1551. offy - ObjectData[i][oY],
  1552. offz - ObjectData[i][oZ],
  1553. ObjectData[i][oRX],
  1554. ObjectData[i][oRY],
  1555. ObjectData[i][oRZ],
  1556. syncrot
  1557. );
  1558. fwrite(f,templine);
  1559. }
  1560. }
  1561. if(mobjects)
  1562. {
  1563. fwrite(f,"/////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n");
  1564. fwrite(f,"/////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n");
  1565. fwrite(f,"/////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n");
  1566. }
  1567. // We need to write all of the objects that didn't have materials set now
  1568. foreach(new i : Objects)
  1569. {
  1570. if(ObjectData[i][oAttachedVehicle] > -1 || !GroupedObjects[playerid][i] || centerindex == i) continue;
  1571. new bool:skipobject = true;
  1572. // Does the object have materials?
  1573. for(new j = 0; j < MAX_MATERIALS; j++)
  1574. {
  1575. // This object has already been written
  1576. if(ObjectData[i][oTexIndex][j] != 0 || ObjectData[i][oColorIndex][j] != 0 || ObjectData[i][ousetext])
  1577. {
  1578. skipobject = true;
  1579. break;
  1580. }
  1581. }
  1582. // Object has not been exported yet export
  1583. if(!skipobject)
  1584. {
  1585. format(templine,sizeof(templine),"tmpobjid = CreateObject(%i,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f);\r\n",ObjectData[i][oModel],ObjectData[i][oX],ObjectData[i][oY],ObjectData[i][oZ],ObjectData[i][oRX],ObjectData[i][oRY],ObjectData[i][oRZ],drawdist);
  1586. fwrite(f,templine);
  1587. }
  1588. // Attach the object
  1589. format(templine,sizeof(templine),"AttachObjectToObject(tmpobjid,centobjid,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%i);\r\n",
  1590. offx - ObjectData[i][oX],
  1591. offy - ObjectData[i][oY],
  1592. offz - ObjectData[i][oZ],
  1593. ObjectData[i][oRX],
  1594. ObjectData[i][oRY],
  1595. ObjectData[i][oRZ],
  1596. syncrot
  1597. );
  1598. fwrite(f,templine);
  1599. }
  1600. fclose(f);
  1601. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1602. format(templine, sizeof(templine), "Map has been exported to %s", exportmap);
  1603. SendClientMessage(playerid, STEALTH_GREEN, templine);
  1604. }
  1605. }
  1606. Dialog_ShowCallback(playerid, using inline SelectObjectCenterNode, DIALOG_STYLE_INPUT, "Texture Studio", "Enter object index of attach object center", "Ok", "Cancel");
  1607. return 1;
  1608. }
  1609. // Save objects as a prefab data base
  1610. new NewPreFabString[512];
  1611. new DB: PrefabDB;
  1612. YCMD:gprefab(playerid, arg[], help)
  1613. {
  1614. if(help)
  1615. {
  1616. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1617. SendClientMessage(playerid, STEALTH_GREEN, "Save current objects as a prefabricated group.");
  1618. return 1;
  1619. }
  1620. MapOpenCheck();
  1621. new count;
  1622. foreach(new i : Objects)
  1623. {
  1624. if(GroupedObjects[playerid][i])
  1625. {
  1626. count++;
  1627. break;
  1628. }
  1629. }
  1630. if(count)
  1631. {
  1632. inline CreatePrefab(cpid, cdialogid, cresponse, clistitem, string:ctext[])
  1633. {
  1634. #pragma unused clistitem, cdialogid, cpid
  1635. if(cresponse)
  1636. {
  1637. if(!isnull(ctext))
  1638. {
  1639. new mapname[128];
  1640. format(mapname, sizeof(mapname), "tstudio/PreFabs/%s.db", ctext);
  1641. if(!fexist(mapname))
  1642. {
  1643. // Open the map for editing
  1644. PrefabDB = db_open_persistent(mapname);
  1645. if(!NewPreFabString[0])
  1646. {
  1647. strimplode(" ",
  1648. NewPreFabString,
  1649. sizeof(NewPreFabString),
  1650. "CREATE TABLE IF NOT EXISTS `Objects`",
  1651. "(ModelID INTEGER,",
  1652. "xPos REAL,",
  1653. "yPos REAL,",
  1654. "zPos REAL,",
  1655. "rxRot REAL,",
  1656. "ryRot REAL,",
  1657. "rzRot REAL,",
  1658. "TextureIndex TEXT,",
  1659. "ColorIndex TEXT,",
  1660. "usetext INTEGER,",
  1661. "FontFace INTEGER,",
  1662. "FontSize INTEGER,",
  1663. "FontBold INTEGER,",
  1664. "FontColor INTEGER,",
  1665. "BackColor INTEGER,",
  1666. "Alignment INTEGER,",
  1667. "TextFontSize INTEGER,",
  1668. "ObjectText TEXT);"
  1669. );
  1670. }
  1671. db_exec(PrefabDB, NewPreFabString);
  1672. // Prefab extra info
  1673. db_exec(PrefabDB, "CREATE TABLE IF NOT EXISTS `PrefabInfo` (zOFF REAL);");
  1674. db_exec(PrefabDB, "INSERT INTO `PrefabInfo` VALUES(0.0);");
  1675. new Float:x, Float:y, Float:z;
  1676. if(!GetGroupCenter(playerid, x, y, z))
  1677. {
  1678. foreach(new i : Objects)
  1679. {
  1680. if(GroupedObjects[playerid][i])
  1681. {
  1682. x = ObjectData[i][oX];
  1683. y = ObjectData[i][oY];
  1684. z = ObjectData[i][oZ];
  1685. break;
  1686. }
  1687. }
  1688. }
  1689. count = 0;
  1690. db_begin_transaction(EditMap);
  1691. foreach(new i : Objects)
  1692. {
  1693. if(GroupedObjects[playerid][i])
  1694. {
  1695. sqlite_InsertPrefab(i, x, y, z);
  1696. count++;
  1697. }
  1698. }
  1699. db_end_transaction(EditMap);
  1700. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1701. new line[128];
  1702. format(line, sizeof(line), "You have created a prefab Object Count: %i", count);
  1703. SendClientMessage(playerid, STEALTH_GREEN, line);
  1704. db_free_persistent(PrefabDB);
  1705. }
  1706. else
  1707. {
  1708. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1709. SendClientMessage(playerid, STEALTH_YELLOW, "A prefab with that name already exists");
  1710. Dialog_ShowCallback(playerid, using inline CreatePrefab, DIALOG_STYLE_INPUT, "Texture Studio", "Enter a prefab name", "Ok", "Cancel");
  1711. }
  1712. }
  1713. else
  1714. {
  1715. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1716. SendClientMessage(playerid, STEALTH_YELLOW, "You must give your prefab a filename");
  1717. Dialog_ShowCallback(playerid, using inline CreatePrefab, DIALOG_STYLE_INPUT, "Texture Studio", "Enter a prefab name", "Ok", "Cancel");
  1718. }
  1719. }
  1720. }
  1721. Dialog_ShowCallback(playerid, using inline CreatePrefab, DIALOG_STYLE_INPUT, "Texture Studio", "Enter a prefab name", "Ok", "Cancel");
  1722. }
  1723. else
  1724. {
  1725. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1726. SendClientMessage(playerid, STEALTH_YELLOW, "No object to save to prefab");
  1727. }
  1728. return 1;
  1729. }
  1730. // Insert object to prefab DB
  1731. new DBStatement:insertprefabstmt;
  1732. new InsertPrefabString[512];
  1733. sqlite_InsertPrefab(index, Float:x, Float:y, Float:z)
  1734. {
  1735. // Inserts a new index
  1736. if(!InsertPrefabString[0])
  1737. {
  1738. // Prepare query
  1739. strimplode(" ",
  1740. InsertPrefabString,
  1741. sizeof(InsertPrefabString),
  1742. "INSERT INTO `Objects`",
  1743. "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
  1744. );
  1745. }
  1746. insertprefabstmt = db_prepare(PrefabDB, InsertPrefabString);
  1747. // Bind our results
  1748. stmt_bind_value(insertprefabstmt, 0, DB::TYPE_INT, ObjectData[index][oModel]);
  1749. stmt_bind_value(insertprefabstmt, 1, DB::TYPE_FLOAT, ObjectData[index][oX]-x);
  1750. stmt_bind_value(insertprefabstmt, 2, DB::TYPE_FLOAT, ObjectData[index][oY]-y);
  1751. stmt_bind_value(insertprefabstmt, 3, DB::TYPE_FLOAT, ObjectData[index][oZ]-z);
  1752. stmt_bind_value(insertprefabstmt, 4, DB::TYPE_FLOAT, ObjectData[index][oRX]);
  1753. stmt_bind_value(insertprefabstmt, 5, DB::TYPE_FLOAT, ObjectData[index][oRY]);
  1754. stmt_bind_value(insertprefabstmt, 6, DB::TYPE_FLOAT, ObjectData[index][oRZ]);
  1755. stmt_bind_value(insertprefabstmt, 7, DB::TYPE_ARRAY, ObjectData[index][oTexIndex], MAX_MATERIALS);
  1756. stmt_bind_value(insertprefabstmt, 8, DB::TYPE_ARRAY, ObjectData[index][oColorIndex], MAX_MATERIALS);
  1757. stmt_bind_value(insertprefabstmt, 9, DB::TYPE_INT, ObjectData[index][ousetext]);
  1758. stmt_bind_value(insertprefabstmt, 10, DB::TYPE_INT, ObjectData[index][oFontFace]);
  1759. stmt_bind_value(insertprefabstmt, 11, DB::TYPE_INT, ObjectData[index][oFontSize]);
  1760. stmt_bind_value(insertprefabstmt, 12, DB::TYPE_INT, ObjectData[index][oFontBold]);
  1761. stmt_bind_value(insertprefabstmt, 13, DB::TYPE_INT, ObjectData[index][oFontColor]);
  1762. stmt_bind_value(insertprefabstmt, 14, DB::TYPE_INT, ObjectData[index][oBackColor]);
  1763. stmt_bind_value(insertprefabstmt, 15, DB::TYPE_INT, ObjectData[index][oAlignment]);
  1764. stmt_bind_value(insertprefabstmt, 16, DB::TYPE_INT, ObjectData[index][oTextFontSize]);
  1765. stmt_bind_value(insertprefabstmt, 17, DB::TYPE_STRING, ObjectData[index][oObjectText], MAX_TEXT_LENGTH);
  1766. stmt_execute(insertprefabstmt);
  1767. stmt_close(insertprefabstmt);
  1768. }
  1769. YCMD:prefabsetz(playerid, arg[], help)
  1770. {
  1771. if(help)
  1772. {
  1773. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1774. SendClientMessage(playerid, STEALTH_GREEN, "Set prefabricated group Z axis offset.");
  1775. return 1;
  1776. }
  1777. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1778. if(isnull(arg)) ShowPrefabs(playerid);
  1779. else
  1780. {
  1781. new Float:offset;
  1782. new mapname[128];
  1783. if(sscanf(arg, "s[128]f", mapname, offset)) return SendClientMessage(playerid, STEALTH_YELLOW, "You must supply a valid offset value!");
  1784. format(mapname, sizeof(mapname), "tstudio/PreFabs/%s.db", mapname);
  1785. if(fexist(mapname))
  1786. {
  1787. PrefabDB = db_open_persistent(mapname);
  1788. new Query[128];
  1789. format(Query, sizeof(Query), "UPDATE `PrefabInfo` SET `zOFF` = %f;", offset);
  1790. db_exec(PrefabDB, Query);
  1791. db_free_persistent(PrefabDB);
  1792. SendClientMessage(playerid, STEALTH_GREEN, "Updated prefab Z-Load offset");
  1793. }
  1794. else SendClientMessage(playerid, STEALTH_YELLOW, "That prefab does not exist!");
  1795. }
  1796. return 1;
  1797. }
  1798. // Load a prefab specify a filename
  1799. YCMD:prefab(playerid, arg[], help)
  1800. {
  1801. if(help)
  1802. {
  1803. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1804. SendClientMessage(playerid, STEALTH_GREEN, "Load a prefabricated group of objects.");
  1805. return 1;
  1806. }
  1807. MapOpenCheck();
  1808. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1809. if(isnull(arg)) ShowPrefabs(playerid);
  1810. else
  1811. {
  1812. new mapname[128];
  1813. format(mapname, sizeof(mapname), "tstudio/PreFabs/%s.db", arg);
  1814. if(fexist(mapname))
  1815. {
  1816. PrefabDB = db_open_persistent(mapname);
  1817. sqlite_LoadPrefab(playerid);
  1818. db_free_persistent(PrefabDB);
  1819. SendClientMessage(playerid, STEALTH_GREEN, "Prefab loaded and set to your group selection");
  1820. }
  1821. else SendClientMessage(playerid, STEALTH_YELLOW, "That prefab does not exist!");
  1822. }
  1823. return 1;
  1824. }
  1825. YCMD:0group(playerid, arg[], help)
  1826. {
  1827. if(help)
  1828. {
  1829. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1830. SendClientMessage(playerid, STEALTH_GREEN, "Center all currently selected objects to the center of San Andreas.");
  1831. return 1;
  1832. }
  1833. MapOpenCheck();
  1834. new Float:gCenterX, Float:gCenterY, Float:gCenterZ;
  1835. GetGroupCenter(playerid, gCenterX, gCenterY, gCenterZ);
  1836. new bool:hasgroup;
  1837. new time = GetTickCount();
  1838. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  1839. db_begin_transaction(EditMap);
  1840. foreach(new i : Objects)
  1841. {
  1842. if(GroupedObjects[playerid][i])
  1843. {
  1844. SaveUndoInfo(i, UNDO_TYPE_EDIT, time);
  1845. ObjectData[i][oX] -= gCenterX;
  1846. ObjectData[i][oY] -= gCenterY;
  1847. ObjectData[i][oZ] -= gCenterZ;
  1848. SetDynamicObjectPos(ObjectData[i][oID], ObjectData[i][oX], ObjectData[i][oY], ObjectData[i][oZ]);
  1849. sqlite_UpdateObjectPos(i);
  1850. UpdateObject3DText(i);
  1851. hasgroup = true;
  1852. }
  1853. }
  1854. db_end_transaction(EditMap);
  1855. if(hasgroup) SendClientMessage(playerid, STEALTH_GREEN, "Moved grouped objects to 0,0,0");
  1856. else SendClientMessage(playerid, STEALTH_YELLOW, "You don't have any objects grouped");
  1857. return 1;
  1858. }
  1859. tsfunc ShowPrefabs(playerid)
  1860. {
  1861. new dir:dHandle = dir_open("./scriptfiles/tstudio/PreFabs/");
  1862. new item[40], type;
  1863. new line[128];
  1864. new extension[3];
  1865. new fcount;
  1866. new total;
  1867. // Create a load list
  1868. while(dir_list(dHandle, item, type))
  1869. {
  1870. if(type != FM_DIR)
  1871. {
  1872. // We need to check extension
  1873. if(strlen(item) > 3)
  1874. {
  1875. format(extension, sizeof(extension), "%s%s", item[strlen(item) - 2],item[strlen(item) - 1]);
  1876. // File is apparently a db
  1877. if(!strcmp(extension, "db"))
  1878. {
  1879. format(line, sizeof(line), "%s %s,", line, item);
  1880. fcount++;
  1881. total++;
  1882. if(fcount == 8)
  1883. {
  1884. SendClientMessage(playerid, STEALTH_YELLOW, line);
  1885. fcount = 0;
  1886. line = "";
  1887. }
  1888. }
  1889. }
  1890. }
  1891. }
  1892. if(fcount != 0) SendClientMessage(playerid, STEALTH_YELLOW, line);
  1893. if(total > 0)
  1894. {
  1895. format(line, sizeof(line), "Displaying %i prefabs", total);
  1896. SendClientMessage(playerid, STEALTH_GREEN, line);
  1897. }
  1898. else SendClientMessage(playerid, STEALTH_YELLOW, "There are no prefabs to list!");
  1899. return 1;
  1900. }
  1901. static DBStatement:loadprefabstmt;
  1902. // Loads map objects from a data base
  1903. sqlite_LoadPrefab(playerid, offset = true)
  1904. {
  1905. // Load query stmt
  1906. loadprefabstmt = db_prepare(PrefabDB, "SELECT * FROM `Objects`");
  1907. new tmpobject[OBJECTINFO];
  1908. // Bind our results
  1909. stmt_bind_result_field(loadprefabstmt, 0, DB::TYPE_INT, tmpobject[oModel]);
  1910. stmt_bind_result_field(loadprefabstmt, 1, DB::TYPE_FLOAT, tmpobject[oX]);
  1911. stmt_bind_result_field(loadprefabstmt, 2, DB::TYPE_FLOAT, tmpobject[oY]);
  1912. stmt_bind_result_field(loadprefabstmt, 3, DB::TYPE_FLOAT, tmpobject[oZ]);
  1913. stmt_bind_result_field(loadprefabstmt, 4, DB::TYPE_FLOAT, tmpobject[oRX]);
  1914. stmt_bind_result_field(loadprefabstmt, 5, DB::TYPE_FLOAT, tmpobject[oRY]);
  1915. stmt_bind_result_field(loadprefabstmt, 6, DB::TYPE_FLOAT, tmpobject[oRZ]);
  1916. stmt_bind_result_field(loadprefabstmt, 7, DB::TYPE_ARRAY, tmpobject[oTexIndex], MAX_MATERIALS);
  1917. stmt_bind_result_field(loadprefabstmt, 8, DB::TYPE_ARRAY, tmpobject[oColorIndex], MAX_MATERIALS);
  1918. stmt_bind_result_field(loadprefabstmt, 9, DB::TYPE_INT, tmpobject[ousetext]);
  1919. stmt_bind_result_field(loadprefabstmt, 10, DB::TYPE_INT, tmpobject[oFontFace]);
  1920. stmt_bind_result_field(loadprefabstmt, 11, DB::TYPE_INT, tmpobject[oFontSize]);
  1921. stmt_bind_result_field(loadprefabstmt, 12, DB::TYPE_INT, tmpobject[oFontBold]);
  1922. stmt_bind_result_field(loadprefabstmt, 13, DB::TYPE_INT, tmpobject[oFontColor]);
  1923. stmt_bind_result_field(loadprefabstmt, 14, DB::TYPE_INT, tmpobject[oBackColor]);
  1924. stmt_bind_result_field(loadprefabstmt, 15, DB::TYPE_INT, tmpobject[oAlignment]);
  1925. stmt_bind_result_field(loadprefabstmt, 16, DB::TYPE_INT, tmpobject[oTextFontSize]);
  1926. stmt_bind_result_field(loadprefabstmt, 17, DB::TYPE_STRING, tmpobject[oObjectText], MAX_TEXT_LENGTH);
  1927. // Get the ZOffset
  1928. new Query[128];
  1929. new DBResult:r;
  1930. new Float:zoff;
  1931. format(Query, sizeof(Query), "SELECT * FROM `PrefabInfo`");
  1932. r = db_query(PrefabDB, Query);
  1933. db_get_field_assoc(r, "zOFF", Query, 128);
  1934. zoff = floatstr(Query);
  1935. db_free_result(r);
  1936. new Float:px, Float:py, Float:pz, Float:fa;
  1937. new time = GetTickCount();
  1938. if(offset) GetPosFaInFrontOfPlayer(playerid, 2.0, px, py, pz, fa);
  1939. else GetPlayerPos(playerid, px, py, pz);
  1940. // Clear any grouped objects
  1941. ClearGroup(playerid);
  1942. // Execute query
  1943. if(stmt_execute(loadprefabstmt))
  1944. {
  1945. db_begin_transaction(EditMap);
  1946. while(stmt_fetch_row(loadprefabstmt))
  1947. {
  1948. new index = AddDynamicObject(tmpobject[oModel], tmpobject[oX]+px, tmpobject[oY]+py, tmpobject[oZ]+pz+zoff, tmpobject[oRX], tmpobject[oRY], tmpobject[oRZ]);
  1949. // Set textures and colors
  1950. for(new i = 0; i < MAX_MATERIALS; i++)
  1951. {
  1952. ObjectData[index][oTexIndex][i] = tmpobject[oTexIndex][i];
  1953. ObjectData[index][oColorIndex][i] = tmpobject[oColorIndex][i];
  1954. }
  1955. // Get all text settings
  1956. ObjectData[index][ousetext] = tmpobject[ousetext];
  1957. ObjectData[index][oFontFace] = tmpobject[oFontFace];
  1958. ObjectData[index][oFontSize] = tmpobject[oFontSize];
  1959. ObjectData[index][oFontBold] = tmpobject[oFontBold];
  1960. ObjectData[index][oFontColor] = tmpobject[oFontColor];
  1961. ObjectData[index][oBackColor] = tmpobject[oBackColor];
  1962. ObjectData[index][oAlignment] = tmpobject[oAlignment];
  1963. ObjectData[index][oTextFontSize] = tmpobject[oTextFontSize];
  1964. ObjectData[index][oGroup] = 0;
  1965. // Get any text string
  1966. format(ObjectData[index][oObjectText], MAX_TEXT_LENGTH, "%s", tmpobject[oObjectText]);
  1967. UpdateObject3DText(index, true);
  1968. // Add new object to prefab
  1969. GroupedObjects[playerid][index] = true;
  1970. OnUpdateGroup3DText(index);
  1971. // We need to update textures and materials
  1972. UpdateMaterial(index);
  1973. // Update the object text
  1974. UpdateObjectText(index);
  1975. // Save materials to material database
  1976. sqlite_SaveMaterialIndex(index);
  1977. // Save colors to material database
  1978. sqlite_SaveColorIndex(index);
  1979. // Save all text
  1980. sqlite_SaveAllObjectText(index);
  1981. SaveUndoInfo(index, UNDO_TYPE_CREATED, time);
  1982. }
  1983. db_end_transaction(EditMap);
  1984. // Update the Group GUI
  1985. UpdatePlayerGSelText(playerid);
  1986. stmt_close(loadprefabstmt);
  1987. return 1;
  1988. }
  1989. stmt_close(loadprefabstmt);
  1990. return 0;
  1991. }