antiCash.inc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /*
  2. native GetPlayerCash(playerid);
  3. native GivePlayerCash(playerid, amount);
  4. native ResetPlayerCash(playerid);
  5. */
  6. new PlayerMoney[MAX_PLAYERS];
  7. forward GetPlayerCash(playerid);
  8. public GetPlayerCash(playerid)
  9. {
  10. return PlayerMoney[playerid];
  11. }
  12. forward GivePlayerCash(playerid, amount);
  13. public GivePlayerCash(playerid, amount)
  14. {
  15. PlayerMoney[playerid] += amount;
  16. return UpdateMoney(playerid);
  17. }
  18. forward ResetPlayerCash(playerid);
  19. public ResetPlayerCash(playerid)
  20. {
  21. PlayerMoney[playerid] = 0;
  22. return UpdateMoney(playerid);
  23. }
  24. // TimerFix v2 beta by Slice
  25. #if !defined _samp_included
  26. #error Please include a_samp before Timer Fix.
  27. #endif
  28. #if !defined TIMER_FIX_TICK_INTERVAL
  29. #define TIMER_FIX_TICK_INTERVAL 5
  30. #endif
  31. #if !defined TIMER_FIX_TIMER_SLOTS
  32. #define TIMER_FIX_TIMER_SLOTS 128
  33. #endif
  34. #if !defined TIMER_FIX_MAX_ARGUMENTS
  35. #define TIMER_FIX_MAX_ARGUMENTS 32
  36. #endif
  37. #if !defined TIMER_FIX_PERFORMANCE_CHECKS
  38. #define TIMER_FIX_PERFORMANCE_CHECKS true
  39. #endif
  40. #if !defined TIMER_FIX_DEBUG
  41. #define TIMER_FIX_DEBUG false
  42. #endif
  43. #define TF:: TF_
  44. enum TF::e_TIMER {
  45. bool:e_bIsUsed,
  46. e_iNumArguments,
  47. e_axArguments[TIMER_FIX_MAX_ARGUMENTS],
  48. #if TIMER_FIX_DEBUG
  49. e_aiArgumentTypes[TIMER_FIX_MAX_ARGUMENTS],
  50. #endif
  51. e_iFunctionAddress,
  52. e_szFunctionName[32],
  53. e_iInterval,
  54. e_iNextCall,
  55. bool:e_bIsRepeating
  56. };
  57. static
  58. #if TIMER_FIX_DEBUG
  59. TF::gs_szDebugBuffer[512],
  60. #endif
  61. TF::gs_Timers[TIMER_FIX_TIMER_SLOTS][TF::e_TIMER],
  62. TF::gs_iCurrentTimer = -1
  63. ;
  64. // Fix for y_timers
  65. #define _Timer_C(O@ _Timer_C(SetTimerEx
  66. stock SetTimerHook(const szFunctionName[], iInterval, {bool, _}:bRepeating, const szFormat[] = !"", {_, PlayerText3D, Text, Text3D, Menu, DB, DBResult, File, Float}:...) {
  67. static
  68. bool:s_bTimerTickTimerStarted = false
  69. ;
  70. if (!s_bTimerTickTimerStarted) {
  71. SetTimer(!"TF_TimerTick", TIMER_FIX_TICK_INTERVAL, true);
  72. s_bTimerTickTimerStarted = true;
  73. }
  74. new
  75. iSlot = -1
  76. ;
  77. for (new i = 0; i < sizeof(TF::gs_Timers); i++) {
  78. if (!TF::gs_Timers[i][e_bIsUsed]) {
  79. iSlot = i;
  80. break;
  81. }
  82. }
  83. if (iSlot == -1) {
  84. print(!"(TimerFix) ERROR: Ran out of timer slots. Increase TIMER_FIX_TIMER_SLOTS (current value: " #TIMER_FIX_TIMER_SLOTS ").");
  85. return -1;
  86. }
  87. if (!(TF::gs_Timers[iSlot][e_iFunctionAddress] = TF::GetPublicFunctionAddress(szFunctionName))) {
  88. new
  89. szFunctionNameUnpacked[32]
  90. ;
  91. strunpack(szFunctionNameUnpacked, szFunctionName);
  92. printf("(TimerFix) ERROR: Invalid function (\"%s\").", szFunctionNameUnpacked);
  93. return -1;
  94. }
  95. new
  96. #if TIMER_FIX_DEBUG
  97. bool:bFormatIsPacked = ispacked(szFormat),
  98. #endif
  99. iNumArgs = max(0, numargs() - 4)
  100. ;
  101. if (iNumArgs != strlen(szFormat)) {
  102. new
  103. szFormatUnpacked[128 char]
  104. ;
  105. strunpack(szFormatUnpacked, szFormat);
  106. printf("(TimerFix) ERROR: The number of arguments (%d) doesn't match the number of arguments in the format specifier (\"%s\").", iNumArgs, szFormatUnpacked);
  107. return -1;
  108. }
  109. TF::gs_Timers[iSlot][e_bIsUsed] = true;
  110. TF::gs_Timers[iSlot][e_bIsRepeating] = bRepeating;
  111. TF::gs_Timers[iSlot][e_iInterval] = iInterval;
  112. TF::gs_Timers[iSlot][e_iNextCall] = GetTickCount() + iInterval;
  113. TF::gs_Timers[iSlot][e_iNumArguments] = iNumArgs;
  114. strunpack(TF::gs_Timers[iSlot][e_szFunctionName], szFunctionName, 32);
  115. for (new i = 0; i < iNumArgs; i++) {
  116. TF::gs_Timers[iSlot][e_axArguments][i] = getarg(4 + i);
  117. #if TIMER_FIX_DEBUG
  118. TF::gs_Timers[iSlot][e_aiArgumentTypes][i] = bFormatIsPacked ? szFormat{i} : szFormat[i];
  119. #endif
  120. }
  121. #if TIMER_FIX_DEBUG
  122. printf("(TimerFix) DEBUG: Timer created; %d = \"%s\".", iSlot, TF::gs_Timers[iSlot][e_szFunctionName]);
  123. #endif
  124. return iSlot;
  125. }
  126. stock KillTimerHook(iTimer) {
  127. if (0 <= iTimer < sizeof(TF::gs_Timers)) {
  128. if (TF::gs_Timers[iTimer][e_bIsUsed]) {
  129. TF::gs_Timers[iTimer][e_bIsUsed] = false;
  130. #if TIMER_FIX_DEBUG
  131. printf("(TimerFix) DEBUG: Killed timer %d (\"%s\").", iTimer, TF::gs_Timers[iTimer][e_szFunctionName]);
  132. #endif
  133. return true;
  134. }
  135. }
  136. #if TIMER_FIX_DEBUG
  137. printf("(TimerFix) DEBUG: Failed to kill timer %d; not in use / invalid id.", iTimer);
  138. #endif
  139. return false;
  140. }
  141. #define SetTimer SetTimerHook
  142. #define SetTimerEx SetTimerHook
  143. #define KillTimer KillTimerHook
  144. stock KillThisTimer() {
  145. if (TF::gs_iCurrentTimer != -1)
  146. KillTimer(TF::gs_iCurrentTimer);
  147. }
  148. forward TF::TimerTick();
  149. public TF::TimerTick() {
  150. new
  151. iTick,
  152. iFunc,
  153. iArg,
  154. i, j
  155. ;
  156. if (TF::gs_iCurrentTimer != -1) {
  157. printf("(TimerFix) ERROR: The function \"%s\" didn't properly execute, some timers might not have been called.", TF::gs_Timers[TF::gs_iCurrentTimer][e_szFunctionName]);
  158. TF::gs_iCurrentTimer = -1;
  159. }
  160. for (i = 0; i < sizeof(TF::gs_Timers); i++) {
  161. if (!TF::gs_Timers[i][e_bIsUsed])
  162. continue;
  163. if ((iTick = GetTickCount()) >= TF::gs_Timers[i][e_iNextCall]) {
  164. iFunc = TF::gs_Timers[i][e_iFunctionAddress];
  165. // This is done before and after execution, in case execution fails
  166. if (TF::gs_Timers[i][e_bIsRepeating])
  167. TF::gs_Timers[i][e_iNextCall] = iTick + TF::gs_Timers[i][e_iInterval] - 1;
  168. #if TIMER_FIX_DEBUG
  169. TF::PrintFunctionCall(i);
  170. #endif
  171. j = TF::gs_Timers[i][e_iNumArguments];
  172. TF::gs_iCurrentTimer = i;
  173. // Push the arguments
  174. while (--j >= 0) {
  175. #emit CONST.alt TF_gs_Timers
  176. #emit LOAD.S.pri i
  177. #emit IDXADDR
  178. #emit MOVE.alt
  179. #emit LOAD.I
  180. #emit ADD
  181. #emit ADD.C 8 // e_axArguments * 4
  182. #emit MOVE.alt
  183. #emit LOAD.S.pri j
  184. #emit IDXADDR
  185. #emit LOAD.I
  186. #emit PUSH.pri
  187. }
  188. // Push the number of arguments
  189. iArg = TF::gs_Timers[i][e_iNumArguments] * 4;
  190. #emit PUSH.S iArg
  191. // Push the return address
  192. #emit LCTRL 6
  193. #emit ADD.C 28
  194. #emit PUSH.pri
  195. // Call the function
  196. #emit LOAD.S.pri iFunc
  197. #emit SCTRL 6
  198. #if TIMER_FIX_PERFORMANCE_CHECKS
  199. if (GetTickCount() - iTick > 10) {
  200. }
  201. #endif
  202. if (TF::gs_Timers[i][e_bIsRepeating])
  203. TF::gs_Timers[i][e_iNextCall] = GetTickCount() + TF::gs_Timers[i][e_iInterval] - 1;
  204. else {
  205. TF::gs_Timers[i][e_bIsUsed] = false;
  206. #if TIMER_FIX_DEBUG
  207. printf("(TimerFix) DEBUG: Timer %d (\"%s\") finished.", i, TF::gs_Timers[i][e_szFunctionName]);
  208. #endif
  209. }
  210. TF::gs_iCurrentTimer = -1;
  211. }
  212. }
  213. }
  214. stock TF::PrintFunctionCall(i) {
  215. format(TF::gs_szDebugBuffer, sizeof(TF::gs_szDebugBuffer), "(TimerFix) DEBUG: Calling: %s(", TF::gs_Timers[i][e_szFunctionName]);
  216. for (new j = 0; j < TF::gs_Timers[i][e_iNumArguments]; j++) {
  217. if (j)
  218. strcat(TF::gs_szDebugBuffer, ", ");
  219. switch (TF::gs_Timers[i][e_aiArgumentTypes][j]) {
  220. case 'f', 'F':
  221. format(TF::gs_szDebugBuffer, sizeof(TF::gs_szDebugBuffer), "%s%.2f", TF::gs_szDebugBuffer, TF::gs_Timers[i][e_axArguments][j]);
  222. default:
  223. format(TF::gs_szDebugBuffer, sizeof(TF::gs_szDebugBuffer), "%s%d", TF::gs_szDebugBuffer, TF::gs_Timers[i][e_axArguments][j]);
  224. }
  225. }
  226. strcat(TF::gs_szDebugBuffer, ")");
  227. print(TF::gs_szDebugBuffer);
  228. }
  229. stock TF::GetPublicFunctionAddress(const szName[]) {
  230. new
  231. iIndex,
  232. iTemp
  233. ;
  234. if (-1 != (iIndex = funcidx(szName))) {
  235. // Load the offset to DAT from the prefix
  236. #emit LCTRL 1
  237. // Invert it so we have the offset to the prefix from DAT
  238. #emit NEG
  239. // Copy it to alt for use later
  240. #emit MOVE.alt
  241. // Add 32 to jump to the offset containing the public function's table
  242. #emit ADD.C 32
  243. // Read the value there; must be done using LREF because
  244. // it's outside of the DAT section
  245. #emit STOR.S.pri iTemp
  246. #emit LREF.S.pri iTemp
  247. // Add the value we just loaded to the prefix (that we stored in alt)
  248. #emit ADD
  249. // Add index * 8 (each entry contains 2 cells - a pointer to the function's name
  250. // and a pointer to the function itself, relative to COD).
  251. #emit LOAD.S.alt iIndex
  252. #emit SHL.C.alt 3
  253. // Add that to the offset
  254. #emit ADD
  255. // Now get the address it's pointing to. This seems to only work
  256. // using LREF (as opposed to LOAD.I, for example).
  257. #emit STOR.S.pri iTemp
  258. #emit LREF.S.pri iTemp
  259. // Restore the stack
  260. #emit STACK 8
  261. // Return the address
  262. #emit RETN
  263. }
  264. return 0;
  265. }