You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

394 lines
8.0 KiB

  1. #include <stdlib.h>
  2. #include "types.h"
  3. #include "util.h"
  4. #include "Bill.h"
  5. #include "Computer.h"
  6. #include "Game.h"
  7. #include "Horde.h"
  8. #include "Network.h"
  9. #include "OS.h"
  10. #include "UI.h"
  11. /* speed at which OS drops */
  12. #define GRAVITY 3
  13. /* speed of moving Bill */
  14. #define SLOW 0
  15. #define FAST 1
  16. #define WCELS 4 /* # of bill walking animation frames */
  17. #define DCELS 5 /* # of bill dying animation frames */
  18. #define ACELS 13 /* # of bill switching OS frames */
  19. static Picture *lcels[WCELS], *rcels[WCELS], *acels[ACELS], *dcels[DCELS];
  20. static int width, height;
  21. static void
  22. get_border(int *x, int *y) {
  23. int i = RAND(0, 3);
  24. int screensize = Game_screensize();
  25. if (i % 2 == 0)
  26. *x = RAND(0, screensize - width);
  27. else
  28. *y = RAND(0, screensize - height);
  29. switch (i) {
  30. case 0:
  31. *y = -height - 16;
  32. break;
  33. case 1:
  34. *x = screensize + 1;
  35. break;
  36. case 2:
  37. *y = screensize + 1;
  38. break;
  39. case 3:
  40. *x = - width - 2;
  41. break;
  42. }
  43. }
  44. /* Adds a bill to the in state */
  45. void
  46. Bill_enter(Bill **billp) {
  47. Bill *bill;
  48. Computer *computer;
  49. bill = xalloc(sizeof *bill);
  50. bill->state = BILL_STATE_IN;
  51. get_border(&bill->x, &bill->y);
  52. bill->index = 0;
  53. bill->cels = lcels;
  54. bill->cargo = OS_WINGDOWS;
  55. bill->x_offset = -2;
  56. bill->y_offset = -15;
  57. bill->target_c = RAND(0, Network_num_computers() - 1);
  58. computer = Network_get_computer(bill->target_c);
  59. bill->target_x = computer->x + Computer_width() - BILL_OFFSET_X;
  60. bill->target_y = computer->y + BILL_OFFSET_Y;
  61. Horde_inc_counter(HORDE_COUNTER_ON, 1);
  62. Horde_inc_counter(HORDE_COUNTER_OFF, -1);
  63. bill->prev = NULL;
  64. bill->next = NULL;
  65. *billp = bill;
  66. }
  67. static int
  68. step_size(unsigned int level) {
  69. return MIN(11 + level, 15);
  70. }
  71. /* Moves bill toward his target - returns whether or not he moved */
  72. static int
  73. move(Bill *bill, int mode) {
  74. int xdist = bill->target_x - bill->x;
  75. int ydist = bill->target_y - bill->y;
  76. int step = step_size(Game_level());
  77. int dx, dy;
  78. int signx = xdist >= 0 ? 1 : -1;
  79. int signy = ydist >= 0 ? 1 : -1;
  80. xdist = abs(xdist);
  81. ydist = abs(ydist);
  82. if (!xdist && !ydist)
  83. return 0;
  84. else if (xdist < step && ydist < step) {
  85. bill->x = bill->target_x;
  86. bill->y = bill->target_y;
  87. }
  88. else {
  89. dx = (xdist*step*signx)/(xdist+ydist);
  90. dy = (ydist*step*signy)/(xdist+ydist);
  91. if (mode == FAST) {
  92. dx *= 1.25;
  93. dy *= 1.25;
  94. }
  95. bill->x += dx;
  96. bill->y += dy;
  97. if (dx < 0)
  98. bill->cels = lcels;
  99. else if (dx > 0)
  100. bill->cels = rcels;
  101. }
  102. return 1;
  103. }
  104. static void
  105. draw_std(Bill *bill) {
  106. if (bill->cargo >= 0)
  107. OS_draw(bill->cargo, bill->x + bill->x_offset,
  108. bill->y + bill->y_offset);
  109. UI_draw(bill->cels[bill->index], bill->x, bill->y);
  110. }
  111. static void
  112. draw_at(Bill *bill) {
  113. Computer *computer = Network_get_computer(bill->target_c);
  114. if (bill->index > 6 && bill->index < 12)
  115. OS_draw(0, bill->x + bill->sx, bill->y + bill->sy);
  116. if (bill->cargo >= 0)
  117. OS_draw(bill->cargo, bill->x + bill->x_offset,
  118. bill->y + bill->y_offset);
  119. UI_draw(bill->cels[bill->index], computer->x, computer->y);
  120. }
  121. static void
  122. draw_stray(Bill *bill) {
  123. OS_draw(bill->cargo, bill->x, bill->y);
  124. }
  125. void
  126. Bill_draw(Bill *bill) {
  127. switch (bill->state) {
  128. case BILL_STATE_IN:
  129. case BILL_STATE_OUT:
  130. case BILL_STATE_DYING:
  131. draw_std(bill);
  132. break;
  133. case BILL_STATE_AT:
  134. draw_at(bill);
  135. break;
  136. case BILL_STATE_STRAY:
  137. draw_stray(bill);
  138. break;
  139. default:
  140. break;
  141. }
  142. }
  143. /* Update Bill's position */
  144. static void
  145. update_in(Bill *bill) {
  146. int moved = move(bill, SLOW);
  147. Computer *computer = Network_get_computer(bill->target_c);
  148. if (!moved && computer->os != OS_WINGDOWS && !computer->busy) {
  149. computer->busy = 1;
  150. bill->cels = acels;
  151. bill->index = 0;
  152. bill->state = BILL_STATE_AT;
  153. return;
  154. }
  155. else if (!moved) {
  156. int i;
  157. do {
  158. i = RAND(0, Network_num_computers() - 1);
  159. } while (i == bill->target_c);
  160. computer = Network_get_computer(i);
  161. bill->target_c = i;
  162. bill->target_x = computer->x + Computer_width() - BILL_OFFSET_X;
  163. bill->target_y = computer->y + BILL_OFFSET_Y;
  164. }
  165. bill->index++;
  166. bill->index %= WCELS;
  167. bill->y_offset += (8 * (bill->index % 2) - 4);
  168. }
  169. /* Update Bill standing at a computer */
  170. static void
  171. update_at(Bill *bill) {
  172. Computer *computer = Network_get_computer(bill->target_c);
  173. if (bill->index == 0 && computer->os == OS_OFF) {
  174. bill->index = 6;
  175. if (computer->stray == NULL)
  176. bill->cargo = -1;
  177. else {
  178. bill->cargo = computer->stray->cargo;
  179. Horde_remove_bill(computer->stray);
  180. computer->stray = NULL;
  181. }
  182. } else
  183. bill->index++;
  184. if (bill->index == 13) {
  185. bill->y_offset = -15;
  186. bill->x_offset = -2;
  187. get_border(&bill->target_x, &bill->target_y);
  188. bill->index = 0;
  189. bill->cels = lcels;
  190. bill->state = BILL_STATE_OUT;
  191. computer->busy = 0;
  192. return;
  193. }
  194. bill->y_offset = height - OS_height();
  195. switch (bill->index) {
  196. case 1:
  197. case 2:
  198. bill->x -= 8;
  199. bill->x_offset +=8;
  200. break;
  201. case 3:
  202. bill->x -= 10;
  203. bill->x_offset +=10;
  204. break;
  205. case 4:
  206. bill->x += 3;
  207. bill->x_offset -=3;
  208. break;
  209. case 5:
  210. bill->x += 2;
  211. bill->x_offset -=2;
  212. break;
  213. case 6:
  214. if (computer->os != OS_OFF) {
  215. Network_inc_counter(NETWORK_COUNTER_BASE, -1);
  216. Network_inc_counter(NETWORK_COUNTER_OFF, 1);
  217. bill->cargo = computer->os;
  218. }
  219. else {
  220. bill->x -= 21;
  221. bill->x_offset += 21;
  222. }
  223. computer->os = OS_OFF;
  224. bill->y_offset = -15;
  225. bill->x += 20;
  226. bill->x_offset -=20;
  227. break;
  228. case 7:
  229. bill->sy = bill->y_offset;
  230. bill->sx = -2;
  231. break;
  232. case 8:
  233. bill->sy = -15;
  234. bill->sx = -2;
  235. break;
  236. case 9:
  237. bill->sy = -7;
  238. bill->sx = -7;
  239. bill->x -= 8;
  240. bill->x_offset +=8;
  241. break;
  242. case 10:
  243. bill->sy = 0;
  244. bill->sx = -7;
  245. bill->x -= 15;
  246. bill->x_offset +=15;
  247. break;
  248. case 11:
  249. bill->sy = 0;
  250. bill->sx = -7;
  251. computer->os = OS_WINGDOWS;
  252. Network_inc_counter(NETWORK_COUNTER_OFF, -1);
  253. Network_inc_counter(NETWORK_COUNTER_WIN, 1);
  254. break;
  255. case 12:
  256. bill->x += 11;
  257. bill->x_offset -=11;
  258. }
  259. }
  260. /* Updates Bill fleeing with his ill gotten gain */
  261. static void
  262. update_out(Bill *bill) {
  263. int screensize = Game_screensize();
  264. if (UI_intersect(bill->x, bill->y, width, height, 0, 0,
  265. screensize, screensize))
  266. {
  267. move(bill, FAST);
  268. bill->index++;
  269. bill->index %= WCELS;
  270. bill->y_offset += (8*(bill->index%2)-4);
  271. }
  272. else {
  273. Horde_remove_bill(bill);
  274. Horde_inc_counter(HORDE_COUNTER_ON, -1);
  275. Horde_inc_counter(HORDE_COUNTER_OFF, 1);
  276. }
  277. }
  278. /* Updates a Bill who is dying */
  279. static void
  280. update_dying(Bill *bill) {
  281. if (bill->index < DCELS - 1){
  282. bill->y_offset += (bill->index * GRAVITY);
  283. bill->index++;
  284. }
  285. else {
  286. bill->y += bill->y_offset;
  287. if (bill->cargo < 0 || bill->cargo == OS_WINGDOWS)
  288. Horde_remove_bill(bill);
  289. else {
  290. Horde_move_bill(bill);
  291. bill->state = BILL_STATE_STRAY;
  292. }
  293. Horde_inc_counter(HORDE_COUNTER_ON, -1);
  294. }
  295. }
  296. void
  297. Bill_update(Bill *bill) {
  298. switch (bill->state) {
  299. case BILL_STATE_IN:
  300. update_in(bill);
  301. break;
  302. case BILL_STATE_AT:
  303. update_at(bill);
  304. break;
  305. case BILL_STATE_OUT:
  306. update_out(bill);
  307. break;
  308. case BILL_STATE_DYING:
  309. update_dying(bill);
  310. break;
  311. default:
  312. break;
  313. }
  314. }
  315. void
  316. Bill_set_dying(Bill *bill) {
  317. bill->index = -1;
  318. bill->cels = dcels;
  319. bill->x_offset = -2;
  320. bill->y_offset = -15;
  321. bill->state = BILL_STATE_DYING;
  322. }
  323. int
  324. Bill_clicked(Bill *bill, int locx, int locy) {
  325. return (locx > bill->x && locx < bill->x + width &&
  326. locy > bill->y && locy < bill->y + height);
  327. }
  328. int
  329. Bill_clickedstray(Bill *bill, int locx, int locy) {
  330. return (locx > bill->x && locx < bill->x + OS_width() &&
  331. locy > bill->y && locy < bill->y + OS_height());
  332. }
  333. void
  334. Bill_load_pix () {
  335. int i;
  336. for (i = 0; i < WCELS - 1; i++) {
  337. UI_load_picture_indexed("billL", i, 1, &lcels[i]);
  338. UI_load_picture_indexed("billR", i, 1, &rcels[i]);
  339. }
  340. lcels[WCELS - 1] = lcels[1];
  341. rcels[WCELS - 1] = rcels[1];
  342. for (i = 0; i < DCELS; i++)
  343. UI_load_picture_indexed("billD", i, 1, &dcels[i]);
  344. width = UI_picture_width(dcels[0]);
  345. height = UI_picture_height(dcels[0]);
  346. for (i = 0; i < ACELS; i++)
  347. UI_load_picture_indexed("billA", i, 1, &acels[i]);
  348. }
  349. int
  350. Bill_width() {
  351. return width;
  352. }
  353. int
  354. Bill_height() {
  355. return height;
  356. }
  357. int
  358. Bill_get_state(Bill *bill) {
  359. return bill->state;
  360. }