y_td.inc 64 KB

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