PageRenderTime 55ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/object.c

https://code.google.com/p/fit-game/
C | 960 lines | 740 code | 115 blank | 105 comment | 221 complexity | 246321ee276b4b611594f9c5d97aa80e MD5 | raw file
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdbool.h>
  5. #include <SDL/SDL.h>
  6. #include <SDL/SDL_image.h>
  7. #include <SDL/SDL_ttf.h>
  8. #include "object.h"
  9. #include "global.h"
  10. #include "graphic.h"
  11. #include "textures.h"
  12. #include "file.h"
  13. #include "string.h"
  14. #include "game.h"
  15. #include "filesystem.h"
  16. /**
  17. * Deskriptor struktury T_Object pro nacitani/ukladani pres soubor
  18. * - nutno synchronizovat s hlavickou
  19. */
  20. // POZOR: Pridani nejakeho alokovatelneho parametru pak nalezite osetrete v clone_object_base (object.c)
  21. const struct_def_t TDef_Object[] = {
  22. //Menitelne parametry
  23. { "id", P_TYPE_INT32, offsetof(T_Object, id ) },
  24. { "f_id", P_TYPE_INT32_ARRAY, offsetof(T_Object, f_id ) },
  25. { "x", P_TYPE_INT16, offsetof(T_Object, x ) },
  26. { "y", P_TYPE_INT16, offsetof(T_Object, y ) },
  27. { "width", P_TYPE_UINT16, offsetof(T_Object, width ) },
  28. { "height", P_TYPE_UINT16, offsetof(T_Object, height ) },
  29. { "tex_offset_x", P_TYPE_INT16, offsetof(T_Object, tex_offset_x ) },
  30. { "tex_offset_y", P_TYPE_INT16, offsetof(T_Object, tex_offset_y ) },
  31. { "tex_width", P_TYPE_UINT16, offsetof(T_Object, tex_width ) },
  32. { "tex_height", P_TYPE_UINT16, offsetof(T_Object, tex_height ) },
  33. { "texture", P_TYPE_STRING, offsetof(T_Object, texture_name ) },
  34. { "type", P_TYPE_UINT32, offsetof(T_Object, type ) },
  35. { "mode", P_TYPE_UINT32, offsetof(T_Object, mode ) },
  36. { "state", P_TYPE_UINT32, offsetof(T_Object, state ) },
  37. { "phase", P_TYPE_UINT32, offsetof(T_Object, phase ) },
  38. { "v_speed", P_TYPE_INT16, offsetof(T_Object, v_speed ) },
  39. { "h_speed", P_TYPE_INT16, offsetof(T_Object, h_speed ) },
  40. { "msg", P_TYPE_STRING, offsetof(T_Object, msg ) },
  41. { "str", P_TYPE_STRING, offsetof(T_Object, str ) },
  42. { "portable", P_TYPE_UINT8, offsetof(T_Object, portable ) },
  43. { "countdown", P_TYPE_UINT16, offsetof(T_Object, countdown ) },
  44. { "flying", P_TYPE_UINT8, offsetof(T_Object, flying ) },
  45. { "except", P_TYPE_UINT8, offsetof(T_Object, except ) },
  46. { "number", P_TYPE_UINT8, offsetof(T_Object, number ) },
  47. { "resistance", P_TYPE_UINT8, offsetof(T_Object, resistance ) },
  48. { "max_number", P_TYPE_UINT8, offsetof(T_Object, max_number ) },
  49. { "cooldown", P_TYPE_UINT16, offsetof(T_Object, cooldown ) },
  50. { "team", P_TYPE_UINT8, offsetof(T_Object, team ) },
  51. { "turn", P_TYPE_UINT8, offsetof(T_Object, turn ) },
  52. { "speed", P_TYPE_FLOAT, offsetof(T_Object, speed ) },
  53. { "damage", P_TYPE_UINT8, offsetof(T_Object, damage ) },
  54. { "combat", P_TYPE_UINT8, offsetof(T_Object, combat ) },
  55. //tohle presouvat byla hloupost, neulozilo by se do save :/
  56. { "collisions", P_TYPE_UINT8, offsetof(T_Object, collisions ) },
  57. // ALIASY <= tohle jsou pouze reference na vlastnosti nahore
  58. { "hp", P_TYPE_UINT8, offsetof(T_Object, number ) },
  59. { "max_hp", P_TYPE_UINT8, offsetof(T_Object, max_number ) },
  60. //Zarazka
  61. { NULL, P_TYPE_END, sizeof(T_Object) }
  62. };
  63. // INTERNI DATOVE PARAMETRY VSECHNY NULOVAT ZDE!
  64. void zero_object_internal_params(T_Object *object)
  65. {
  66. object->textures = NULL;
  67. object->surface = NULL;
  68. object->ghost = NULL;
  69. object->to_remove = false;
  70. object->has_objects_count = 0;
  71. object->has_objects = NULL;
  72. object->belongs_to_objects_count = 0;
  73. object->belongs_to_objects = NULL;
  74. }
  75. // DEFAULTY EXTERNICH PARAMETRU ZDE:
  76. // NENI TREBA NULOVAT
  77. void set_default_object_external_params(T_Object *object)
  78. {
  79. object->speed = 1;
  80. object->damage = 1;
  81. }
  82. // VSECHNY INTERNI (!) POLOZKY SE MUSI DEALOKOVAT
  83. // EXTERNI SE DEALOKUJI SAMY
  84. void free_object_data(T_Object *object)
  85. {
  86. free_struct_data(object, TDef_Object);
  87. free(object->textures);
  88. free(object->has_objects);
  89. free(object->belongs_to_objects);
  90. }
  91. /* Inicializace objektu, volat az po nacteni textur*/
  92. void init_object(T_Object *object)
  93. {
  94. // Povolime zmenit v levelu vyhodnocovani kolizi, tusim ze se to bude hodit
  95. // Napriklad pruchozi a nepruchozi dekorace ci falesna zed ;)
  96. if(object->collisions == COLLISION_UNDEF)
  97. object->collisions = obj_types[object->type].collisions;
  98. // FIXME: Beretovi se to nelibi, ta velikost objektu dle textury, casem asi zrusit
  99. if(object->textures!=NULL && object->width==0)
  100. {
  101. object->width = object->textures[0]->w;
  102. }
  103. if(object->textures!=NULL && object->height==0)
  104. {
  105. object->height = object->textures[0]->h;
  106. }
  107. if(object->tex_width == 0)
  108. {
  109. object->tex_width = object->width;
  110. }
  111. if(object->tex_height == 0)
  112. {
  113. object->tex_height = object->height;
  114. }
  115. }
  116. /* Nacte soubor do seznamu */
  117. int parser(char *file, T_ObjectList *list, T_Textures_List *tex_list)
  118. {
  119. init_object_list(list);
  120. const int buf_len = 1024;
  121. unsigned int curr_line = 0;
  122. FILE *f = safe_fopen(file, "r");
  123. if (f == NULL)
  124. {
  125. fprintf(stderr, "parser: Cannot open file with level: %s\n", file);
  126. return EXIT_FAILURE;
  127. }
  128. T_Object tmp_object;
  129. char buf[buf_len];
  130. while (fgets(buf, buf_len, f) != NULL)
  131. {
  132. curr_line++;
  133. if (buf[0] == '[')
  134. {
  135. //Nulovani objektu
  136. zero_object(&tmp_object);
  137. if (add_to_object_list(list, &tmp_object) == NULL)
  138. {
  139. //free(buf); //FIXME: momentalne neni dynamicka
  140. free_object_list(list);
  141. fclose(f);
  142. fprintf(stderr, "Couldn't create object\n");
  143. return EXIT_FAILURE;
  144. }
  145. char *close = strchr(buf, ']');
  146. if (close == NULL)
  147. {
  148. close = buf + strlen(buf) - 1;
  149. }
  150. *close = '\0';
  151. char *section = buf + 1;
  152. // identifikovat typ objektu
  153. E_TYPE type;
  154. for (type = 0; type < TYPE_LAST; type++)
  155. {
  156. if (obj_types[type].keyword != NULL)
  157. {
  158. if (!strcmp(section, obj_types[type].keyword))
  159. {
  160. list->last->type = type;
  161. break;
  162. }
  163. }
  164. }
  165. if (type == TYPE_LAST)
  166. {
  167. //free(buf); //momentalne neni dynamicka
  168. free_object_list(list);
  169. fclose(f);
  170. fprintf(stderr, "Bad file (3): %s line %u\n", file, curr_line);
  171. return EXIT_FAILURE;
  172. }
  173. }
  174. else if (list->last != NULL)
  175. {
  176. if (file_load_field(buf, list->last, TDef_Object) < 0)
  177. {
  178. //free(buf); //momentalne neni dynamicka
  179. free_object_list(list);
  180. fclose(f);
  181. fprintf(stderr, "Error reading file: %s\n", file);
  182. return EXIT_FAILURE;
  183. }
  184. }
  185. }
  186. fclose(f);
  187. //Nahrat textury
  188. for (T_Object * item = list->first; item != NULL; item = item->next)
  189. {
  190. if (item->texture_name != NULL)
  191. {
  192. if (update_object_textures(item, tex_list) == EXIT_FAILURE)
  193. {
  194. fprintf(stderr, "parser: Cannot find texture: %s\n", item->texture_name);
  195. free_object_list(list);
  196. return EXIT_FAILURE;
  197. }
  198. init_object(item);
  199. }
  200. }
  201. //Vygenerovani vazeb
  202. if(regenerate_bindings(list) == EXIT_FAILURE)
  203. {
  204. free_object_list(list);
  205. return EXIT_FAILURE;
  206. }
  207. //pro test vazeb mezi objekty
  208. #if DEBUG_PRINT_RELATIONS == 1
  209. print_relations(list);
  210. #endif
  211. return EXIT_SUCCESS;
  212. }
  213. /* Sjednoti list old s list new (podle portable objektu) vcetne textur */
  214. int merge_object_list (const T_ObjectList *old, T_ObjectList *new, T_Textures_List *tex_list)
  215. {
  216. T_Object *n, *p, *o;
  217. T_Object *last = new->last; //ukazatel na posledni objekt v novem seznamu
  218. // konverzni tabulka pro portable objekty - nutne kvuli znovuvytvoreni vazeb mezi nimi v novem levelu
  219. // neprislo mi nutne ji delat dynamickou, 1024 portable objektu do dalsiho levelu uplne staci ;)
  220. #define PORTABLE_MAX 1024
  221. struct
  222. {
  223. int32_t old_id;
  224. int32_t new_id;
  225. } id_table[PORTABLE_MAX];
  226. unsigned int id_table_n = 0;
  227. // prvnim pruchodem pridame do noveho seznamu portable objekty ze stareho seznamu
  228. for(o = old->first; o != NULL; o = o->next)
  229. {
  230. // u hrace najdeme hrace stejneho id v novem listu a jen zmenime nektere parametry
  231. if(o->type == TYPE_PLAYER)
  232. {
  233. p = find_object_by_id(new, o->id);
  234. if(p && p->type == TYPE_PLAYER)
  235. {
  236. if (o->number > p->number) p->number = o->number;
  237. if (o->max_number > p->max_number) p->max_number = o->max_number;
  238. if(p->msg == NULL)
  239. {
  240. p->msg = (char *) malloc(sizeof(char) * (strlen(o->msg) + 1));
  241. if(p->msg)
  242. {
  243. strcpy(p->msg, o->msg);
  244. }
  245. else
  246. {
  247. fprintf(stderr, "merge_object_list(): cannot allocate!\n");
  248. return EXIT_FAILURE;
  249. }
  250. }
  251. }
  252. else
  253. {
  254. fprintf(stderr, "merge_object_list(): cannot find player with id %i in new list!\n", o->id);
  255. return EXIT_FAILURE;
  256. }
  257. }
  258. // jiny objekt, pokud je portable a zaroven except (viditelne a aktivni objekty kopirovat je nesmysl), primo zkopirujem
  259. else if (o->portable && o->except)
  260. {
  261. // clone vygeneruje nove id
  262. if((n = clone_object_base(o, new, tex_list)) == NULL)
  263. {
  264. fprintf(stderr, "merge_object_list(): cannot clone object!\n");
  265. return EXIT_FAILURE;
  266. }
  267. else
  268. {
  269. // musime si zatim poznacit, k cemu objekt ve starem seznamu patri
  270. id_table[id_table_n].old_id = o->id;
  271. id_table[id_table_n].new_id = n->id;
  272. id_table_n++;
  273. if(id_table_n == PORTABLE_MAX)
  274. {
  275. fprintf(stderr, "merge_object_list: portable objects overflow, maximum is %i\n", PORTABLE_MAX);
  276. return EXIT_FAILURE;
  277. }
  278. // neni treba kopirovat, staci ukazovat, nakopiruj pak add_object_relation
  279. n->f_id = o->f_id;
  280. }
  281. }
  282. }
  283. // a ted spravime vazby u novych objektu - celkem porod :)
  284. #define BUF_COUNT_MAX 1024 // buffer kam se zalohuji fg klice, zatim staticky staci
  285. int32_t buf[BUF_COUNT_MAX];
  286. int count = 0;
  287. int old_id = 0;
  288. for(o = last->next; o != NULL; o = o->next)
  289. {
  290. // zapamatujem si f klice objektu
  291. count = 0;
  292. while(o->f_id && o->f_id[count] != 0)
  293. {
  294. buf[count] = o->f_id[count];
  295. count++;
  296. if (count == BUF_COUNT_MAX)
  297. {
  298. fprintf(stderr, "merge_object_list: f_id overflow, maximum is %i\n", BUF_COUNT_MAX);
  299. return EXIT_FAILURE;
  300. }
  301. }
  302. o->f_id = NULL;
  303. // projdeme foreign klice
  304. for (int i = 0; i < count; i++)
  305. {
  306. old_id = 0;
  307. // porovname objekt s nove pridanymi objekty
  308. for(p = last->next; p != NULL; p = p->next)
  309. {
  310. // podle konverzni tabulky zjistime jestli stare id objektu odpovida foreign id
  311. for (unsigned int j = 0; j < id_table_n; j++)
  312. {
  313. if(id_table[j].new_id == p->id)
  314. {
  315. old_id = id_table[j].old_id;
  316. break;
  317. }
  318. }
  319. // foreign klic odpovida id najiteho objektu, objekty sparujeme
  320. if(buf[i] == old_id)
  321. {
  322. if(add_object_relation(o, p) == EXIT_FAILURE)
  323. return EXIT_FAILURE;
  324. break;
  325. }
  326. // old_id objektu nepatri, nulujeme ho
  327. else
  328. old_id = 0;
  329. }
  330. // pro dany foreign klic se zadne old id nenaslo, muze to byt relace s hracem
  331. // hraci se ID nezmenilo
  332. if(old_id == 0)
  333. {
  334. p = find_object_by_id(new, buf[i]);
  335. if (p != NULL && p->type == TYPE_PLAYER)
  336. {
  337. if (add_object_relation(o, p) == EXIT_FAILURE)
  338. return EXIT_FAILURE;
  339. }
  340. // K objektu neni foreign objekt, coz znamena ze foreign objekt neni portable a neprenesl se
  341. // shazovat level je asi prilis tvrde, nicmene stavat by se to asi nemelo
  342. else
  343. {
  344. fprintf(stderr, "merge_object_list: cannot find foreign object in new list\n");
  345. }
  346. }
  347. }
  348. }
  349. return EXIT_SUCCESS;
  350. }
  351. /* Funkce prida polozku na konec seznamu a pokud nema id, doplni mu*/
  352. T_Object* add_to_object_list(T_ObjectList *list, T_Object *data)
  353. {
  354. T_Object *o = (T_Object*) malloc(sizeof(T_Object));
  355. *o = *data;
  356. if (o == NULL)
  357. {
  358. fprintf(stderr, "add_to_object_list: Cannot allocate memory\n");
  359. free_object_list(list);
  360. return NULL;
  361. }
  362. o->next = NULL;
  363. //Seznam jeste nebyl inicializovan, vytvorim ho
  364. if(list->first == NULL)
  365. {
  366. list->first = o;
  367. list->last = o;
  368. o->prev = NULL;
  369. }
  370. //Pridam polozku nakonec
  371. else
  372. {
  373. o->prev = list->last;
  374. list->last->next = o;
  375. list->last = o;
  376. }
  377. //Objekt nema id, nejake mu vymyslim
  378. if(o->id == 0)
  379. {
  380. o->id = list->id;
  381. list->id--;
  382. }
  383. return o;
  384. }
  385. /* Funkce uklidi seznam */
  386. void free_object_list(T_ObjectList *list)
  387. {
  388. T_Object *o;
  389. while(list->first != NULL)
  390. {
  391. o = list->first;
  392. if(o != NULL)
  393. {
  394. free_object_data(o);
  395. }
  396. list->first = list->first->next;
  397. free(o);
  398. }
  399. list->last = NULL;
  400. list->id = -1;
  401. }
  402. /* Funkce najde objekt dle typu */
  403. T_Object *find_object_by_type(T_ObjectList *list, unsigned int type)
  404. {
  405. T_Object *o = list->first;
  406. while(o != NULL)
  407. {
  408. if(o->type == type)
  409. return o;
  410. o = o->next;
  411. }
  412. return NULL;
  413. }
  414. /* Funkce najde objekt podle id */
  415. /* Spise nepouzivat a vyuzivat relace!!! */
  416. T_Object *find_object_by_id(T_ObjectList *list, Sint32 id)
  417. {
  418. T_Object *o = list->first;
  419. while(o != NULL)
  420. {
  421. if(o->id == id)
  422. return o;
  423. o = o->next;
  424. }
  425. return NULL;
  426. }
  427. /* Funkce najde nejvetsi souradnici Y kde je jeste mapa */
  428. unsigned int find_biggest_y(T_ObjectList *list)
  429. {
  430. T_Object *o = list->first;
  431. Sint16 y = list->first->y + list->first->height;
  432. while(o != NULL)
  433. {
  434. if(y < (o->y + o->height))
  435. y = o->y + o->height;
  436. o = o->next;
  437. }
  438. return y;
  439. }
  440. /* Funkce smaze objekt, spoji seznam a vrati ukazatel na nasledujici objekt */
  441. /* Pokud je objekt na konci seznamu, vrati NULL */
  442. /* Pokud objekt nenajde, vrati NULL */
  443. T_Object *destroy_object(T_ObjectList *list, T_Object *object)
  444. {
  445. T_Object *temp;
  446. if(object == NULL)
  447. return NULL;
  448. if(list->first == object)
  449. {
  450. temp = object->next;
  451. list->first = temp;
  452. if (temp != NULL) temp->prev = NULL;
  453. if (list->last == object) list->last = temp;
  454. }
  455. else if(list->last == object)
  456. {
  457. temp=object->prev;
  458. list->last = temp;
  459. if (temp != NULL) temp->next = NULL;
  460. if (list->first == object) list->first = temp;
  461. temp = NULL;
  462. }
  463. else
  464. {
  465. temp = object->next;
  466. if (object->prev != NULL) object->prev->next = temp;
  467. if (temp != NULL) temp->prev = object->prev;
  468. }
  469. free_object_data(object);
  470. free(object);
  471. return temp;
  472. }
  473. /* Funkce vynuluje objekt */
  474. void zero_object(T_Object *object)
  475. {
  476. object->type = TYPE_BLANK;
  477. zero_struct(object, TDef_Object);
  478. zero_object_internal_params(object);
  479. set_default_object_external_params(object);
  480. object->next = NULL;
  481. object->prev = NULL;
  482. }
  483. /* Funkce inicializuje seznam */
  484. void init_object_list(T_ObjectList *list)
  485. {
  486. list->first = NULL;
  487. list->last = NULL;
  488. list->id = -1;
  489. }
  490. /* zaktualizuje texturu objektu podle texture_name */
  491. int update_object_textures(T_Object *object, T_Textures_List *tex_list)
  492. {
  493. if(object->texture_name == 0)
  494. return EXIT_SUCCESS;
  495. if(obj_types[object->type].img_count == 0)
  496. {
  497. fprintf(stderr, "update_object_textures: textures count is zero!");
  498. return EXIT_FAILURE;
  499. }
  500. int t_count = obj_types[object->type].img_count;
  501. T_Textures *tex = get_Textures_for_Map(object->texture_name, t_count, tex_list);
  502. if (object->textures != NULL)
  503. {
  504. // zahodit predchozi textury
  505. free(object->textures);
  506. object->textures = NULL;
  507. }
  508. object->textures = (SDL_Surface**) malloc(sizeof(SDL_Surface*) * t_count);
  509. if (!tex)
  510. {
  511. return EXIT_FAILURE;
  512. }
  513. for (int i = 0; i < t_count; i++)
  514. {
  515. object->textures[i] = tex->images[i];
  516. }
  517. return EXIT_SUCCESS;
  518. }
  519. /* Prida zavislost objektu o1 na objektu o2 */
  520. int add_object_relation(T_Object *o1, T_Object *o2)
  521. {
  522. //Objekt o2 nema id. Objekt o1 mit id nemusi.
  523. if(o2->id == 0)
  524. {
  525. fprintf(stderr, "add_object_relation: Object hasn't id");
  526. return EXIT_FAILURE;
  527. }
  528. // pocet foreign klicu
  529. unsigned int i = 0; while(o1->f_id && o1->f_id[i]) {i++;}
  530. Sint32 *tmp;
  531. // alokace foreign pole
  532. if (i == 0)
  533. {
  534. if(!(o1->f_id = (Sint32*) malloc(sizeof(Sint32) * KEYS_REALLOCATE_COUNT)))
  535. {
  536. fprintf(stderr, "add_object_relation: Cannot allocate memory");
  537. return EXIT_FAILURE;
  538. }
  539. }
  540. i++;
  541. if(i % KEYS_REALLOCATE_COUNT == 0)
  542. {
  543. tmp = o1->f_id;
  544. if(!(o1->f_id = (Sint32*) realloc(o1->f_id, sizeof(Sint32) * (i + KEYS_REALLOCATE_COUNT))))
  545. {
  546. free(tmp);
  547. fprintf(stderr, "add_object_relation: Cannot allocate memory");
  548. return EXIT_FAILURE;
  549. }
  550. }
  551. // pridame foreign klic
  552. o1->f_id[i-1] = o2->id;
  553. o1->f_id[i] = 0;
  554. // upravime vazby
  555. // belongs:
  556. if(allocate_t_objects_array(&o1->belongs_to_objects, o1->belongs_to_objects_count, KEYS_REALLOCATE_COUNT) == EXIT_FAILURE)
  557. return EXIT_FAILURE;
  558. o1->belongs_to_objects[o1->belongs_to_objects_count] = o2;
  559. o1->belongs_to_objects_count++;
  560. // has:
  561. if(allocate_t_objects_array(&o2->has_objects, o2->has_objects_count, KEYS_REALLOCATE_COUNT) == EXIT_FAILURE)
  562. return EXIT_FAILURE;
  563. o2->has_objects[o2->has_objects_count] = o1;
  564. o2->has_objects_count++;
  565. return EXIT_SUCCESS;
  566. }
  567. /* Odstrani zavislost objektu o1 na objetku o2 */
  568. void remove_object_relation(T_Object *o1, T_Object *o2)
  569. {
  570. unsigned int i, j;
  571. for(i = j = 0; i < o2->has_objects_count; i++, j++)
  572. {
  573. if(o2->has_objects[i] == o1)
  574. {
  575. i++;
  576. if(i == o2->has_objects_count) break;
  577. }
  578. o2->has_objects[j] = o2->has_objects[i];
  579. }
  580. if (i != j) o2->has_objects_count--;
  581. for(i = j = 0; i < o1->belongs_to_objects_count; i++, j++)
  582. {
  583. if(o1->belongs_to_objects[i] == o2)
  584. {
  585. i++;
  586. if(i == o1->belongs_to_objects_count) break;
  587. }
  588. o1->belongs_to_objects[j] = o1->belongs_to_objects[i];
  589. }
  590. if (i != j) o1->belongs_to_objects_count--;
  591. i = j = 0;
  592. while(o1->f_id && o1->f_id[i] != 0)
  593. {
  594. if(o2->id && o1->f_id[i] == o2->id)
  595. {
  596. i++;
  597. if(o1->f_id[i] == 0)
  598. break;
  599. }
  600. o1->f_id[j] = o1->f_id[i];
  601. i++; j++;
  602. }
  603. o1->f_id[j] = 0; //zarazka
  604. }
  605. /* Odstrani vsechny zavislosti objektu na jinych objektech*/
  606. void remove_all_object_relations(T_Object *o)
  607. {
  608. while(o->belongs_to_objects_count)
  609. {
  610. remove_object_relation(o, o->belongs_to_objects[0]);
  611. }
  612. while(o->has_objects_count)
  613. {
  614. remove_object_relation(o->has_objects[0], o);
  615. }
  616. }
  617. /* Odstrani objekt, ducha i vsechny zavislosti a vrati ukazatel na dalsi polozku seznamu */
  618. T_Object *destroy_object_and_bindings(T_ObjectList *list, T_Object *object)
  619. {
  620. //odstranit ducha
  621. if(object->ghost)
  622. destroy_object_and_bindings(list, object->ghost);
  623. //odstranit vazby
  624. remove_all_object_relations(object);
  625. //smazat objekt
  626. return destroy_object(list, object);
  627. }
  628. /* OVeri, zda o1 zavisi na o2 */
  629. bool o1_is_depend_on_o2(T_Object *o1, T_Object *o2)
  630. {
  631. for(unsigned int i = 0; i < o1->belongs_to_objects_count; i++)
  632. {
  633. if(o1->belongs_to_objects[i] == o2)
  634. return true;
  635. }
  636. return false;
  637. }
  638. /* Naalokuje ci realokuje pole objektu */
  639. int allocate_t_objects_array(T_Object ***objects, int use, int realloc_count)
  640. {
  641. T_Object **tmp;
  642. //alokace
  643. if(use == 0 && *objects == NULL)
  644. {
  645. *objects = (T_Object**) malloc(sizeof(T_Object*) * realloc_count);
  646. if(*objects == NULL)
  647. {
  648. fprintf(stderr, "allocate_t_objects_array: Cannot allocate memmory!\n");
  649. return EXIT_FAILURE;
  650. }
  651. }
  652. //realokace
  653. else if((use % realloc_count) == 0)
  654. {
  655. tmp = *objects;
  656. *objects = (T_Object**) realloc(*objects, sizeof(T_Object*) * (use + realloc_count));
  657. if (*objects == NULL)
  658. {
  659. fprintf(stderr, "allocate_t_objects_array: Cannot allocate memmory!\n");
  660. free(tmp);
  661. return EXIT_FAILURE;
  662. }
  663. }
  664. return EXIT_SUCCESS;
  665. }
  666. /* Vrati prvni foreign objekt daneho typu */
  667. /* Hodi se pouze tehdy, kdy se vice objektu neocekava / jsou chybou */
  668. T_Object * get_first_foreign_object_by_type(T_Object *object, Uint32 type)
  669. {
  670. for(unsigned int i=0; i<object->belongs_to_objects_count; i++)
  671. {
  672. if(object->belongs_to_objects[i]->type == type)
  673. return object->belongs_to_objects[i];
  674. }
  675. return NULL;
  676. }
  677. /* Vrati prvni vlastni objekt daneho typu */
  678. /* Hodi se pouze tehdy, kdy se vice objektu neocekava / jsou chybou */
  679. T_Object * get_first_own_object_by_type(T_Object *object, Uint32 type)
  680. {
  681. for(unsigned int i=0; i<object->has_objects_count; i++)
  682. {
  683. if(object->has_objects[i]->type == type)
  684. return object->has_objects[i];
  685. }
  686. return NULL;
  687. }
  688. /* Projde vsechny objekty a nastavi jim vazby podle klicu */
  689. /* Melo by stacit volat jen jednou */
  690. int regenerate_bindings(T_ObjectList *list)
  691. {
  692. T_Object *o1, *o2;
  693. o1 = list->first;
  694. unsigned int i;
  695. while(o1 != NULL)
  696. {
  697. o2 = list->first;
  698. o1->has_objects_count = 0;
  699. o1->belongs_to_objects_count = 0;
  700. free(o1->has_objects);
  701. free(o1->belongs_to_objects);
  702. o1->has_objects = NULL;
  703. o1->belongs_to_objects = NULL;
  704. while(o2 != NULL)
  705. {
  706. // stejne objekty
  707. if (o1 == o2)
  708. {
  709. o2 = o2->next;
  710. continue;
  711. }
  712. // poruseni integrity, dva objekty maji stejne id
  713. if (o1->id && o1->id == o2->id)
  714. {
  715. fprintf(stderr, "Integrity error: two objects has same id (%i)\n", o1->id);
  716. return EXIT_FAILURE;
  717. }
  718. // projdu foreign klice objektu o1
  719. i = 0;
  720. while(o1->f_id && o1->f_id[i])
  721. {
  722. // klic odkazuje na objekt o2
  723. if(o1->f_id[i] == o2->id)
  724. {
  725. //alokace
  726. if(allocate_t_objects_array(&o1->belongs_to_objects, o1->belongs_to_objects_count, KEYS_REALLOCATE_COUNT) == EXIT_FAILURE)
  727. return EXIT_FAILURE;
  728. o1->belongs_to_objects[o1->belongs_to_objects_count] = o2;
  729. o1->belongs_to_objects_count++;
  730. }
  731. i++;
  732. }
  733. // projdu foreign klice objektu o2
  734. i = 0;
  735. while(o2->f_id && o2->f_id[i])
  736. {
  737. // klic odkazuje na objekt o1
  738. if(o2->f_id[i] == o1->id)
  739. {
  740. //alokace
  741. if(allocate_t_objects_array(&o1->has_objects, o1->has_objects_count, KEYS_REALLOCATE_COUNT) == EXIT_FAILURE)
  742. return EXIT_FAILURE;
  743. o1->has_objects[o1->has_objects_count] = o2;
  744. o1->has_objects_count++;
  745. }
  746. i++;
  747. }
  748. o2 = o2->next;
  749. }
  750. i = 0; while(o1->f_id && o1->f_id[i]) i++;
  751. //Objekty o2, ke kteremu patri o1 se nepodarilo najit
  752. if (i != o1->belongs_to_objects_count)
  753. {
  754. fprintf(stderr, "Integrity error: object (%i) cannot find some foreign objects\n", o1->id);
  755. return EXIT_FAILURE;
  756. }
  757. o1 = o1->next;
  758. }
  759. return EXIT_SUCCESS;
  760. }
  761. /* Pro debug, vypise relace*/
  762. void print_relations(T_ObjectList *list)
  763. {
  764. printf("DEBUG - relations:\n\n");
  765. T_Object *o = list->first;
  766. while(o)
  767. {
  768. printf("id: %i, type: %s\n", o->id, obj_types[o->type].keyword);
  769. /*
  770. if(o->type == TYPE_PLAYER)
  771. {
  772. printf("\thp: %i, :max_hp: %i %s\n", o->number, o->max_number, o->msg);
  773. }*/
  774. if(o->belongs_to_objects_count) printf("belongs:\n");
  775. for(unsigned int i=0; i < o->belongs_to_objects_count;i++)
  776. printf("\tid: %i, type: %s\n", o->belongs_to_objects[i]->id, obj_types[o->belongs_to_objects[i]->type].keyword);
  777. if(o->has_objects_count) printf("has:\n");
  778. for(unsigned int i =0; i < o->has_objects_count;i++)
  779. printf("\tid: %i, type: %s\n", o->has_objects[i]->id, obj_types[o->has_objects[i]->type].keyword);
  780. int i=0;
  781. if(o->f_id) printf("f_id:\n");
  782. while(o->f_id && o->f_id[i])
  783. {
  784. printf("\tid: %i\n", o->f_id[i]);
  785. i++;
  786. }
  787. printf("=========\n");
  788. o = o->next;
  789. }
  790. }
  791. /* Prepocet souradnic z jedne vztazne soustavy na druhou */
  792. void obj_change_surface(T_Object *o, T_Object *new_surface)
  793. {
  794. Sint16 old_h_speed = o->surface == NULL ? 0 : o->surface->h_speed;
  795. Sint16 old_v_speed = o->surface == NULL ? 0 : o->surface->v_speed;
  796. Sint16 new_h_speed = new_surface == NULL ? 0 : new_surface->h_speed;
  797. Sint16 new_v_speed = new_surface == NULL ? 0 : new_surface->v_speed;
  798. o->h_speed += old_h_speed - new_h_speed;
  799. o->v_speed += old_v_speed - new_v_speed;
  800. o->surface = new_surface;
  801. }
  802. /* Naklonuje objekt vcetne textur krome internich parametru a relaci a vloziho do listu */
  803. T_Object *clone_object_base(T_Object *object, T_ObjectList *list, T_Textures_List *tex_list)
  804. {
  805. T_Object *tmp_object = malloc(sizeof(T_Object));
  806. memcpy(tmp_object, object, sizeof(T_Object));
  807. // Tohle se musi vynulovat, jinak to hezky rachne
  808. zero_object_internal_params(tmp_object);
  809. tmp_object->id = 0;
  810. tmp_object->f_id = NULL;
  811. tmp_object->str = NULL;
  812. tmp_object->msg = NULL;
  813. if(object->str)
  814. {
  815. tmp_object->str = (char*) malloc(sizeof(char) * (strlen(object->str) + 1));
  816. strcpy(tmp_object->str, object->str);
  817. }
  818. if(object->msg)
  819. {
  820. tmp_object->msg = (char*) malloc(sizeof(char) * (strlen(object->msg) + 1));
  821. strcpy(tmp_object->msg, object->msg);
  822. }
  823. if (object->texture_name != NULL)
  824. {
  825. tmp_object->texture_name = (char *) malloc(strlen(object->texture_name)+1);
  826. if (tmp_object->texture_name != NULL)
  827. {
  828. strcpy(tmp_object->texture_name, object->texture_name);
  829. }
  830. else
  831. {
  832. fprintf(stderr, "clone_object: Cannot allocate memory");
  833. exit(1);
  834. }
  835. }
  836. T_Object *inserted_object;
  837. inserted_object = add_to_object_list(list, tmp_object);
  838. free(tmp_object);
  839. if (inserted_object->texture_name != NULL)
  840. {
  841. if (update_object_textures(inserted_object, tex_list) == EXIT_FAILURE)
  842. exit(1);
  843. }
  844. return inserted_object;
  845. }