y_td_entry.inc 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054
  1. #if defined _INC_y_td
  2. #endinput
  3. #endif
  4. #define _INC_y_td
  5. /*
  6. Legal:
  7. Version: MPL 1.1
  8. The contents of this file are subject to the Mozilla Public License Version
  9. 1.1 the "License"; you may not use this file except in compliance with
  10. the License. You may obtain a copy of the License at
  11. http://www.mozilla.org/MPL/
  12. Software distributed under the License is distributed on an "AS IS" basis,
  13. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. for the specific language governing rights and limitations under the
  15. License.
  16. The Original Code is the YSI framework.
  17. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  18. Portions created by the Initial Developer are Copyright C 2011
  19. the Initial Developer. All Rights Reserved.
  20. Contributors:
  21. Y_Less
  22. koolk
  23. JoeBullet/Google63
  24. g_aSlice/Slice
  25. Misiur
  26. samphunter
  27. tianmeta
  28. maddinat0r
  29. spacemud
  30. Crayder
  31. Dayvison
  32. Ahmad45123
  33. Zeex
  34. irinel1996
  35. Yiin-
  36. Chaprnks
  37. Konstantinos
  38. Masterchen09
  39. Southclaws
  40. PatchwerkQWER
  41. m0k1
  42. paulommu
  43. udan111
  44. Thanks:
  45. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  46. ZeeX - Very productive conversations.
  47. koolk - IsPlayerinAreaEx code.
  48. TheAlpha - Danish translation.
  49. breadfish - German translation.
  50. Fireburn - Dutch translation.
  51. yom - French translation.
  52. 50p - Polish translation.
  53. Zamaroht - Spanish translation.
  54. Los - Portuguese translation.
  55. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
  56. me to strive to better.
  57. Pixels^ - Running XScripters where the idea was born.
  58. Matite - Pestering me to release it and using it.
  59. Very special thanks to:
  60. Thiadmer - PAWN, whose limits continue to amaze me!
  61. Kye/Kalcor - SA:MP.
  62. SA:MP Team past, present and future - SA:MP.
  63. Optional plugins:
  64. Gamer_Z - GPS.
  65. Incognito - Streamer.
  66. Me - sscanf2, fixes2, Whirlpool.
  67. */
  68. #include "..\..\YSI_Core\y_utils"
  69. #include "..\..\YSI_Storage\y_xml"
  70. #include "..\..\YSI_Server\y_colours"
  71. #include "..\..\YSI_Coding\y_stringhash"
  72. #include "..\..\YSI_Coding\y_timers"
  73. #include "..\..\YSI_Data\y_iterate"
  74. #include "..\..\YSI_Coding\y_hooks"
  75. #if !defined MAX_TEXT_DRAW_STYLES
  76. #define MAX_TEXT_DRAW_STYLES (Style:32)
  77. #endif
  78. #define MAX_TEXT_DRAW_LINE (128)
  79. #define TEXT_DRAW_NO_NEXT (Text:-1)
  80. #define TEXT_DRAW_NAN (0xFFFFFFFF)
  81. //#define TEXT_DRAW_NO_STYLE_NAME
  82. //#tryinclude <sscanf2>
  83. enum td_align
  84. {
  85. td_align_none,
  86. td_align_left,
  87. td_align_center,
  88. td_align_centre = td_align_center,
  89. td_align_right
  90. }
  91. enum e_TD_BITS:(<<= 1)
  92. {
  93. e_TD_BITS_SHADOW = 0x000000FF,
  94. e_TD_BITS_OUTLINE = 0x0000FF00,
  95. e_TD_BITS_ALIGN = 0x000F0000,
  96. e_TD_BITS_FONT = 0x00F00000,
  97. e_TD_BITS_BOX = 0x01000000,
  98. e_TD_BITS_PROP
  99. }
  100. enum E_TD_DATA
  101. {
  102. #if !defined TEXT_DRAW_NO_STYLE_NAME
  103. E_TD_DATA_NAME[MAX_XML_ENTRY_NAME char],
  104. #endif
  105. E_TD_DATA_HASH,
  106. Float:E_TD_DATA_X,
  107. Float:E_TD_DATA_Y,
  108. Float:E_TD_DATA_LX,
  109. Float:E_TD_DATA_LY,
  110. Float:E_TD_DATA_TX,
  111. Float:E_TD_DATA_TY,
  112. E_TD_DATA_COLOUR,
  113. e_TD_BITS:E_TD_DATA_BITS,
  114. E_TD_DATA_BOX,
  115. E_TD_DATA_BG,
  116. E_TD_DATA_TIME,
  117. Text:E_TD_DATA_USE,
  118. E_TD_DATA_UPDATE
  119. }
  120. enum E_TD_DISPLAY
  121. {
  122. E_TD_DISPLAY_TEXT[MAX_TEXT_DRAW_LINE char],
  123. Float:E_TD_DISPLAY_X,
  124. Float:E_TD_DISPLAY_Y,
  125. Text:E_TD_DISPLAY_NEXT,
  126. Style:E_TD_DISPLAY_STYLE,
  127. E_TD_DISPLAY_LIFE,
  128. Text:E_TD_DISPLAY_REAL,
  129. E_TD_DISPLAY_REVISION, // Used to protect against ABA errors.
  130. Text:E_TD_DISPLAY_LINKED // Links two TDs together for languages.
  131. }
  132. forward TD_LoadColour();
  133. forward TD_Textdraw();
  134. forward TD_HideForPlayerPub(playerid, Text:textDraw, revision);
  135. static stock
  136. XML:YSI_g_sXMLRules = NO_XML_FILE,
  137. YSI_g_sTDData[MAX_TEXT_DRAW_STYLES][E_TD_DATA],
  138. YSI_g_sTDDisplay[Text:MAX_TEXT_DRAWS][E_TD_DISPLAY],
  139. //YSI_g_sTDTimers[Text:MAX_TEXT_DRAWS][MAX_PLAYERS],
  140. // This is actually dual purpose.
  141. Text:YSI_g_sUnused,
  142. BitArray:YSI_g_sPlayerDraws[MAX_PLAYERS]<_:MAX_TEXT_DRAWS>;
  143. //Bit:YSI_g_sPlayerDraws[MAX_PLAYERS][Bit_Bits(MAX_TEXT_DRAWS)];
  144. //static stock TD_SetTimer(playerid, Text:td, time, revision)
  145. //{
  146. // SetTimerEx("TD_HideForPlayer", time, 0, "iii", playerid, _:td, revision);
  147. //}
  148. #define TD_SetTimer(%0,%1,%2,%3) SetTimerEx("TD_HideForPlayerPub", (%2), 0, "iii", (%0), _:(%1), (%3))
  149. /*-------------------------------------------------------------------------*//**
  150. * <param name="id">Text draw style to check validity of,</param>
  151. *//*------------------------------------------------------------------------**/
  152. P:D(bool:TD_IsValidStyle(Style:id));
  153. #define TD_IsValidStyle(%1) \
  154. (Style:0 <= (%1) < MAX_TEXT_DRAW_STYLES && YSI_g_sTDData[(%1)][E_TD_DATA_HASH])
  155. #define _TD_IsValid(%1) \
  156. ((%1) < MAX_TEXT_DRAW_STYLES && YSI_g_sTDData[(%1)][E_TD_DATA_HASH])
  157. #define _TD_TextValid(%0) \
  158. (Text:0 <= (%0) < Text:MAX_TEXT_DRAWS && YSI_g_sTDDisplay[(%0)][E_TD_DISPLAY_TEXT][0])
  159. //#define TDL_START(%0) new __tdl_base=%1;do{
  160. //#define TDL_END(%0) %1=YSI_g_sTDDisplay[(%1)][E_TD_DISPLAY_LINKED];}while(%1!=__tdl_base);
  161. #define TDL_START(%1) for (new Text:__tdl_base = %1; ; ) {
  162. #define TDL_END(%1) {%1 = YSI_g_sTDDisplay[(%1)][E_TD_DISPLAY_LINKED]; if (%1 == __tdl_base) break;}}
  163. /*-------------------------------------------------------------------------*//**
  164. * <remarks>
  165. * Constructor.
  166. * </remarks>
  167. *//*------------------------------------------------------------------------**/
  168. HOOK__ OnScriptInit()
  169. {
  170. if (YSI_g_sXMLRules == NO_XML_FILE)
  171. {
  172. YSI_g_sXMLRules = XML_New();
  173. if (YSI_g_sXMLRules != NO_XML_FILE)
  174. {
  175. // y_styles has a copy of these rules.
  176. XML_AddHandler(YSI_g_sXMLRules, "color", "TD_LoadColour");
  177. XML_AddHandler(YSI_g_sXMLRules, "colour", "TD_LoadColour");
  178. XML_AddHandler(YSI_g_sXMLRules, "textdraw", "TD_Textdraw");
  179. //XML_AddHandler(YSI_g_sXMLRules, "box", "TD_Box");
  180. //XML_AddHandler(YSI_g_sXMLRules, "background", "TD_Background");
  181. //XML_AddHandler(YSI_g_sXMLRules, "style", "TD_Style");
  182. }
  183. }
  184. for (new Text:i; Text:i < Text:MAX_TEXT_DRAWS; i++)
  185. {
  186. YSI_g_sTDDisplay[i][E_TD_DISPLAY_REAL] = Text:INVALID_TEXT_DRAW;
  187. YSI_g_sTDDisplay[i][E_TD_DISPLAY_NEXT] = i + Text:1;
  188. }
  189. YSI_g_sTDDisplay[Text:MAX_TEXT_DRAWS - Text:1][E_TD_DISPLAY_NEXT] = TEXT_DRAW_NO_NEXT;
  190. return 1;
  191. }
  192. /*-------------------------------------------------------------------------*//**
  193. * <param name="filename">File to parse as a textdraw data file.</param>
  194. *//*------------------------------------------------------------------------**/
  195. stock TD_Parse(const filename[])
  196. {
  197. P:3("TD_Parse called: \"%s\"", filename);
  198. return XML_Parse(YSI_g_sXMLRules, filename);
  199. }
  200. /*-------------------------------------------------------------------------*//**
  201. * <remarks>
  202. * XML callback for loading the &lt;colour&gt; tag.
  203. * </remarks>
  204. *//*------------------------------------------------------------------------**/
  205. public TD_LoadColour()
  206. {
  207. P:2("TD_LoadColour called");
  208. static
  209. name[MAX_XML_ENTRY_NAME],
  210. val[MAX_XML_ENTRY_TEXT];
  211. new
  212. colour,
  213. hash;
  214. while (XML_GetKeyValue(name, val))
  215. {
  216. if (!strcmp(name, "name", true))
  217. {
  218. hash = YHash(val, false, hash_bernstein); //COLOUR_NAME_HASH(val);
  219. }
  220. else if (!strcmp(name, "hex", true))
  221. {
  222. #if defined _inc_sscanf2 || defined unformat
  223. unformat(val, "x", colour);
  224. #else
  225. colour = hexstr(val);
  226. #endif
  227. }
  228. else if (!strcmp(name, "value", true))
  229. {
  230. #if defined _inc_sscanf2 || defined unformat
  231. if (unformat(val, "n", colour))
  232. #else
  233. if (ishex(val)) colour = hexstr(val);
  234. else if (isnumeric(val)) colour = strval(val);
  235. else
  236. #endif
  237. colour = GetColour(val);
  238. }
  239. }
  240. //if (hash) Text_SetColour(hash, colour);
  241. if (hash) SetColourHash(hash, colour);
  242. return colour;
  243. }
  244. /*-------------------------------------------------------------------------*//**
  245. * <param name="x">X position the text will appear at.</param>
  246. * <param name="y">Y position the text will appear at,</param>
  247. * <param name="letterX">Letter X size.</param>
  248. * <param name="letterY">Letter Y size.</param>
  249. * <param name="textX">Box X size.</param>
  250. * <param name="textY">Box Y size.</param>
  251. * <param name="colour">Text colour.</param>
  252. * <param name="boxColour">Colour of the text box.</param>
  253. * <param name="bgColour">Colour of the text background.</param>
  254. * <param name="shadow">Text shadow size.</param>
  255. * <param name="outline">Text outline size.</param>
  256. * <param name="align">Text alignment.</param>
  257. * <param name="font">Text font style.</param>
  258. * <param name="proportional">Wether to make the text proportional.</param>
  259. * <param name="box">Wether to use a box.</param>
  260. * <param name="time">Time for the text to display in ms (0 = infinate).</param>
  261. * <param name="name">Name of the style.</param>
  262. * <remarks>
  263. * Creates a text draw style structure according to given
  264. * parameters, can be used to display any text in the given
  265. * style without repeated redefinitions.
  266. * </remarks>
  267. *//*------------------------------------------------------------------------**/
  268. stock Style:TD_Create(Float:x = 0.0, Float:y = 0.0, Float:letterX = 0.48, Float:letterY = 1.12, Float:textX = 1280.0, Float:textY = 1280.0, colour = 0xE1E1E1FF, boxColour = 0x80808080, bgColour = 0x000000FF, shadow = 2, outline = 0, align = _:td_align_none, font = 1, bool:proportional = false, bool:box = false, time = 0, const name[] = "\1")
  269. {
  270. P:3("Text:TD_Create called: %f, %f, %f, %f, %f, %f, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, \"%s\"", x, y, letterX, letterY, textX, textY, colour, boxColour, bgColour, shadow, outline, align, font, _:proportional, _:box, time, name);
  271. new
  272. Style:i;
  273. while (_TD_IsValid(i))
  274. {
  275. ++i;
  276. }
  277. if (i == MAX_TEXT_DRAW_STYLES)
  278. {
  279. return MAX_TEXT_DRAW_STYLES;
  280. }
  281. #if !defined TEXT_DRAW_NO_STYLE_NAME
  282. strpack(YSI_g_sTDData[i][E_TD_DATA_NAME], name, MAX_XML_ENTRY_NAME);
  283. #endif
  284. YSI_g_sTDData[i][E_TD_DATA_HASH] = bernstein(name);
  285. YSI_g_sTDData[i][E_TD_DATA_X] = x;
  286. YSI_g_sTDData[i][E_TD_DATA_Y] = y;
  287. YSI_g_sTDData[i][E_TD_DATA_LX] = letterX;
  288. YSI_g_sTDData[i][E_TD_DATA_LY] = letterY;
  289. YSI_g_sTDData[i][E_TD_DATA_TX] = textX;
  290. YSI_g_sTDData[i][E_TD_DATA_TY] = textY;
  291. YSI_g_sTDData[i][E_TD_DATA_COLOUR] = colour;
  292. YSI_g_sTDData[i][E_TD_DATA_BITS] =
  293. ((box) ? (e_TD_BITS_BOX) : (e_TD_BITS:0)) |
  294. ((proportional) ? (e_TD_BITS_PROP) : (e_TD_BITS:0)) |
  295. (e_TD_BITS:(shadow << 0) & e_TD_BITS_SHADOW) |
  296. (e_TD_BITS:(outline << 8) & e_TD_BITS_OUTLINE) |
  297. (e_TD_BITS:(align << 16) & e_TD_BITS_ALIGN) |
  298. (e_TD_BITS:(font << 20) & e_TD_BITS_FONT);
  299. YSI_g_sTDData[i][E_TD_DATA_BOX] = boxColour;
  300. YSI_g_sTDData[i][E_TD_DATA_BG] = bgColour;
  301. YSI_g_sTDData[i][E_TD_DATA_TIME] = time;
  302. YSI_g_sTDData[i][E_TD_DATA_USE] = TEXT_DRAW_NO_NEXT;
  303. YSI_g_sTDData[i][E_TD_DATA_UPDATE] = -1;
  304. return Style:i;
  305. }
  306. /*-------------------------------------------------------------------------*//**
  307. * <remarks>
  308. * XML callback for loading the &lt;textdraw&gt; tag.
  309. * </remarks>
  310. *//*------------------------------------------------------------------------**/
  311. public TD_Textdraw()
  312. {
  313. // Set all the default values quickly.
  314. P:1("TD_Textdraw called");
  315. new
  316. Style:i = TD_Create();
  317. if (i != MAX_TEXT_DRAW_STYLES)
  318. {
  319. P:5("TD_Textdraw: created %i", _:i);
  320. static
  321. name[MAX_XML_ENTRY_NAME],
  322. val[MAX_XML_ENTRY_TEXT];
  323. new
  324. e_TD_BITS:bits,
  325. // Bernstein hash of 1.
  326. hash = -32;
  327. // !"\1"
  328. //YSI_g_sTDData[i][E_TD_DATA_NAME] = 0x01000000;
  329. while (XML_GetKeyValue(name, val))
  330. {
  331. P:7("TD_Textdraw: loop");
  332. if (!strcmp(name, "x", true))
  333. {
  334. YSI_g_sTDData[i][E_TD_DATA_X] = floatstr(val);
  335. }
  336. else if (!strcmp(name, "y", true))
  337. {
  338. YSI_g_sTDData[i][E_TD_DATA_Y] = floatstr(val);
  339. }
  340. else if (!strcmp(name, "letterx", true))
  341. {
  342. YSI_g_sTDData[i][E_TD_DATA_LX] = floatstr(val);
  343. }
  344. else if (!strcmp(name, "lettery", true))
  345. {
  346. YSI_g_sTDData[i][E_TD_DATA_LY] = floatstr(val);
  347. }
  348. else if (!strcmp(name, "textx", true))
  349. {
  350. YSI_g_sTDData[i][E_TD_DATA_TX] = floatstr(val);
  351. }
  352. else if (!strcmp(name, "texty", true))
  353. {
  354. YSI_g_sTDData[i][E_TD_DATA_TY] = floatstr(val);
  355. }
  356. else if (!strcmp(name, "alignment", true))
  357. {
  358. bits &= ~e_TD_BITS_ALIGN;
  359. if (!strcmp(val, "left", true)) bits |= e_TD_BITS:(_:td_align_left << 16) & e_TD_BITS_ALIGN;
  360. else if (!strcmp(val, "right", true)) bits |= e_TD_BITS:(_:td_align_right << 16) & e_TD_BITS_ALIGN;
  361. else if (!strcmp(val, "center", true) || !strcmp(val, "centre", true)) bits |= e_TD_BITS:(_:td_align_center << 16) & e_TD_BITS_ALIGN;
  362. }
  363. else if (!strcmp(name, "color", true) || !strcmp(name, "colour", true))
  364. {
  365. P:2("TD_Textdraw: colour called");
  366. // This could now be done with the sscanf "n" type for "number".
  367. #if defined _inc_sscanf2 || defined unformat
  368. new
  369. colour;
  370. if (!unformat(val, "n", colour)) YSI_g_sTDData[i][E_TD_DATA_COLOUR] = colour;
  371. #else
  372. if (ishex(val)) YSI_g_sTDData[i][E_TD_DATA_COLOUR] = hexstr(val);
  373. else if (isnumeric(val)) YSI_g_sTDData[i][E_TD_DATA_COLOUR] = strval(val);
  374. #endif
  375. else YSI_g_sTDData[i][E_TD_DATA_COLOUR] = GetColour(val);
  376. }
  377. else if (!strcmp(name, "box", true))
  378. {
  379. new
  380. box = strval(val);
  381. if (box)
  382. {
  383. bits |= e_TD_BITS_BOX;
  384. YSI_g_sTDData[i][E_TD_DATA_BOX] = box;
  385. }
  386. }
  387. else if (!strcmp(name, "shadow", true))
  388. {
  389. bits = (bits & ~e_TD_BITS_SHADOW) | (e_TD_BITS:(strval(val)) & e_TD_BITS_SHADOW);
  390. }
  391. else if (!strcmp(name, "outline", true))
  392. {
  393. bits = (bits & ~e_TD_BITS_OUTLINE) | (e_TD_BITS:(strval(val) << 8) & e_TD_BITS_OUTLINE);
  394. }
  395. else if (!strcmp(name, "background", true))
  396. {
  397. #if defined _inc_sscanf2 || defined unformat
  398. new
  399. colour;
  400. if (!unformat(val, "n", colour)) YSI_g_sTDData[i][E_TD_DATA_BG] = colour;
  401. #else
  402. if (ishex(val)) YSI_g_sTDData[i][E_TD_DATA_BG] = hexstr(val);
  403. else if (isnumeric(val)) YSI_g_sTDData[i][E_TD_DATA_BG] = strval(val);
  404. #endif
  405. else YSI_g_sTDData[i][E_TD_DATA_BG] = GetColour(val);
  406. P:5("TD_Textdraw(): Background color: \"%s\", %d, %d: 0x%04x%04x", val, ishex(val), isnumeric(val), YSI_g_sTDData[i][E_TD_DATA_BG] >>> 16, YSI_g_sTDData[i][E_TD_DATA_BG] & 0xFFFF);
  407. }
  408. else if (!strcmp(name, "font", true))
  409. {
  410. bits = (bits & ~e_TD_BITS_FONT) | (e_TD_BITS:(strval(val) << 20) & e_TD_BITS_FONT);
  411. }
  412. else if (!strcmp(name, "proportional", true))
  413. {
  414. P:7("TD_Textdraw: proportional");
  415. bits |= e_TD_BITS_PROP;
  416. }
  417. else if (!strcmp(name, "time", true))
  418. {
  419. YSI_g_sTDData[i][E_TD_DATA_TIME] = strval(val);
  420. }
  421. else if (!strcmp(name, "name", true))
  422. {
  423. #if !defined TEXT_DRAW_NO_STYLE_NAME
  424. strpack(YSI_g_sTDData[i][E_TD_DATA_NAME], val, MAX_XML_ENTRY_NAME);
  425. #endif
  426. hash = bernstein(val);
  427. }
  428. }
  429. YSI_g_sTDData[i][E_TD_DATA_BITS] = bits;
  430. /*if (!(YSI_g_sTDData[i][E_TD_DATA_NAME] & 0xFF000000))
  431. {
  432. YSI_g_sTDData[i][E_TD_DATA_NAME] = 0x01000000;
  433. }*/
  434. //YSI_g_sTDData[i][E_TD_DATA_HASH] = bernstein(YSI_g_sTDData[i][E_TD_DATA_NAME]);
  435. YSI_g_sTDData[i][E_TD_DATA_HASH] = hash;
  436. P:5("TD data: %.2f %.2f %.2f %.2f %.2f %.2f %x %d %x %d %d", YSI_g_sTDData[i][E_TD_DATA_X], YSI_g_sTDData[i][E_TD_DATA_Y], YSI_g_sTDData[i][E_TD_DATA_LX], YSI_g_sTDData[i][E_TD_DATA_LY], YSI_g_sTDData[i][E_TD_DATA_TX], YSI_g_sTDData[i][E_TD_DATA_TY], YSI_g_sTDData[i][E_TD_DATA_COLOUR], YSI_g_sTDData[i][E_TD_DATA_BOX], YSI_g_sTDData[i][E_TD_DATA_BG], YSI_g_sTDData[i][E_TD_DATA_TIME], YSI_g_sTDData[i][E_TD_DATA_BITS]);//, YSI_g_sTDData[i][E_TD_DATA_NAME]);
  437. }
  438. return _:i;
  439. }
  440. /*-------------------------------------------------------------------------*//**
  441. * <param name="name">A style name to get a style index for.</param>
  442. *//*------------------------------------------------------------------------**/
  443. stock Style:TD_GetNamed(const name[])
  444. {
  445. new
  446. hash = bernstein(name);
  447. P:3("Text:TD_GetID called: %i", hash);
  448. new
  449. Style:i;
  450. while (i != MAX_TEXT_DRAW_STYLES && YSI_g_sTDData[i][E_TD_DATA_HASH] != hash)
  451. {
  452. ++i;
  453. }
  454. return i;
  455. }
  456. /*-------------------------------------------------------------------------*//**
  457. * <param name="hash">Hash of a style name to get a style index for.</param>
  458. *//*------------------------------------------------------------------------**/
  459. stock Style:TD_GetID(hash)
  460. {
  461. P:3("Text:TD_GetID called: %i", hash);
  462. new
  463. Style:i;
  464. while (i != MAX_TEXT_DRAW_STYLES && YSI_g_sTDData[i][E_TD_DATA_HASH] != hash)
  465. {
  466. ++i;
  467. }
  468. return i;
  469. }
  470. /*-------------------------------------------------------------------------*//**
  471. * <param name="styleID">Style to clone.</param>
  472. * <param name="name">Name of the new style.</param>
  473. * <remarks>
  474. * Copies a text draw style and returns the new handle.
  475. * </remarks>
  476. *//*------------------------------------------------------------------------**/
  477. //#if 0
  478. stock Style:TD_Clone(Style:styleID, const name[] = "\1")
  479. {
  480. P:3("Text:TD_Clone called: %i, \"%s\"", _:styleID, name);
  481. if (!TD_IsValidStyle(styleID))
  482. {
  483. return MAX_TEXT_DRAW_STYLES;
  484. }
  485. new
  486. Style:i;
  487. while (_TD_IsValid(i))
  488. {
  489. i++;
  490. }
  491. if (i == MAX_TEXT_DRAW_STYLES)
  492. {
  493. return MAX_TEXT_DRAW_STYLES;
  494. }
  495. YSI_g_sTDData[i] = YSI_g_sTDData[styleID];
  496. #if !defined TEXT_DRAW_NO_STYLE_NAME
  497. strpack(YSI_g_sTDData[i][E_TD_DATA_NAME], name, MAX_XML_ENTRY_NAME);
  498. #endif
  499. YSI_g_sTDData[i][E_TD_DATA_HASH] = bernstein(name);
  500. // memcpy?
  501. /*YSI_g_sTDData[i][E_TD_DATA_X] = YSI_g_sTDData[styleID][E_TD_DATA_X];
  502. YSI_g_sTDData[i][E_TD_DATA_Y] = YSI_g_sTDData[styleID][E_TD_DATA_Y];
  503. YSI_g_sTDData[i][E_TD_DATA_LX] = YSI_g_sTDData[styleID][E_TD_DATA_LX];
  504. YSI_g_sTDData[i][E_TD_DATA_LY] = YSI_g_sTDData[styleID][E_TD_DATA_LY];
  505. YSI_g_sTDData[i][E_TD_DATA_TX] = YSI_g_sTDData[styleID][E_TD_DATA_TX];
  506. YSI_g_sTDData[i][E_TD_DATA_TY] = YSI_g_sTDData[styleID][E_TD_DATA_TY];
  507. YSI_g_sTDData[i][E_TD_DATA_COLOUR] = YSI_g_sTDData[styleID][E_TD_DATA_COLOUR];
  508. YSI_g_sTDData[i][E_TD_DATA_BITS] = YSI_g_sTDData[styleID][E_TD_DATA_BITS];
  509. YSI_g_sTDData[i][E_TD_DATA_BOX] = YSI_g_sTDData[styleID][E_TD_DATA_BOX];
  510. YSI_g_sTDData[i][E_TD_DATA_BG] = YSI_g_sTDData[styleID][E_TD_DATA_BG];
  511. YSI_g_sTDData[i][E_TD_DATA_TIME] = YSI_g_sTDData[styleID][E_TD_DATA_TIME];*/
  512. YSI_g_sTDData[i][E_TD_DATA_USE] = TEXT_DRAW_NO_NEXT;
  513. YSI_g_sTDData[i][E_TD_DATA_UPDATE] = -1;
  514. return Style:i;
  515. }
  516. /*-------------------------------------------------------------------------*//**
  517. * <param name="styleID">Style to get the data of.</param>
  518. * <param name="data">Return array.</param>
  519. *//*------------------------------------------------------------------------**/
  520. stock TD_GetStyleData(Style:styleID, data[E_TD_DATA])
  521. {
  522. if (TD_IsValidStyle(styleID))
  523. {
  524. data = YSI_g_sTDData[styleID];
  525. return 1;
  526. }
  527. return 0;
  528. }
  529. /*-------------------------------------------------------------------------*//**
  530. * <param name="styleID">Style to modify.</param>
  531. * <param name="name">Name to give the style.</param>
  532. *//*------------------------------------------------------------------------**/
  533. stock TD_Name(Style:styleID, const name[])
  534. {
  535. P:3("TD_Name called: %i, \"%s\"", _:styleID, name);
  536. if (!TD_IsValidStyle(styleID))
  537. {
  538. return 0;
  539. }
  540. #if !defined TEXT_DRAW_NO_STYLE_NAME
  541. strpack(YSI_g_sTDData[styleID][E_TD_DATA_NAME], name, MAX_XML_ENTRY_NAME);
  542. #endif
  543. YSI_g_sTDData[styleID][E_TD_DATA_HASH] = bernstein(name);
  544. return 1;
  545. }
  546. /*-------------------------------------------------------------------------*//**
  547. * <param name="textID">Text to modify.</param>
  548. * <param name="x">New horizontal position.</param>
  549. * <param name="y">New vertical position.</param>
  550. * <remarks>
  551. * Moves a single bit of text, not all with a style.
  552. * </remarks>
  553. *//*------------------------------------------------------------------------**/
  554. stock TD_TextPosition(Text:textID, Float:x, Float:y)
  555. {
  556. P:3("TD_TextPosition called: %i, %i, %i", _:textID, x, y);
  557. if (!_TD_TextValid(textID))
  558. {
  559. return 0;
  560. }
  561. TDL_START(textID)
  562. {
  563. YSI_g_sTDDisplay[textID][E_TD_DISPLAY_X] = x;
  564. YSI_g_sTDDisplay[textID][E_TD_DISPLAY_Y] = y;
  565. TD_UpdateOne(textID, YSI_g_sTDDisplay[textID][E_TD_DISPLAY_STYLE]);
  566. }
  567. TDL_END(textID)
  568. return 1;
  569. }
  570. /*-------------------------------------------------------------------------*//**
  571. * <param name="textID">Text to modify.</param>
  572. * <param name="x">New horizontal position.</param>
  573. * <remarks>
  574. * Moves a single bit of text, not all with a style.
  575. * </remarks>
  576. *//*------------------------------------------------------------------------**/
  577. stock TD_TextXPos(Text:textID, Float:x)
  578. {
  579. P:3("TD_TextXPos called: %i, %i", _:textID, x);
  580. if (!_TD_TextValid(textID))
  581. {
  582. return 0;
  583. }
  584. TDL_START(textID)
  585. {
  586. YSI_g_sTDDisplay[textID][E_TD_DISPLAY_X] = x;
  587. TD_UpdateOne(textID, YSI_g_sTDDisplay[textID][E_TD_DISPLAY_STYLE]);
  588. }
  589. TDL_END(textID)
  590. return 1;
  591. }
  592. /*-------------------------------------------------------------------------*//**
  593. * <param name="textID">Text to modify.</param>
  594. * <param name="y">New vertical position.</param>
  595. * <remarks>
  596. * Moves a single bit of text, not all with a style.
  597. * </remarks>
  598. *//*------------------------------------------------------------------------**/
  599. stock TD_TextYPos(Text:textID, Float:y)
  600. {
  601. P:3("TD_TextYPos called: %i, %i", _:textID, y);
  602. if (!_TD_TextValid(textID))
  603. {
  604. return 0;
  605. }
  606. TDL_START(textID)
  607. {
  608. YSI_g_sTDDisplay[textID][E_TD_DISPLAY_Y] = y;
  609. TD_UpdateOne(textID, YSI_g_sTDDisplay[textID][E_TD_DISPLAY_STYLE]);
  610. }
  611. TDL_END(textID)
  612. return 1;
  613. }
  614. /*-------------------------------------------------------------------------*//**
  615. * <param name="styleID">Style to modify.</param>
  616. * <param name="x">New horizontal position.</param>
  617. * <param name="y">New vertical position.</param>
  618. * <param name="update">Wether to update the appearence for players.</param>
  619. * <remarks>
  620. * Update is default false to not modify moved texts.
  621. * </remarks>
  622. *//*------------------------------------------------------------------------**/
  623. stock TD_StylePosition(Style:styleID, Float:x, Float:y)
  624. {
  625. P:3("TD_StylePosition called: %i, %i, %i", _:styleID, x, y);
  626. if (!TD_IsValidStyle(styleID))
  627. {
  628. return 0;
  629. }
  630. YSI_g_sTDData[styleID][E_TD_DATA_X] = x;
  631. YSI_g_sTDData[styleID][E_TD_DATA_Y] = y;
  632. if (update) TD_Update(styleID, true);
  633. return 1;
  634. }
  635. /*-------------------------------------------------------------------------*//**
  636. * <param name="styleID">Style to modify.</param>
  637. * <param name="x">New horizontal position.</param>
  638. * <param name="update">Wether to update the appearence for players.</param>
  639. * <remarks>
  640. * Update is default false to not modify moved texts.
  641. * </remarks>
  642. *//*------------------------------------------------------------------------**/
  643. stock TD_StyleXPos(Style:styleID, Float:x)
  644. {
  645. P:3("TD_StyleXPos called: %i, %i", _:styleID, x);
  646. if (!TD_IsValidStyle(styleID))
  647. {
  648. return 0;
  649. }
  650. YSI_g_sTDData[styleID][E_TD_DATA_X] = x;
  651. if (update) TD_Update(styleID, true);
  652. return 1;
  653. }
  654. /*-------------------------------------------------------------------------*//**
  655. * <param name="styleID">Style to modify.</param>
  656. * <param name="y">New vertical position.</param>
  657. * <param name="update">Wether to update the appearence for players.</param>
  658. * <remarks>
  659. * Update is default false to not modify moved texts.
  660. * </remarks>
  661. *//*------------------------------------------------------------------------**/
  662. stock TD_StyleYPos(Style:styleID, Float:y)
  663. {
  664. P:3("TD_StyleYPos called: %i, %i", _:styleID, y);
  665. if (!TD_IsValidStyle(styleID))
  666. {
  667. return 0;
  668. }
  669. YSI_g_sTDData[styleID][E_TD_DATA_Y] = y;
  670. if (update) TD_Update(styleID, true);
  671. return 1;
  672. }
  673. /*-------------------------------------------------------------------------*//**
  674. * <param name="styleID">Style to modify.</param>
  675. * <param name="x">New letter width.</param>
  676. * <param name="y">New letter height.</param>
  677. * <param name="update">Wether to update the appearence for players.</param>
  678. *//*------------------------------------------------------------------------**/
  679. stock TD_LetterSize(Style:styleID, Float:x, Float:y)
  680. {
  681. P:3("TD_LetterSize called: %i, %i, %i", _:styleID, x, y);
  682. if (!TD_IsValidStyle(styleID))
  683. {
  684. return 0;
  685. }
  686. YSI_g_sTDData[styleID][E_TD_DATA_LX] = x;
  687. YSI_g_sTDData[styleID][E_TD_DATA_LY] = y;
  688. TD_Update(styleID);
  689. return 1;
  690. }
  691. /*-------------------------------------------------------------------------*//**
  692. * <param name="styleID">Style to modify.</param>
  693. * <param name="x">New letter width.</param>
  694. * <param name="update">Wether to update the appearence for players.</param>
  695. *//*------------------------------------------------------------------------**/
  696. stock TD_LetterX(Style:styleID, Float:x)
  697. {
  698. P:3("TD_LetterX called: %i, %i", _:styleID, x);
  699. if (!TD_IsValidStyle(styleID))
  700. {
  701. return 0;
  702. }
  703. YSI_g_sTDData[styleID][E_TD_DATA_LX] = x;
  704. TD_Update(styleID);
  705. return 1;
  706. }
  707. /*-------------------------------------------------------------------------*//**
  708. * <param name="styleID">Style to modify.</param>
  709. * <param name="y">New letter height.</param>
  710. * <param name="update">Wether to update the appearence for players.</param>
  711. *//*------------------------------------------------------------------------**/
  712. stock TD_LetterY(Style:styleID, Float:y)
  713. {
  714. P:3("TD_LetterY called: %i, %i", _:styleID, y);
  715. if (!TD_IsValidStyle(styleID))
  716. {
  717. return 0;
  718. }
  719. YSI_g_sTDData[styleID][E_TD_DATA_LY] = y;
  720. TD_Update(styleID);
  721. return 1;
  722. }
  723. /*-------------------------------------------------------------------------*//**
  724. * <param name="styleID">Style to modify.</param>
  725. * <param name="x">New text width.</param>
  726. * <param name="y">New text height.</param>
  727. * <param name="update">Wether to update the appearence for players.</param>
  728. *//*------------------------------------------------------------------------**/
  729. stock TD_TextSize(Style:styleID, Float:x, Float:y)
  730. {
  731. P:3("TD_TextSize called: %i, %i, %i", _:styleID, x, y);
  732. if (!TD_IsValidStyle(styleID))
  733. {
  734. return 0;
  735. }
  736. YSI_g_sTDData[styleID][E_TD_DATA_TX] = x;
  737. YSI_g_sTDData[styleID][E_TD_DATA_TY] = y;
  738. TD_Update(styleID);
  739. return 1;
  740. }
  741. /*-------------------------------------------------------------------------*//**
  742. * <param name="styleID">Style to modify.</param>
  743. * <param name="x">New text width.</param>
  744. * <param name="update">Wether to update the appearence for players.</param>
  745. *//*------------------------------------------------------------------------**/
  746. stock TD_TextX(Style:styleID, Float:x)
  747. {
  748. P:3("TD_TextX called: %i, %i", _:styleID, x);
  749. if (!TD_IsValidStyle(styleID))
  750. {
  751. return 0;
  752. }
  753. YSI_g_sTDData[styleID][E_TD_DATA_TX] = x;
  754. TD_Update(styleID);
  755. return 1;
  756. }
  757. /*-------------------------------------------------------------------------*//**
  758. * <param name="styleID">Style to modify.</param>
  759. * <param name="y">New text height.</param>
  760. * <param name="update">Wether to update the appearence for players.</param>
  761. *//*------------------------------------------------------------------------**/
  762. stock TD_TextY(Style:styleID, Float:y)
  763. {
  764. P:3("TD_TextY called: %i, %i", _:styleID, y);
  765. if (!TD_IsValidStyle(styleID))
  766. {
  767. return 0;
  768. }
  769. YSI_g_sTDData[styleID][E_TD_DATA_TY] = y;
  770. TD_Update(styleID);
  771. return 1;
  772. }
  773. /*-------------------------------------------------------------------------*//**
  774. * <param name="styleID">Style to modify.</param>
  775. * <param name="alignment">Where to align the text in it's box.</param>
  776. * <param name="update">Wether to update the appearence for players.</param>
  777. * <remarks>
  778. * Designed to take ta_align enum values and numbers.
  779. * </remarks>
  780. *//*------------------------------------------------------------------------**/
  781. stock TD_Alignment(Style:styleID, alignment = _:td_align_none)
  782. {
  783. P:3("TD_Alignment called: %i, %i", _:styleID, alignment);
  784. if (!TD_IsValidStyle(styleID))
  785. {
  786. return 0;
  787. }
  788. YSI_g_sTDData[styleID][E_TD_DATA_BITS] = (YSI_g_sTDData[styleID][E_TD_DATA_BITS] & ~e_TD_BITS_ALIGN) | (e_TD_BITS:(alignment << 16) & e_TD_BITS_ALIGN);
  789. TD_Update(styleID);
  790. return 1;
  791. }
  792. /*-------------------------------------------------------------------------*//**
  793. * <param name="styleID">Style to modify.</param>
  794. * <param name="colour">New text colour.</param>
  795. * <param name="update">Wether to update the appearence for players.</param>
  796. *//*------------------------------------------------------------------------**/
  797. stock TD_Colour(Style:styleID, colour)
  798. {
  799. P:3("TD_Colour called: %i, %i", _:styleID, colour);
  800. if (!TD_IsValidStyle(styleID))
  801. {
  802. return 0;
  803. }
  804. YSI_g_sTDData[styleID][E_TD_DATA_COLOUR] = colour;
  805. TD_Update(styleID);
  806. return 1;
  807. }
  808. #define TD_Color TD_Colour
  809. /*-------------------------------------------------------------------------*//**
  810. * <param name="styleID">Style to modify.</param>
  811. * <param name="use">Wether or not to show a box round the text.</param>
  812. * <param name="update">Wether to update the appearence for players.</param>
  813. *//*------------------------------------------------------------------------**/
  814. stock TD_UseBox(Style:styleID, bool:use)
  815. {
  816. P:3("TD_UseBox called: %i, %i", _:styleID, _:use);
  817. if (!TD_IsValidStyle(styleID))
  818. {
  819. return 0;
  820. }
  821. if (use) YSI_g_sTDData[styleID][E_TD_DATA_BITS] |= e_TD_BITS_BOX;
  822. else YSI_g_sTDData[styleID][E_TD_DATA_BITS] &= ~e_TD_BITS_BOX;
  823. TD_Update(styleID);
  824. return 1;
  825. }
  826. /*-------------------------------------------------------------------------*//**
  827. * <param name="styleID">Style to modify.</param>
  828. * <param name="colour">New box colour.</param>
  829. * <param name="update">Wether to update the appearence for players.</param>
  830. *//*------------------------------------------------------------------------**/
  831. stock TD_BoxColour(Style:styleID, colour)
  832. {
  833. P:3("TD_BoxColour called: %i, %i", _:styleID, colour);
  834. if (!TD_IsValidStyle(styleID))
  835. {
  836. return 0;
  837. }
  838. YSI_g_sTDData[styleID][E_TD_DATA_BOX] = colour;
  839. TD_Update(styleID);
  840. return 1;
  841. }
  842. #define TD_BoxColor TD_BoxColour
  843. /*-------------------------------------------------------------------------*//**
  844. * <param name="styleID">Style to modify.</param>
  845. * <param name="size">Size of the letter shadow,</param>
  846. * <param name="update">Wether to update the appearence for players.</param>
  847. *//*------------------------------------------------------------------------**/
  848. stock TD_SetShadow(Style:styleID, size)
  849. {
  850. P:3("TD_SetShadow called: %i, %i", _:styleID, size);
  851. if (!TD_IsValidStyle(styleID))
  852. {
  853. return 0;
  854. }
  855. YSI_g_sTDData[styleID][E_TD_DATA_BITS] = (YSI_g_sTDData[styleID][E_TD_DATA_BITS] & ~e_TD_BITS_SHADOW) | (e_TD_BITS:(size) & e_TD_BITS_SHADOW);
  856. TD_Update(styleID);
  857. return 1;
  858. }
  859. /*-------------------------------------------------------------------------*//**
  860. * <param name="styleID">Style to modify.</param>
  861. * <param name="size">Size of the letter outline.</param>
  862. * <param name="update">Wether to update the appearence for players.</param>
  863. *//*------------------------------------------------------------------------**/
  864. stock TD_SetOutline(Style:styleID, size)
  865. {
  866. P:3("TD_SetOutline called: %i, %i", _:styleID, size);
  867. if (!TD_IsValidStyle(styleID))
  868. {
  869. return 0;
  870. }
  871. YSI_g_sTDData[styleID][E_TD_DATA_BITS] = (YSI_g_sTDData[styleID][E_TD_DATA_BITS] & ~e_TD_BITS_OUTLINE) | (e_TD_BITS:(size << 8) & e_TD_BITS_OUTLINE);
  872. TD_Update(styleID);
  873. return 1;
  874. }
  875. /*-------------------------------------------------------------------------*//**
  876. * <param name="styleID">Style to modify.</param>
  877. * <param name="colour">New background (outline/shadow) colour.</param>
  878. * <param name="update">Wether to update the appearence for players.</param>
  879. *//*------------------------------------------------------------------------**/
  880. stock TD_BackgroundColour(Style:styleID, colour)
  881. {
  882. P:3("TD_BackgroundColour called: %i, %i", _:styleID, colour);
  883. if (!TD_IsValidStyle(styleID))
  884. {
  885. return 0;
  886. }
  887. YSI_g_sTDData[styleID][E_TD_DATA_BG] = colour;
  888. TD_Update(styleID);
  889. return 1;
  890. }
  891. #define TD_BackgroundColor TD_BackgroundColour
  892. /*-------------------------------------------------------------------------*//**
  893. * <param name="styleID">Style to modify.</param>
  894. * <param name="font">New text font style.</param>
  895. * <param name="update">Wether to update the appearence for players.</param>
  896. *//*------------------------------------------------------------------------**/
  897. stock TD_Font(Style:styleID, font)
  898. {
  899. P:3("TD_Font called: %i, %i", _:styleID, font);
  900. if (!TD_IsValidStyle(styleID))
  901. {
  902. return 0;
  903. }
  904. YSI_g_sTDData[styleID][E_TD_DATA_BITS] = (YSI_g_sTDData[styleID][E_TD_DATA_BITS] & ~e_TD_BITS_FONT) | (e_TD_BITS:(font << 20) & e_TD_BITS_FONT);
  905. TD_Update(styleID);
  906. return 1;
  907. }
  908. /*-------------------------------------------------------------------------*//**
  909. * <param name="styleID">Style to modify.</param>
  910. * <param name="set">Wether to make the letters proportional or not.</param>
  911. * <param name="update">Wether to update the appearence for players.</param>
  912. *//*------------------------------------------------------------------------**/
  913. stock TD_SetProportional(Style:styleID, bool:set)
  914. {
  915. P:3("TD_SetProportional called: %i, %i", _:styleID, _:set);
  916. if (!TD_IsValidStyle(styleID))
  917. {
  918. return 0;
  919. }
  920. if (set) YSI_g_sTDData[styleID][E_TD_DATA_BITS] |= e_TD_BITS_PROP;
  921. else YSI_g_sTDData[styleID][E_TD_DATA_BITS] &= ~e_TD_BITS_PROP;
  922. TD_Update(styleID);
  923. return 1;
  924. }
  925. /*-------------------------------------------------------------------------*//**
  926. * <param name="styleID">Style to modify.</param>
  927. * <param name="time">New time for the text to display for.</param>
  928. * <param name="existing">Whether or not to change the display of existing text draws.</param>
  929. * <remarks>
  930. * Doesn't update existing timed texts, just new ones. Now does all of them.
  931. * </remarks>
  932. *//*------------------------------------------------------------------------**/
  933. stock TD_SetTime(Style:styleID, time, bool:existing = false)
  934. {
  935. P:3("TD_SetTime called: %i, %i, %i", _:styleID, time, _:existing);
  936. if (!TD_IsValidStyle(styleID))
  937. {
  938. return 0;
  939. }
  940. YSI_g_sTDData[styleID][E_TD_DATA_TIME] = time;
  941. if (existing)
  942. {
  943. // Hide this after the given time for all players.
  944. new
  945. Text:next = YSI_g_sTDData[styleId][E_TD_DATA_USE],
  946. Text:last = TEXT_DRAW_NO_NEXT;
  947. while (next != TEXT_DRAW_NO_NEXT)
  948. {
  949. // DO update the revision here!
  950. new
  951. index = Bit_Slot(next),
  952. Bit:mod = Bit_Mask(next),
  953. revision = ++YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REVISION];
  954. FOREACH__ (new playerid : Player)
  955. {
  956. if (YSI_g_sPlayerDraws[playerid][index] & mod)
  957. {
  958. TD_SetTimer(playerid, next, time, revision);
  959. }
  960. }
  961. last = next;
  962. next = YSI_g_sTDDisplay[next][E_TD_DISPLAY_NEXT];
  963. }
  964. }
  965. return 1;
  966. }
  967. /*-------------------------------------------------------------------------*//**
  968. * <summary>Text:TD_RenderInternal</summary>
  969. * <param name="text">String to output.</param>
  970. * <param name="id">Text draw style to render the text in.</param>
  971. * <param name="slot">the slot the text is stored in.</param>
  972. * <returns>
  973. * TextDraw id.
  974. * </returns>
  975. * <remarks>
  976. * Basically the application layer, creates a text_draw with the
  977. * saved data.
  978. * </remarks>
  979. *//*------------------------------------------------------------------------**/
  980. #if !defined CST_TextDrawCreate
  981. native Text:CST_TextDrawCreate(Float:x, Float:y, const text[]) = TextDrawCreate;
  982. #endif
  983. static stock Text:TD_RenderInternal(const text[], const style[E_TD_DATA], Float:x, Float:y)
  984. {
  985. //P:4("Text:TD_Render called: \"%s\", %i, %i", text, _:id, _:slot);
  986. new
  987. Text:textDraw = CST_TextDrawCreate(x, y, text);
  988. if (textDraw != Text:INVALID_TEXT_DRAW)
  989. {
  990. new
  991. e_TD_BITS:bits = style[E_TD_DATA_BITS];
  992. TextDrawLetterSize(textDraw, style[E_TD_DATA_LX], style[E_TD_DATA_LY]);
  993. TextDrawTextSize(textDraw, style[E_TD_DATA_TX], style[E_TD_DATA_TY]);
  994. TextDrawAlignment(textDraw, e_TEXT_DRAW_ALIGN:(_:(bits & e_TD_BITS_ALIGN) >> 16));
  995. TextDrawColor(textDraw, style[E_TD_DATA_COLOUR]);
  996. TextDrawUseBox(textDraw, !!(bits & e_TD_BITS_BOX));
  997. TextDrawBoxColor(textDraw, style[E_TD_DATA_BOX]);
  998. TextDrawSetShadow(textDraw, _:(bits & e_TD_BITS_SHADOW));
  999. TextDrawSetOutline(textDraw, _:(bits & e_TD_BITS_OUTLINE) >> 8);
  1000. TextDrawBackgroundColor(textDraw, style[E_TD_DATA_BG]);
  1001. TextDrawFont(textDraw, _:(bits & e_TD_BITS_FONT) >> 20);
  1002. TextDrawSetProportional(textDraw, !!(bits & e_TD_BITS_PROP));
  1003. }
  1004. return textDraw;
  1005. }
  1006. /*-------------------------------------------------------------------------*//**
  1007. * <summary>Text:TD_Render</summary>
  1008. * <param name="text">String to output.</param>
  1009. * <param name="id">Text draw style to render the text in.</param>
  1010. * <param name="slot">the slot the text is stored in.</param>
  1011. * <returns>
  1012. * TextDraw id.
  1013. * </returns>
  1014. * <remarks>
  1015. * Basically the application layer, creates a text_draw with the
  1016. * saved data.
  1017. * </remarks>
  1018. *//*------------------------------------------------------------------------**/
  1019. static stock Text:TD_Render(const text[], Style:id, Text:slot)
  1020. {
  1021. P:4("Text:TD_Render called: \"%s\", %i, %i", text, _:id, _:slot);
  1022. return TD_RenderInternal(text, YSI_g_sTDData[id], YSI_g_sTDDisplay[slot][E_TD_DISPLAY_X], YSI_g_sTDDisplay[slot][E_TD_DISPLAY_Y]);
  1023. }
  1024. /*-------------------------------------------------------------------------*//**
  1025. * <param name="id">Style to update for players.</param>
  1026. * <param name="pos">Wether or not to update children's positions.</param>
  1027. * <remarks>
  1028. * Loops through all texts displayed using the current render style and updates
  1029. * their real display.
  1030. * </remarks>
  1031. *//*------------------------------------------------------------------------**/
  1032. stock TD_Update(Style:id, bool:pos = false)
  1033. {
  1034. P:3("TD_Update called: %i, %i", _:id, _:pos);
  1035. if (!TD_IsValidStyle(id))
  1036. {
  1037. return;
  1038. }
  1039. if (pos)
  1040. {
  1041. // Put this all in one "if" block.
  1042. new
  1043. Text:next = YSI_g_sTDData[id][E_TD_DATA_USE],
  1044. Float:x = YSI_g_sTDData[id][E_TD_DATA_X],
  1045. Float:y = YSI_g_sTDData[id][E_TD_DATA_Y];
  1046. while (next != TEXT_DRAW_NO_NEXT)
  1047. {
  1048. YSI_g_sTDDisplay[next][E_TD_DISPLAY_X] = x;
  1049. YSI_g_sTDDisplay[next][E_TD_DISPLAY_Y] = y;
  1050. next = YSI_g_sTDDisplay[next][E_TD_DISPLAY_NEXT];
  1051. }
  1052. }
  1053. // Update the apperance after a load of updates have been applied.
  1054. if (YSI_g_sTDData[id][E_TD_DATA_UPDATE] == -1)
  1055. {
  1056. YSI_g_sTDData[id][E_TD_DATA_UPDATE] = SetTimerEx("TD_UpdateInternal", 1, 0, "i", _:id);
  1057. }
  1058. }
  1059. forward TD_UpdateInternal(Style:id);
  1060. public TD_UpdateInternal(Style:id)
  1061. {
  1062. new
  1063. Text:next = YSI_g_sTDData[id][E_TD_DATA_USE];
  1064. while (next != TEXT_DRAW_NO_NEXT)
  1065. {
  1066. TD_UpdateOne(next, id);
  1067. next = YSI_g_sTDDisplay[next][E_TD_DISPLAY_NEXT];
  1068. }
  1069. }
  1070. /*-------------------------------------------------------------------------*//**
  1071. * <param name="slot">Text to update.</param>
  1072. * <param name="id">Style to use.</param>
  1073. * <remarks>
  1074. * Updates a single text's appearance. Modified to use a timer with a delay of
  1075. * 1ms, to be called after the current slew of updates. This means that doing
  1076. * a whole load of modifications at once will all be committed to players at
  1077. * the same time. This used to be done with the optional "update" parameter.
  1078. * </remarks>
  1079. *//*------------------------------------------------------------------------**/
  1080. stock TD_UpdateOne(Text:slot, Style:id)
  1081. {
  1082. P:3("TD_UpdateOne called: %i, %i", _:slot, _:id);
  1083. // DON'T update the revision in here - if you show a TD to a player for 5
  1084. // seconds and change it after 2, they should just get the new version for
  1085. // 3 seconds, it shouldn't reset the timer.
  1086. new
  1087. Text:real = YSI_g_sTDDisplay[slot][E_TD_DISPLAY_REAL];
  1088. TextDrawDestroy(real);
  1089. real = TD_Render(YSI_g_sTDDisplay[slot][E_TD_DISPLAY_TEXT], id, slot);
  1090. YSI_g_sTDDisplay[slot][E_TD_DISPLAY_REAL] = real;
  1091. if (real != Text:INVALID_TEXT_DRAW)
  1092. {
  1093. new
  1094. index = Bit_Slot(slot),
  1095. Bit:mod = Bit_Mask(slot);
  1096. FOREACH__ (new playerid : Player)
  1097. {
  1098. if (YSI_g_sPlayerDraws[playerid][index] & mod)
  1099. {
  1100. TextDrawShowForPlayer(playerid, real);
  1101. }
  1102. }
  1103. }
  1104. }
  1105. /*-------------------------------------------------------------------------*//**
  1106. * <param name="styleId">Text draw style ID you want to remove.</param>
  1107. * <remarks>
  1108. * Just nulls the name to remove it's active marker.
  1109. * </remarks>
  1110. *//*------------------------------------------------------------------------**/
  1111. stock TD_Delete(Style:styleId)
  1112. {
  1113. P:3("TD_Delete called: %i", _:styleId);
  1114. if (!TD_IsValidStyle(styleId))
  1115. {
  1116. return 0;
  1117. }
  1118. if (YSI_g_sTDData[styleId][E_TD_DATA_UPDATE] != -1)
  1119. {
  1120. KillTimer(YSI_g_sTDData[styleId][E_TD_DATA_UPDATE]);
  1121. YSI_g_sTDData[styleId][E_TD_DATA_UPDATE] = -1;
  1122. }
  1123. new
  1124. Text:next = YSI_g_sTDData[styleId][E_TD_DATA_USE],
  1125. Text:last = TEXT_DRAW_NO_NEXT;
  1126. // Loop through all the TDs using this style.
  1127. while (next != TEXT_DRAW_NO_NEXT)
  1128. {
  1129. TextDrawDestroy(YSI_g_sTDDisplay[next][E_TD_DISPLAY_REAL]);
  1130. YSI_g_sTDDisplay[next][E_TD_DISPLAY_REAL] = Text:INVALID_TEXT_DRAW;
  1131. YSI_g_sTDDisplay[next][E_TD_DISPLAY_TEXT][0] = '\0';
  1132. ++YSI_g_sTDDisplay[next][E_TD_DISPLAY_REVISION];
  1133. new
  1134. index = Bit_Slot(next),
  1135. Bit:mod = ~Bit_Mask(next);
  1136. FOREACH__ (new playerid : Player)
  1137. {
  1138. // TODO: Update.
  1139. /*if (YSI_g_sTDTimers[next][playerid])
  1140. {
  1141. KillTimer(YSI_g_sTDTimers[next][playerid]);
  1142. }
  1143. YSI_g_sTDTimers[next][playerid] = 0;*/
  1144. // Kill the update timer.
  1145. // Mark this player as not having this TD.
  1146. YSI_g_sPlayerDraws[playerid][index] &= mod;
  1147. }
  1148. last = next;
  1149. next = YSI_g_sTDDisplay[next][E_TD_DISPLAY_NEXT];
  1150. }
  1151. // Add the entire style list to the unused list at once.
  1152. if (last != TEXT_DRAW_NO_NEXT)
  1153. {
  1154. // There are items to add.
  1155. YSI_g_sTDDisplay[last][E_TD_DISPLAY_NEXT] = YSI_g_sUnused;
  1156. YSI_g_sUnused = YSI_g_sTDData[styleId][E_TD_DATA_USE];
  1157. }
  1158. // Mark the style as unused.
  1159. YSI_g_sTDData[styleId][E_TD_DATA_USE] = TEXT_DRAW_NO_NEXT;
  1160. #if !defined TEXT_DRAW_NO_STYLE_NAME
  1161. YSI_g_sTDData[styleId][E_TD_DATA_NAME] = 0;
  1162. #endif
  1163. YSI_g_sTDData[styleId][E_TD_DATA_HASH] = 0;
  1164. return 1;
  1165. }
  1166. /*-------------------------------------------------------------------------*//**
  1167. * <param name="textDraw">Text draw to destroy safely.</param>
  1168. * <remarks>
  1169. * Destroys this text draw only if it is marked for garbage collection. It
  1170. * does not however check that no-one can see the text draw, so those people
  1171. * who can currently see it will loose it.
  1172. * </remarks>
  1173. *//*------------------------------------------------------------------------**/
  1174. static stock TD_TryDestroy(Text:textDraw)
  1175. {
  1176. P:4("TD_TryDestroy called: %i", _:textDraw);
  1177. // Destroy this if it is marked to be garbage collected.
  1178. if (YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] & 0x80000000)
  1179. {
  1180. TD_Destroy(textDraw);
  1181. return 1;
  1182. }
  1183. return 0;
  1184. }
  1185. /*-------------------------------------------------------------------------*//**
  1186. * <param name="textDraw">Text draw to destroy safely.</param>
  1187. * <remarks>
  1188. * Optimised for multiple people. Not very well though...
  1189. * </remarks>
  1190. *//*------------------------------------------------------------------------**/
  1191. stock TD_Destroy(Text:textDraw)
  1192. {
  1193. P:3("TD_Destroy called: %i", _:textDraw);
  1194. if (Text:0 <= textDraw < Text:MAX_TEXT_DRAWS)
  1195. {
  1196. TDL_START(textDraw)
  1197. {
  1198. // Find the TD before this one in the style list.
  1199. new
  1200. Style:style = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_STYLE],
  1201. Text:next = YSI_g_sTDData[style][E_TD_DATA_USE],
  1202. Text:last = TEXT_DRAW_NO_NEXT;
  1203. while (next != TEXT_DRAW_NO_NEXT)
  1204. {
  1205. if (next == textDraw)
  1206. {
  1207. break;
  1208. }
  1209. last = next;
  1210. next = YSI_g_sTDDisplay[next][E_TD_DISPLAY_NEXT];
  1211. }
  1212. // Destroy the SA:MP text draw.
  1213. new
  1214. Text:real = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REAL];
  1215. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REAL] = Text:INVALID_TEXT_DRAW;
  1216. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_TEXT][0] = '\0';
  1217. ++YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REVISION];
  1218. if (real != Text:INVALID_TEXT_DRAW)
  1219. {
  1220. // TextDrawDestroy
  1221. TextDrawDestroy(real);
  1222. // Now kill timers for players.
  1223. // TODO: Update.
  1224. new
  1225. index = Bit_Slot(textDraw),
  1226. Bit:mod = ~Bit_Mask(textDraw);
  1227. FOREACH__ (new playerid : Player)
  1228. {
  1229. /*if (YSI_g_sTDTimers[textDraw][playerid])
  1230. {
  1231. KillTimer(YSI_g_sTDTimers[textDraw][playerid]);
  1232. }
  1233. YSI_g_sTDTimers[textDraw][playerid] = 0;*/
  1234. YSI_g_sPlayerDraws[playerid][index] &= mod;
  1235. }
  1236. }
  1237. // Remove from the style use list and add to the unused list.
  1238. if (next == textDraw)
  1239. {
  1240. if (last == TEXT_DRAW_NO_NEXT)
  1241. {
  1242. YSI_g_sTDData[style][E_TD_DATA_USE] = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_NEXT];
  1243. }
  1244. else
  1245. {
  1246. YSI_g_sTDDisplay[last][E_TD_DISPLAY_NEXT] = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_NEXT];
  1247. }
  1248. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_NEXT] = YSI_g_sUnused;
  1249. YSI_g_sUnused = textDraw;
  1250. }
  1251. P:C(else P:W("Orphaned text draw found."););
  1252. }
  1253. TDL_END(textDraw)
  1254. }
  1255. return 1;
  1256. }
  1257. /*-------------------------------------------------------------------------*//**
  1258. * <param name="td">Text draw to stop updating.</param>
  1259. * <remarks>
  1260. * Unlinks a text draw from another one, so that updating the other one does
  1261. * not update this one.
  1262. * </remarks>
  1263. *//*------------------------------------------------------------------------**/
  1264. stock TD_Unlink(Text:td)
  1265. {
  1266. new
  1267. Text:orig = YSI_g_sTDDisplay[td][E_TD_DISPLAY_LINKED],
  1268. Text:next = orig,
  1269. Text:other = td;
  1270. for ( ; ; )
  1271. {
  1272. if (next == td)
  1273. {
  1274. // Unlinking from no list works fine.
  1275. YSI_g_sTDDisplay[other][E_TD_DISPLAY_LINKED] = orig;
  1276. YSI_g_sTDDisplay[td][E_TD_DISPLAY_LINKED] = td;
  1277. return;
  1278. }
  1279. other = next;
  1280. next = YSI_g_sTDDisplay[next][E_TD_DISPLAY_LINKED];
  1281. }
  1282. }
  1283. /*-------------------------------------------------------------------------*//**
  1284. * <param name="base">Text draw whose updates will be propogated.</param>
  1285. * <param name="other">Text draw that will receive a parent's updates.</param>
  1286. * <remarks>
  1287. * Links two TDs so that manipulating one does the other too. They are already
  1288. * linked through their style, but that's only for style updates. This handles
  1289. * things like screen position updates etc.
  1290. * </remarks>
  1291. *//*------------------------------------------------------------------------**/
  1292. stock TD_Link(Text:base, Text:other)
  1293. {
  1294. if (YSI_g_sTDDisplay[other][E_TD_DISPLAY_LINKED] != other)
  1295. {
  1296. TD_Unlink(other);
  1297. }
  1298. // This is an unordered linked list.
  1299. YSI_g_sTDDisplay[other][E_TD_DISPLAY_LINKED] = YSI_g_sTDDisplay[base][E_TD_DISPLAY_LINKED];
  1300. YSI_g_sTDDisplay[base][E_TD_DISPLAY_LINKED] = other;
  1301. }
  1302. /*-------------------------------------------------------------------------*//**
  1303. * <summary>Text:TD_Display</summary>
  1304. * <param name="text">Text to display onscreen.</param>
  1305. * <param name="id">Style to use to style text.</param>
  1306. * <returns>
  1307. * Internal Text: id, not actual text draw's id.
  1308. * </returns>
  1309. * <remarks>
  1310. * Generates a text draw for to display to people.
  1311. * </remarks>
  1312. *//*------------------------------------------------------------------------**/
  1313. stock Text:TD_Display(const text[], Style:id, Float:x = (Float:TEXT_DRAW_NAN), Float:y = (Float:TEXT_DRAW_NAN))
  1314. {
  1315. if (YSI_g_sUnused == TEXT_DRAW_NO_NEXT)
  1316. {
  1317. return Text:INVALID_TEXT_DRAW;
  1318. }
  1319. if (!TD_IsValidStyle(id))
  1320. {
  1321. return Text:INVALID_TEXT_DRAW;
  1322. }
  1323. // if (x != x)
  1324. // Determine the screen position.
  1325. if (_:x == TEXT_DRAW_NAN)
  1326. {
  1327. YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_X] = YSI_g_sTDData[id][E_TD_DATA_X];
  1328. }
  1329. else
  1330. {
  1331. YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_X] = x;
  1332. }
  1333. if (_:y == TEXT_DRAW_NAN)
  1334. {
  1335. YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_Y] = YSI_g_sTDData[id][E_TD_DATA_Y];
  1336. }
  1337. else
  1338. {
  1339. YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_Y] = y;
  1340. }
  1341. YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_STYLE] = id;
  1342. // Render the code to an internal TD. All TD_Render does is call SA:MP
  1343. // functions, it does no variable sets.
  1344. new
  1345. Text:textDraw = TD_Render(text, id, YSI_g_sUnused);
  1346. if (textDraw == Text:INVALID_TEXT_DRAW)
  1347. {
  1348. return Text:INVALID_TEXT_DRAW;
  1349. }
  1350. YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_REAL] = textDraw;
  1351. YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_LINKED] = YSI_g_sUnused;
  1352. // I don't know wether or not to use strpack here.
  1353. //strcpy(YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_TEXT], text, MAX_TEXT_DRAW_LINE);
  1354. strpack(YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_TEXT], text, MAX_TEXT_DRAW_LINE char);
  1355. textDraw = Text:YSI_g_sUnused;
  1356. YSI_g_sUnused = YSI_g_sTDDisplay[YSI_g_sUnused][E_TD_DISPLAY_NEXT];
  1357. // Add to the list of items using this style.
  1358. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_NEXT] = YSI_g_sTDData[id][E_TD_DATA_USE];
  1359. YSI_g_sTDData[id][E_TD_DATA_USE] = textDraw;
  1360. // Nobody can see it, but don't destroy it.
  1361. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] = 0;
  1362. // Increment this every time this slot is used and cleared.
  1363. ++YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REVISION];
  1364. return textDraw;
  1365. }
  1366. stock Text:TD_DisplayForPlayer(playerid, const text[], Style:id, Float:x = (Float:TEXT_DRAW_NAN), Float:y = (Float:TEXT_DRAW_NAN))
  1367. {
  1368. new
  1369. Text:td = TD_Display(text, id, x, y);
  1370. TD_Garbage(td);
  1371. TD_ShowForPlayer(playerid, td);
  1372. return td;
  1373. }
  1374. stock Text:TD_DisplayForAll(const text[], Style:id, Float:x = (Float:TEXT_DRAW_NAN), Float:y = (Float:TEXT_DRAW_NAN))
  1375. {
  1376. new
  1377. Text:td = TD_Display(text, id, x, y);
  1378. TD_Garbage(td);
  1379. TD_ShowForAll(td);
  1380. return td;
  1381. }
  1382. stock Style:TD_GetDisplayStyle(Text:td)
  1383. {
  1384. return YSI_g_sTDDisplay[td][E_TD_DISPLAY_STYLE];
  1385. }
  1386. /*-------------------------------------------------------------------------*//**
  1387. * <param name="td">The text draw to modify.</param>
  1388. * <param name="text">Text to display onscreen.</param>
  1389. * <remarks>
  1390. * Changes the text on people's screens quickly.
  1391. *
  1392. * This function DOES NOT update linked TDs as the point is that they display
  1393. * the same data in different ways, so will need to be updated in different
  1394. * ways.
  1395. * </remarks>
  1396. *//*------------------------------------------------------------------------**/
  1397. #if !defined CST_TextDrawSetString
  1398. native CST_TextDrawSetString(Text:text, const string[]) = TextDrawSetString;
  1399. #endif
  1400. stock TD_SetString(Text:td, const text[])
  1401. {
  1402. P:3("TD_SetString called: %i, \"%s\"", _:td, text);
  1403. if (_TD_TextValid(td))
  1404. {
  1405. //strcpy(YSI_g_sTDDisplay[td][E_TD_DISPLAY_TEXT], text, MAX_TEXT_DRAW_LINE);
  1406. strpack(YSI_g_sTDDisplay[td][E_TD_DISPLAY_TEXT], text, MAX_TEXT_DRAW_LINE char);
  1407. new
  1408. Text:real = YSI_g_sTDDisplay[td][E_TD_DISPLAY_REAL];
  1409. // This may have lost it's real rendering
  1410. if (real == Text:INVALID_TEXT_DRAW)
  1411. {
  1412. return 0;
  1413. }
  1414. // Get the style information for showing this TD.
  1415. CST_TextDrawSetString(real, text);
  1416. }
  1417. return 1;
  1418. }
  1419. /*-------------------------------------------------------------------------*//**
  1420. * <summary>Text:TD_DisplayHashed</summary>
  1421. * <param name="text">Text to display.</param>
  1422. * <param name="hash">Hashed style name for styling.</param>
  1423. *//*------------------------------------------------------------------------**/
  1424. stock Text:TD_DisplayHashed(const text[], hash, Float:x = (Float:TEXT_DRAW_NAN), Float:y = (Float:TEXT_DRAW_NAN))
  1425. {
  1426. new
  1427. Style:id = TD_GetID(hash);
  1428. if (id != MAX_TEXT_DRAW_STYLES)
  1429. {
  1430. return TD_Display(text, id, x, y);
  1431. }
  1432. return Text:INVALID_TEXT_DRAW;
  1433. }
  1434. stock Text:TD_DisplayHashedForPlayer(playerid, const text[], hash, Float:x = (Float:TEXT_DRAW_NAN), Float:y = (Float:TEXT_DRAW_NAN))
  1435. {
  1436. new
  1437. Style:id = TD_GetID(hash);
  1438. if (id != MAX_TEXT_DRAW_STYLES)
  1439. {
  1440. return TD_DisplayForPlayer(playerid, text, id, x, y);
  1441. }
  1442. return Text:INVALID_TEXT_DRAW;
  1443. }
  1444. stock Text:TD_DisplayHashedForAll(const text[], hash, Float:x = (Float:TEXT_DRAW_NAN), Float:y = (Float:TEXT_DRAW_NAN))
  1445. {
  1446. new
  1447. Style:id = TD_GetID(hash);
  1448. if (id != MAX_TEXT_DRAW_STYLES)
  1449. {
  1450. return TD_DisplayForAll(text, id, x, y);
  1451. }
  1452. return Text:INVALID_TEXT_DRAW;
  1453. }
  1454. /*-------------------------------------------------------------------------*//**
  1455. * <summary>Text:TD_DisplayNamed</summary>
  1456. * <param name="text">Text to display.</param>
  1457. * <param name="style">Named style to display the text with.</param>
  1458. *//*------------------------------------------------------------------------**/
  1459. stock Text:TD_DisplayNamed(const text[], const style[], Float:x = (Float:TEXT_DRAW_NAN), Float:y = (Float:TEXT_DRAW_NAN))
  1460. {
  1461. return TD_DisplayHashed(text, bernstein(style), x, y);
  1462. }
  1463. stock Text:TD_DisplayNamedForPlayer(playerid, const text[], const style[], Float:x = (Float:TEXT_DRAW_NAN), Float:y = (Float:TEXT_DRAW_NAN))
  1464. {
  1465. return TD_DisplayHashedForPlayer(playerid, text, bernstein(style), x, y);
  1466. }
  1467. stock Text:TD_DisplayNamedForAll(const text[], const style[], Float:x = (Float:TEXT_DRAW_NAN), Float:y = (Float:TEXT_DRAW_NAN))
  1468. {
  1469. return TD_DisplayHashedForAll(text, bernstein(style), x, y);
  1470. }
  1471. /*-------------------------------------------------------------------------*//**
  1472. * <param name="playerid">Player to show the text to.</param>
  1473. * <param name="textDraw">ID of the text to show.</param>
  1474. * <remarks>
  1475. * Now destroys any existing text draws using the same style in
  1476. * the same place to avoid overlaps.
  1477. * </remarks>
  1478. *//*------------------------------------------------------------------------**/
  1479. stock TD_ShowForPlayer(playerid, Text:textDraw)
  1480. {
  1481. P:3("TD_ShowForPlayer called: %i, %i", playerid, _:textDraw);
  1482. if (Text:0 <= textDraw < Text:MAX_TEXT_DRAWS && !Bit_GetBit(YSI_g_sPlayerDraws[playerid], _:textDraw))
  1483. {
  1484. new
  1485. Text:real = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REAL],
  1486. Style:style = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_STYLE];
  1487. // This may have lost it's real rendering
  1488. if (real == Text:INVALID_TEXT_DRAW)
  1489. {
  1490. if (!YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_TEXT][0])
  1491. {
  1492. // There is no text to render.
  1493. return 0;
  1494. }
  1495. real = TD_Render(YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_TEXT], style, textDraw);
  1496. if (real == Text:INVALID_TEXT_DRAW)
  1497. {
  1498. return 0;
  1499. }
  1500. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REAL] = real;
  1501. }
  1502. // Now show this for a player.
  1503. TextDrawShowForPlayer(playerid, real);
  1504. Bit_Let(YSI_g_sPlayerDraws[playerid], _:textDraw);
  1505. ++YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE];
  1506. new
  1507. time = YSI_g_sTDData[style][E_TD_DATA_TIME];
  1508. // TODO: Update.
  1509. /*if (YSI_g_sTDTimers[textDraw][playerid])
  1510. {
  1511. KillTimer(YSI_g_sTDTimers[textDraw][playerid]);
  1512. }*/
  1513. if (time)
  1514. {
  1515. //YSI_g_sTDTimers[textDraw][playerid] = SetTimerEx("TD_HideForPlayer", time, 0, "ii", playerid, _:textDraw);
  1516. TD_SetTimer(playerid, textDraw, time, YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REVISION]);
  1517. }
  1518. return 1;
  1519. }
  1520. return 0;
  1521. }
  1522. /*-------------------------------------------------------------------------*//**
  1523. * <param name="playerid">Player to hide the text for.</param>
  1524. * <param name="textDraw">Text to hide.</param>
  1525. * <param name="revision">The version of the text draw which existed when this was set.</param>
  1526. * <remarks>
  1527. * Public so the timer can call it to hide texts with a time set.
  1528. * </remarks>
  1529. *//*------------------------------------------------------------------------**/
  1530. public TD_HideForPlayerPub(playerid, Text:textDraw, revision)
  1531. {
  1532. // Hide the TD only if it's not changed since last time (avoids ABA errors).
  1533. // It CAN, however, get ABCD...A errors if you manage to change this one
  1534. // over 4,000,000,000 times before the timer is called...
  1535. if (YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REVISION] == revision)
  1536. {
  1537. //if (playerid == INVALID_PLAYER_ID)
  1538. //{
  1539. // TD_HideForAll(textDraw);
  1540. //}
  1541. //else
  1542. //{
  1543. TD_HideForPlayer(playerid, textDraw);
  1544. //}
  1545. }
  1546. }
  1547. stock TD_HideForPlayer(playerid, Text:textDraw)
  1548. {
  1549. P:3("TD_HideForPlayer called: %i, %i", playerid, _:textDraw);
  1550. if (IsPlayerConnected(playerid))
  1551. {
  1552. // Find the REAL TD for this player from the base TD.
  1553. TDL_START(textDraw)
  1554. {
  1555. if (Text:0 <= textDraw < Text:MAX_TEXT_DRAWS && Bit_GetBit(YSI_g_sPlayerDraws[playerid], _:textDraw))
  1556. {
  1557. // TODO: Update this to find the correct timer.
  1558. /*if (YSI_g_sTDTimers[textDraw][playerid])
  1559. {
  1560. KillTimer(YSI_g_sTDTimers[textDraw][playerid]);
  1561. }
  1562. YSI_g_sTDTimers[textDraw][playerid] = 0;*/
  1563. //YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] = (count & 0x80000000) | ((count & 0x7FFFFFFF) - 1);
  1564. if (--YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] == 0x80000000)
  1565. {
  1566. // No-one uses this any more, destroy it. Looking back on
  1567. // the code, this doesn't seem well implemented at all!
  1568. // Actually itis, ignore me. I forgot that you have to
  1569. // MANUALLY mark TDs as garbage for collection here.
  1570. TD_Destroy(textDraw);
  1571. }
  1572. else
  1573. {
  1574. Bit_Vet(YSI_g_sPlayerDraws[playerid], _:textDraw);
  1575. TextDrawHideForPlayer(playerid, YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REAL]);
  1576. }
  1577. return 1;
  1578. }
  1579. }
  1580. TDL_END(textDraw)
  1581. }
  1582. return 0;
  1583. }
  1584. /*-------------------------------------------------------------------------*//**
  1585. * <param name="textDraw">Text to show to all players.</param>
  1586. *//*------------------------------------------------------------------------**/
  1587. stock TD_ShowForAll(Text:textDraw)
  1588. {
  1589. P:3("TD_ShowForAll called: %i", _:textDraw);
  1590. if (Text:0 <= textDraw < Text:MAX_TEXT_DRAWS)
  1591. {
  1592. new
  1593. Text:real = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REAL],
  1594. Style:style = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_STYLE];
  1595. // This may have lost it's real rendering
  1596. if (real == Text:INVALID_TEXT_DRAW)
  1597. {
  1598. if (!YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_TEXT][0])
  1599. {
  1600. // There is no text to render.
  1601. return 0;
  1602. }
  1603. real = TD_Render(YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_TEXT], style, textDraw);
  1604. if (real == Text:INVALID_TEXT_DRAW)
  1605. {
  1606. return 0;
  1607. }
  1608. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REAL] = real;
  1609. }
  1610. TextDrawShowForAll(real);
  1611. new
  1612. count = 0,
  1613. index = Bit_Slot(textDraw),
  1614. Bit:mod = Bit_Mask(textDraw),
  1615. time = YSI_g_sTDData[style][E_TD_DATA_TIME],
  1616. revision = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REVISION];
  1617. FOREACH__ (new playerid : Player)
  1618. {
  1619. // Count the number of players with this TD (destroy it if none).
  1620. YSI_g_sPlayerDraws[playerid][index] |= mod;
  1621. ++count;
  1622. if (time)
  1623. {
  1624. TD_SetTimer(playerid, textDraw, time, revision);
  1625. }
  1626. }
  1627. if (count)
  1628. {
  1629. // People can see it.
  1630. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] = (YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] & 0x80000000) | count;
  1631. }
  1632. else
  1633. {
  1634. TD_TryDestroy(textDraw);
  1635. }
  1636. return 1;
  1637. //}
  1638. }
  1639. return 0;
  1640. }
  1641. /*-------------------------------------------------------------------------*//**
  1642. * <param name="textDraw">Text to hide from all players.</param>
  1643. * <remarks>
  1644. * Destroys the real text draw if marked for garbage collection.
  1645. *
  1646. * Hides all linked TDs.
  1647. * </remarks>
  1648. *//*------------------------------------------------------------------------**/
  1649. stock TD_HideForAll(Text:textDraw)
  1650. {
  1651. P:3("TD_HideForAll called: %i", _:textDraw);
  1652. if (Text:0 <= textDraw < Text:MAX_TEXT_DRAWS)
  1653. {
  1654. TDL_START(textDraw)
  1655. {
  1656. new
  1657. Text:real = YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REAL];
  1658. if (!TD_TryDestroy(textDraw))
  1659. {
  1660. if (real != Text:INVALID_TEXT_DRAW)
  1661. {
  1662. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] = 0;
  1663. new
  1664. index = Bit_Slot(textDraw),
  1665. Bit:inv = ~Bit_Mask(textDraw);//,
  1666. //Bit:inv = ~mod;
  1667. // Hide it for all players but don't destroy it.
  1668. TextDrawHideForAll(real);
  1669. ++YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REVISION];
  1670. FOREACH__ (new playerid : Player)
  1671. {
  1672. YSI_g_sPlayerDraws[playerid][index] &= inv;
  1673. }
  1674. }
  1675. }
  1676. }
  1677. TDL_END(textDraw)
  1678. }
  1679. return 1;
  1680. }
  1681. /*-------------------------------------------------------------------------*//**
  1682. * <param name="playerid">Player who left.</param>
  1683. * <param name="reason">Why they left.</param>
  1684. * <remarks>
  1685. * Required to fix bugs in the textdraw system by hiding all
  1686. * visible ones.
  1687. * </remarks>
  1688. *//*------------------------------------------------------------------------**/
  1689. HOOK__ OnPlayerDisconnect(playerid, reason)
  1690. {
  1691. for (new i = 0; i < bits<_:MAX_TEXT_DRAWS>; i++)
  1692. {
  1693. new
  1694. Bit:s = YSI_g_sPlayerDraws[playerid][i],
  1695. j = 0,
  1696. ix = i << 5;
  1697. while (s)
  1698. {
  1699. // Get rid of data for textdraws which this player can see. We
  1700. // don't need to actually hide the textdraw as the player has left.
  1701. if (s & Bit:1)
  1702. {
  1703. new
  1704. Text:textDraw = Text:(ix + j);
  1705. /*if (YSI_g_sTDTimers[textDraw][playerid])
  1706. {
  1707. // TODO: Update.
  1708. KillTimer(YSI_g_sTDTimers[textDraw][playerid]);
  1709. YSI_g_sTDTimers[textDraw][playerid] = 0;
  1710. }*/
  1711. if (--YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] == 0x80000000)
  1712. {
  1713. TD_Destroy(textDraw);
  1714. }
  1715. //TD_TryDestroy(textDraw);
  1716. }
  1717. s >>>= Bit:1;
  1718. ++j;
  1719. }
  1720. YSI_g_sPlayerDraws[playerid][i] = Bit:0;
  1721. }
  1722. }
  1723. /*-------------------------------------------------------------------------*//**
  1724. * <param name="textDraw">Text to mark as garbage.</param>
  1725. * <remarks>
  1726. * Tells the system to remove a text draw when no-one can see it
  1727. * anymore to free up text draw slots.
  1728. *
  1729. * Note that linked TDs don't share garbage status. This is because I said so,
  1730. * not for any good reason (other that I can't be bothered to code it up).
  1731. * Ergo this behaviour is a feature, not a bug!
  1732. * </remarks>
  1733. *//*------------------------------------------------------------------------**/
  1734. stock TD_Garbage(Text:textDraw)
  1735. {
  1736. P:3("TD_Garbage called: %i", _:textDraw);
  1737. if (Text:0 <= textDraw < Text:MAX_TEXT_DRAWS)
  1738. {
  1739. if (YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] & 0x7FFFFFFF)
  1740. {
  1741. // Players can still see it.
  1742. YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_LIFE] |= 0x80000000;
  1743. }
  1744. else
  1745. {
  1746. // No-one can see it.
  1747. TD_Destroy(textDraw);
  1748. }
  1749. }
  1750. }
  1751. /*-------------------------------------------------------------------------*//**
  1752. * <param name="textDraw">Text to morph from it's current style to another style.</param>
  1753. * <param name="style">The style to morph to.</param>
  1754. * <param name="time">The time to take in this morph.</param>
  1755. * <param name="delay">In how long to start this morph (default now).</param>
  1756. * <remarks>
  1757. * Entry point for changing the apperance of a text draw to look like another
  1758. * one. How smooth this is depends on the difference and the time given. The
  1759. * default update time is 50ms (20fps), which isn't too bad. Don't modify
  1760. * revision versions in here as if there is a hide timer, it still applies
  1761. * regardless of what style is currently applied.
  1762. *
  1763. * No longer takes a playerid parameter - it's just tough but easy to work
  1764. * around using y_text.
  1765. * </remarks>
  1766. *//*------------------------------------------------------------------------**/
  1767. #if !defined Y_TD_FRAME_TIME
  1768. #define Y_TD_FRAME_TIME 50
  1769. #endif
  1770. forward TD_MorphTDInternal(Text:td, Style:from, Style:to, speed, pos, revision);
  1771. stock TD_Morph(Text:textDraw, Style:style, time, delay = 0)
  1772. {
  1773. P:2("TD_Morph called: %d %d", TD_IsValidStyle(style), _TD_TextValid(textDraw));
  1774. if (TD_IsValidStyle(style) && _TD_TextValid(textDraw))
  1775. {
  1776. //FOREACH__ (new playerid : PS(players))
  1777. //{
  1778. //TD_MorphInternal(playerid, textDraw, style);
  1779. SetTimerEx("TD_MorphTDInternal", delay + Y_TD_FRAME_TIME, 0, "iiiiii", _:textDraw, _:TD_GetDisplayStyle(textDraw), _:style, time, Y_TD_FRAME_TIME, YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REVISION]); //, YSI_g_sTDDisplay[textDraw][E_TD_DISPLAY_REAL]);
  1780. //SetTimerEx("TD_MorphTDInternal", delay + Y_TD_FRAME_TIME, 0, "iiiiii", _:textDraw, TD_GetDisplayStyle());
  1781. //}
  1782. return 1;
  1783. }
  1784. return 0;
  1785. }
  1786. public TD_MorphTDInternal(Text:td, Style:from, Style:to, speed, pos, revision)
  1787. {
  1788. P:2("TD_MorphTDInternal called: %d %d %d %d %d %d", _:td, _:from, _:to, speed, pos, revision);
  1789. if (!(Text:0 <= td < Text:MAX_TEXT_DRAWS))
  1790. {
  1791. return 0;
  1792. }
  1793. if (YSI_g_sTDDisplay[td][E_TD_DISPLAY_REVISION] != revision)
  1794. {
  1795. return 0;
  1796. }
  1797. static
  1798. sFrom[E_TD_DATA],
  1799. sTo[E_TD_DATA];
  1800. // Get the current style data.
  1801. TD_GetStyleData(to, sTo);
  1802. new
  1803. Text:real,
  1804. index,
  1805. Bit:mask;
  1806. if (pos >= speed)
  1807. {
  1808. // We could add a callback here to indicate that the morph is done.
  1809. // Note that the callback should be BEFORE the TDL loop to include the
  1810. // correct "td" value.
  1811. // Show the TD using the end point only (no interpolation).
  1812. new
  1813. Float:x = sTo[E_TD_DATA_X] - YSI_g_sTDDisplay[td][E_TD_DISPLAY_X],
  1814. Float:y = sTo[E_TD_DATA_Y] - YSI_g_sTDDisplay[td][E_TD_DISPLAY_Y];
  1815. TDL_START(td)
  1816. {
  1817. // Hide this TD for everyone.
  1818. new
  1819. Text:old = YSI_g_sTDDisplay[td][E_TD_DISPLAY_REAL];
  1820. //TextDrawDestroy(real);
  1821. // Render the new version.
  1822. real = TD_RenderInternal(YSI_g_sTDDisplay[td][E_TD_DISPLAY_TEXT], sTo, YSI_g_sTDDisplay[td][E_TD_DISPLAY_X] + x, YSI_g_sTDDisplay[td][E_TD_DISPLAY_Y] + y);
  1823. // Show for all players who had it before.
  1824. index = Bit_Slot(_:td);
  1825. mask = Bit_Mask(_:td);
  1826. FOREACH__ (new playerid : Player)
  1827. {
  1828. if (YSI_g_sPlayerDraws[playerid][index] & mask)
  1829. {
  1830. TextDrawShowForPlayer(playerid, real);
  1831. }
  1832. }
  1833. // Only update the new location pointer. Things like garbage
  1834. // status stay the same as the TD is technically still visible
  1835. // (even if they are fading it out).
  1836. TextDrawDestroy(old);
  1837. YSI_g_sTDDisplay[td][E_TD_DISPLAY_REAL] = real;
  1838. }
  1839. TDL_END(td)
  1840. }
  1841. else
  1842. {
  1843. // Get the BASE position (linked TDs move REALTIVE to this one, as
  1844. // location is not a style parameter).
  1845. new
  1846. Float:x = (sTo[E_TD_DATA_X] - YSI_g_sTDDisplay[td][E_TD_DISPLAY_X]) * pos / speed,
  1847. Float:y = (sTo[E_TD_DATA_Y] - YSI_g_sTDDisplay[td][E_TD_DISPLAY_Y]) * pos / speed;
  1848. TD_GetStyleData(from, sFrom);
  1849. // Calculate how far between the morph stages we are.
  1850. #define MORPH_TD_FROM_TO(%0) sFrom[E_TD_DATA_%0] += (sTo[E_TD_DATA_%0] - sFrom[E_TD_DATA_%0]) * pos / speed
  1851. MORPH_TD_FROM_TO(LX);
  1852. MORPH_TD_FROM_TO(LY);
  1853. MORPH_TD_FROM_TO(TX);
  1854. MORPH_TD_FROM_TO(TY);
  1855. MORPH_TD_FROM_TO(COLOUR);
  1856. //MORPH_TD_FROM_TO(BITS);
  1857. sFrom[E_TD_DATA_BITS] += e_TD_BITS:(_:(sTo[E_TD_DATA_BITS] - sFrom[E_TD_DATA_BITS]) * pos / speed);
  1858. MORPH_TD_FROM_TO(BOX);
  1859. MORPH_TD_FROM_TO(BG);
  1860. #undef MORPH_TD_FROM_TO
  1861. // Loop through all linked TDs and show them to all players.
  1862. TDL_START(td)
  1863. {
  1864. //printf("TDL_Start");
  1865. // Hide this TD for everyone.
  1866. new
  1867. Text:old = YSI_g_sTDDisplay[td][E_TD_DISPLAY_REAL];
  1868. //printf("Destroyed");
  1869. // Render the new version.
  1870. real = TD_RenderInternal(YSI_g_sTDDisplay[td][E_TD_DISPLAY_TEXT], sFrom, YSI_g_sTDDisplay[td][E_TD_DISPLAY_X] + x, YSI_g_sTDDisplay[td][E_TD_DISPLAY_Y] + y);
  1871. printf("New real: %d %f %f", _:real, YSI_g_sTDDisplay[td][E_TD_DISPLAY_X] + x, YSI_g_sTDDisplay[td][E_TD_DISPLAY_Y] + y);
  1872. // Show for all players who had it before.
  1873. index = Bit_Slot(_:td);
  1874. mask = Bit_Mask(_:td);
  1875. FOREACH__ (new playerid : Player)
  1876. {
  1877. //printf("player %d");
  1878. if (YSI_g_sPlayerDraws[playerid][index] & mask)
  1879. {
  1880. //printf("yes");
  1881. TextDrawShowForPlayer(playerid, real);
  1882. }
  1883. }
  1884. TextDrawDestroy(old);
  1885. // Only update the new location pointer. Things like garbage
  1886. // status stay the same as the TD is technically still visible
  1887. // (even if they are fading it out).
  1888. YSI_g_sTDDisplay[td][E_TD_DISPLAY_REAL] = real;
  1889. }
  1890. TDL_END(td)
  1891. // Even though "td" changes in the loop, the end condition is that "td"
  1892. // is the same as when the loop started, meaning that it's fine to reuse
  1893. // it here.
  1894. SetTimerEx("TD_MorphTDInternal", Y_TD_FRAME_TIME, false, "iiiiii", _:td, _:from, _:to, speed, pos + Y_TD_FRAME_TIME, revision);
  1895. }
  1896. return 1;
  1897. }
  1898. #undef TDL_START
  1899. #undef TDL_END