/src/object.c
C | 960 lines | 740 code | 115 blank | 105 comment | 221 complexity | 246321ee276b4b611594f9c5d97aa80e MD5 | raw file
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdbool.h>
- #include <SDL/SDL.h>
- #include <SDL/SDL_image.h>
- #include <SDL/SDL_ttf.h>
- #include "object.h"
- #include "global.h"
- #include "graphic.h"
- #include "textures.h"
- #include "file.h"
- #include "string.h"
- #include "game.h"
- #include "filesystem.h"
- /**
- * Deskriptor struktury T_Object pro nacitani/ukladani pres soubor
- * - nutno synchronizovat s hlavickou
- */
- // POZOR: Pridani nejakeho alokovatelneho parametru pak nalezite osetrete v clone_object_base (object.c)
- const struct_def_t TDef_Object[] = {
- //Menitelne parametry
- { "id", P_TYPE_INT32, offsetof(T_Object, id ) },
- { "f_id", P_TYPE_INT32_ARRAY, offsetof(T_Object, f_id ) },
- { "x", P_TYPE_INT16, offsetof(T_Object, x ) },
- { "y", P_TYPE_INT16, offsetof(T_Object, y ) },
- { "width", P_TYPE_UINT16, offsetof(T_Object, width ) },
- { "height", P_TYPE_UINT16, offsetof(T_Object, height ) },
- { "tex_offset_x", P_TYPE_INT16, offsetof(T_Object, tex_offset_x ) },
- { "tex_offset_y", P_TYPE_INT16, offsetof(T_Object, tex_offset_y ) },
- { "tex_width", P_TYPE_UINT16, offsetof(T_Object, tex_width ) },
- { "tex_height", P_TYPE_UINT16, offsetof(T_Object, tex_height ) },
- { "texture", P_TYPE_STRING, offsetof(T_Object, texture_name ) },
- { "type", P_TYPE_UINT32, offsetof(T_Object, type ) },
- { "mode", P_TYPE_UINT32, offsetof(T_Object, mode ) },
- { "state", P_TYPE_UINT32, offsetof(T_Object, state ) },
- { "phase", P_TYPE_UINT32, offsetof(T_Object, phase ) },
- { "v_speed", P_TYPE_INT16, offsetof(T_Object, v_speed ) },
- { "h_speed", P_TYPE_INT16, offsetof(T_Object, h_speed ) },
- { "msg", P_TYPE_STRING, offsetof(T_Object, msg ) },
- { "str", P_TYPE_STRING, offsetof(T_Object, str ) },
- { "portable", P_TYPE_UINT8, offsetof(T_Object, portable ) },
- { "countdown", P_TYPE_UINT16, offsetof(T_Object, countdown ) },
- { "flying", P_TYPE_UINT8, offsetof(T_Object, flying ) },
- { "except", P_TYPE_UINT8, offsetof(T_Object, except ) },
- { "number", P_TYPE_UINT8, offsetof(T_Object, number ) },
- { "resistance", P_TYPE_UINT8, offsetof(T_Object, resistance ) },
- { "max_number", P_TYPE_UINT8, offsetof(T_Object, max_number ) },
- { "cooldown", P_TYPE_UINT16, offsetof(T_Object, cooldown ) },
- { "team", P_TYPE_UINT8, offsetof(T_Object, team ) },
- { "turn", P_TYPE_UINT8, offsetof(T_Object, turn ) },
- { "speed", P_TYPE_FLOAT, offsetof(T_Object, speed ) },
- { "damage", P_TYPE_UINT8, offsetof(T_Object, damage ) },
- { "combat", P_TYPE_UINT8, offsetof(T_Object, combat ) },
- //tohle presouvat byla hloupost, neulozilo by se do save :/
- { "collisions", P_TYPE_UINT8, offsetof(T_Object, collisions ) },
- // ALIASY <= tohle jsou pouze reference na vlastnosti nahore
- { "hp", P_TYPE_UINT8, offsetof(T_Object, number ) },
- { "max_hp", P_TYPE_UINT8, offsetof(T_Object, max_number ) },
- //Zarazka
- { NULL, P_TYPE_END, sizeof(T_Object) }
- };
- // INTERNI DATOVE PARAMETRY VSECHNY NULOVAT ZDE!
- void zero_object_internal_params(T_Object *object)
- {
- object->textures = NULL;
- object->surface = NULL;
- object->ghost = NULL;
- object->to_remove = false;
- object->has_objects_count = 0;
- object->has_objects = NULL;
- object->belongs_to_objects_count = 0;
- object->belongs_to_objects = NULL;
- }
- // DEFAULTY EXTERNICH PARAMETRU ZDE:
- // NENI TREBA NULOVAT
- void set_default_object_external_params(T_Object *object)
- {
- object->speed = 1;
- object->damage = 1;
- }
- // VSECHNY INTERNI (!) POLOZKY SE MUSI DEALOKOVAT
- // EXTERNI SE DEALOKUJI SAMY
- void free_object_data(T_Object *object)
- {
- free_struct_data(object, TDef_Object);
- free(object->textures);
- free(object->has_objects);
- free(object->belongs_to_objects);
- }
- /* Inicializace objektu, volat az po nacteni textur*/
- void init_object(T_Object *object)
- {
- // Povolime zmenit v levelu vyhodnocovani kolizi, tusim ze se to bude hodit
- // Napriklad pruchozi a nepruchozi dekorace ci falesna zed ;)
-
- if(object->collisions == COLLISION_UNDEF)
- object->collisions = obj_types[object->type].collisions;
-
- // FIXME: Beretovi se to nelibi, ta velikost objektu dle textury, casem asi zrusit
- if(object->textures!=NULL && object->width==0)
- {
- object->width = object->textures[0]->w;
- }
- if(object->textures!=NULL && object->height==0)
- {
- object->height = object->textures[0]->h;
- }
- if(object->tex_width == 0)
- {
- object->tex_width = object->width;
- }
- if(object->tex_height == 0)
- {
- object->tex_height = object->height;
- }
- }
- /* Nacte soubor do seznamu */
- int parser(char *file, T_ObjectList *list, T_Textures_List *tex_list)
- {
- init_object_list(list);
- const int buf_len = 1024;
- unsigned int curr_line = 0;
- FILE *f = safe_fopen(file, "r");
- if (f == NULL)
- {
- fprintf(stderr, "parser: Cannot open file with level: %s\n", file);
- return EXIT_FAILURE;
- }
- T_Object tmp_object;
- char buf[buf_len];
- while (fgets(buf, buf_len, f) != NULL)
- {
- curr_line++;
-
- if (buf[0] == '[')
- {
- //Nulovani objektu
- zero_object(&tmp_object);
- if (add_to_object_list(list, &tmp_object) == NULL)
- {
- //free(buf); //FIXME: momentalne neni dynamicka
- free_object_list(list);
- fclose(f);
- fprintf(stderr, "Couldn't create object\n");
- return EXIT_FAILURE;
- }
- char *close = strchr(buf, ']');
- if (close == NULL)
- {
- close = buf + strlen(buf) - 1;
- }
- *close = '\0';
- char *section = buf + 1;
- // identifikovat typ objektu
- E_TYPE type;
- for (type = 0; type < TYPE_LAST; type++)
- {
- if (obj_types[type].keyword != NULL)
- {
- if (!strcmp(section, obj_types[type].keyword))
- {
- list->last->type = type;
- break;
- }
- }
- }
- if (type == TYPE_LAST)
- {
- //free(buf); //momentalne neni dynamicka
- free_object_list(list);
- fclose(f);
- fprintf(stderr, "Bad file (3): %s line %u\n", file, curr_line);
- return EXIT_FAILURE;
- }
- }
- else if (list->last != NULL)
- {
- if (file_load_field(buf, list->last, TDef_Object) < 0)
- {
- //free(buf); //momentalne neni dynamicka
- free_object_list(list);
- fclose(f);
- fprintf(stderr, "Error reading file: %s\n", file);
- return EXIT_FAILURE;
- }
- }
- }
- fclose(f);
- //Nahrat textury
- for (T_Object * item = list->first; item != NULL; item = item->next)
- {
- if (item->texture_name != NULL)
- {
- if (update_object_textures(item, tex_list) == EXIT_FAILURE)
- {
- fprintf(stderr, "parser: Cannot find texture: %s\n", item->texture_name);
- free_object_list(list);
- return EXIT_FAILURE;
- }
- init_object(item);
- }
- }
-
- //Vygenerovani vazeb
- if(regenerate_bindings(list) == EXIT_FAILURE)
- {
- free_object_list(list);
- return EXIT_FAILURE;
- }
- //pro test vazeb mezi objekty
- #if DEBUG_PRINT_RELATIONS == 1
- print_relations(list);
- #endif
-
- return EXIT_SUCCESS;
- }
- /* Sjednoti list old s list new (podle portable objektu) vcetne textur */
- int merge_object_list (const T_ObjectList *old, T_ObjectList *new, T_Textures_List *tex_list)
- {
- T_Object *n, *p, *o;
- T_Object *last = new->last; //ukazatel na posledni objekt v novem seznamu
-
- // konverzni tabulka pro portable objekty - nutne kvuli znovuvytvoreni vazeb mezi nimi v novem levelu
- // neprislo mi nutne ji delat dynamickou, 1024 portable objektu do dalsiho levelu uplne staci ;)
- #define PORTABLE_MAX 1024
- struct
- {
- int32_t old_id;
- int32_t new_id;
- } id_table[PORTABLE_MAX];
- unsigned int id_table_n = 0;
-
- // prvnim pruchodem pridame do noveho seznamu portable objekty ze stareho seznamu
- for(o = old->first; o != NULL; o = o->next)
- {
- // u hrace najdeme hrace stejneho id v novem listu a jen zmenime nektere parametry
- if(o->type == TYPE_PLAYER)
- {
- p = find_object_by_id(new, o->id);
- if(p && p->type == TYPE_PLAYER)
- {
- if (o->number > p->number) p->number = o->number;
- if (o->max_number > p->max_number) p->max_number = o->max_number;
-
- if(p->msg == NULL)
- {
- p->msg = (char *) malloc(sizeof(char) * (strlen(o->msg) + 1));
- if(p->msg)
- {
- strcpy(p->msg, o->msg);
- }
- else
- {
- fprintf(stderr, "merge_object_list(): cannot allocate!\n");
- return EXIT_FAILURE;
- }
- }
- }
- else
- {
- fprintf(stderr, "merge_object_list(): cannot find player with id %i in new list!\n", o->id);
- return EXIT_FAILURE;
- }
- }
- // jiny objekt, pokud je portable a zaroven except (viditelne a aktivni objekty kopirovat je nesmysl), primo zkopirujem
- else if (o->portable && o->except)
- {
- // clone vygeneruje nove id
- if((n = clone_object_base(o, new, tex_list)) == NULL)
- {
- fprintf(stderr, "merge_object_list(): cannot clone object!\n");
- return EXIT_FAILURE;
- }
- else
- {
- // musime si zatim poznacit, k cemu objekt ve starem seznamu patri
- id_table[id_table_n].old_id = o->id;
- id_table[id_table_n].new_id = n->id;
- id_table_n++;
- if(id_table_n == PORTABLE_MAX)
- {
- fprintf(stderr, "merge_object_list: portable objects overflow, maximum is %i\n", PORTABLE_MAX);
- return EXIT_FAILURE;
- }
- // neni treba kopirovat, staci ukazovat, nakopiruj pak add_object_relation
- n->f_id = o->f_id;
- }
- }
- }
-
- // a ted spravime vazby u novych objektu - celkem porod :)
-
- #define BUF_COUNT_MAX 1024 // buffer kam se zalohuji fg klice, zatim staticky staci
- int32_t buf[BUF_COUNT_MAX];
- int count = 0;
- int old_id = 0;
-
- for(o = last->next; o != NULL; o = o->next)
- {
- // zapamatujem si f klice objektu
- count = 0;
- while(o->f_id && o->f_id[count] != 0)
- {
- buf[count] = o->f_id[count];
- count++;
- if (count == BUF_COUNT_MAX)
- {
- fprintf(stderr, "merge_object_list: f_id overflow, maximum is %i\n", BUF_COUNT_MAX);
- return EXIT_FAILURE;
- }
- }
- o->f_id = NULL;
-
- // projdeme foreign klice
- for (int i = 0; i < count; i++)
- {
- old_id = 0;
- // porovname objekt s nove pridanymi objekty
- for(p = last->next; p != NULL; p = p->next)
- {
- // podle konverzni tabulky zjistime jestli stare id objektu odpovida foreign id
- for (unsigned int j = 0; j < id_table_n; j++)
- {
- if(id_table[j].new_id == p->id)
- {
- old_id = id_table[j].old_id;
- break;
- }
- }
-
- // foreign klic odpovida id najiteho objektu, objekty sparujeme
- if(buf[i] == old_id)
- {
- if(add_object_relation(o, p) == EXIT_FAILURE)
- return EXIT_FAILURE;
-
- break;
- }
-
- // old_id objektu nepatri, nulujeme ho
- else
- old_id = 0;
- }
-
- // pro dany foreign klic se zadne old id nenaslo, muze to byt relace s hracem
- // hraci se ID nezmenilo
- if(old_id == 0)
- {
- p = find_object_by_id(new, buf[i]);
- if (p != NULL && p->type == TYPE_PLAYER)
- {
- if (add_object_relation(o, p) == EXIT_FAILURE)
- return EXIT_FAILURE;
- }
- // K objektu neni foreign objekt, coz znamena ze foreign objekt neni portable a neprenesl se
- // shazovat level je asi prilis tvrde, nicmene stavat by se to asi nemelo
- else
- {
- fprintf(stderr, "merge_object_list: cannot find foreign object in new list\n");
- }
- }
- }
- }
- return EXIT_SUCCESS;
- }
- /* Funkce prida polozku na konec seznamu a pokud nema id, doplni mu*/
- T_Object* add_to_object_list(T_ObjectList *list, T_Object *data)
- {
- T_Object *o = (T_Object*) malloc(sizeof(T_Object));
- *o = *data;
- if (o == NULL)
- {
- fprintf(stderr, "add_to_object_list: Cannot allocate memory\n");
- free_object_list(list);
- return NULL;
- }
- o->next = NULL;
- //Seznam jeste nebyl inicializovan, vytvorim ho
- if(list->first == NULL)
- {
- list->first = o;
- list->last = o;
- o->prev = NULL;
- }
- //Pridam polozku nakonec
- else
- {
- o->prev = list->last;
- list->last->next = o;
- list->last = o;
- }
-
- //Objekt nema id, nejake mu vymyslim
- if(o->id == 0)
- {
- o->id = list->id;
- list->id--;
- }
- return o;
- }
- /* Funkce uklidi seznam */
- void free_object_list(T_ObjectList *list)
- {
- T_Object *o;
- while(list->first != NULL)
- {
- o = list->first;
- if(o != NULL)
- {
- free_object_data(o);
- }
- list->first = list->first->next;
- free(o);
- }
- list->last = NULL;
- list->id = -1;
- }
- /* Funkce najde objekt dle typu */
- T_Object *find_object_by_type(T_ObjectList *list, unsigned int type)
- {
- T_Object *o = list->first;
- while(o != NULL)
- {
- if(o->type == type)
- return o;
- o = o->next;
- }
- return NULL;
- }
- /* Funkce najde objekt podle id */
- /* Spise nepouzivat a vyuzivat relace!!! */
- T_Object *find_object_by_id(T_ObjectList *list, Sint32 id)
- {
- T_Object *o = list->first;
- while(o != NULL)
- {
- if(o->id == id)
- return o;
- o = o->next;
- }
- return NULL;
- }
- /* Funkce najde nejvetsi souradnici Y kde je jeste mapa */
- unsigned int find_biggest_y(T_ObjectList *list)
- {
- T_Object *o = list->first;
- Sint16 y = list->first->y + list->first->height;
- while(o != NULL)
- {
- if(y < (o->y + o->height))
- y = o->y + o->height;
- o = o->next;
- }
- return y;
- }
- /* Funkce smaze objekt, spoji seznam a vrati ukazatel na nasledujici objekt */
- /* Pokud je objekt na konci seznamu, vrati NULL */
- /* Pokud objekt nenajde, vrati NULL */
- T_Object *destroy_object(T_ObjectList *list, T_Object *object)
- {
- T_Object *temp;
- if(object == NULL)
- return NULL;
- if(list->first == object)
- {
- temp = object->next;
- list->first = temp;
- if (temp != NULL) temp->prev = NULL;
- if (list->last == object) list->last = temp;
- }
- else if(list->last == object)
- {
- temp=object->prev;
- list->last = temp;
- if (temp != NULL) temp->next = NULL;
- if (list->first == object) list->first = temp;
- temp = NULL;
- }
- else
- {
- temp = object->next;
- if (object->prev != NULL) object->prev->next = temp;
- if (temp != NULL) temp->prev = object->prev;
- }
- free_object_data(object);
- free(object);
- return temp;
- }
- /* Funkce vynuluje objekt */
- void zero_object(T_Object *object)
- {
- object->type = TYPE_BLANK;
- zero_struct(object, TDef_Object);
- zero_object_internal_params(object);
- set_default_object_external_params(object);
- object->next = NULL;
- object->prev = NULL;
- }
- /* Funkce inicializuje seznam */
- void init_object_list(T_ObjectList *list)
- {
- list->first = NULL;
- list->last = NULL;
- list->id = -1;
- }
- /* zaktualizuje texturu objektu podle texture_name */
- int update_object_textures(T_Object *object, T_Textures_List *tex_list)
- {
- if(object->texture_name == 0)
- return EXIT_SUCCESS;
-
- if(obj_types[object->type].img_count == 0)
- {
- fprintf(stderr, "update_object_textures: textures count is zero!");
- return EXIT_FAILURE;
- }
- int t_count = obj_types[object->type].img_count;
- T_Textures *tex = get_Textures_for_Map(object->texture_name, t_count, tex_list);
- if (object->textures != NULL)
- {
- // zahodit predchozi textury
- free(object->textures);
- object->textures = NULL;
- }
- object->textures = (SDL_Surface**) malloc(sizeof(SDL_Surface*) * t_count);
- if (!tex)
- {
- return EXIT_FAILURE;
- }
- for (int i = 0; i < t_count; i++)
- {
- object->textures[i] = tex->images[i];
- }
- return EXIT_SUCCESS;
- }
- /* Prida zavislost objektu o1 na objektu o2 */
- int add_object_relation(T_Object *o1, T_Object *o2)
- {
- //Objekt o2 nema id. Objekt o1 mit id nemusi.
- if(o2->id == 0)
- {
- fprintf(stderr, "add_object_relation: Object hasn't id");
- return EXIT_FAILURE;
- }
- // pocet foreign klicu
- unsigned int i = 0; while(o1->f_id && o1->f_id[i]) {i++;}
- Sint32 *tmp;
- // alokace foreign pole
- if (i == 0)
- {
- if(!(o1->f_id = (Sint32*) malloc(sizeof(Sint32) * KEYS_REALLOCATE_COUNT)))
- {
- fprintf(stderr, "add_object_relation: Cannot allocate memory");
- return EXIT_FAILURE;
- }
- }
- i++;
- if(i % KEYS_REALLOCATE_COUNT == 0)
- {
- tmp = o1->f_id;
- if(!(o1->f_id = (Sint32*) realloc(o1->f_id, sizeof(Sint32) * (i + KEYS_REALLOCATE_COUNT))))
- {
- free(tmp);
- fprintf(stderr, "add_object_relation: Cannot allocate memory");
- return EXIT_FAILURE;
- }
- }
- // pridame foreign klic
- o1->f_id[i-1] = o2->id;
- o1->f_id[i] = 0;
- // upravime vazby
- // belongs:
- if(allocate_t_objects_array(&o1->belongs_to_objects, o1->belongs_to_objects_count, KEYS_REALLOCATE_COUNT) == EXIT_FAILURE)
- return EXIT_FAILURE;
- o1->belongs_to_objects[o1->belongs_to_objects_count] = o2;
- o1->belongs_to_objects_count++;
- // has:
- if(allocate_t_objects_array(&o2->has_objects, o2->has_objects_count, KEYS_REALLOCATE_COUNT) == EXIT_FAILURE)
- return EXIT_FAILURE;
- o2->has_objects[o2->has_objects_count] = o1;
- o2->has_objects_count++;
- return EXIT_SUCCESS;
- }
- /* Odstrani zavislost objektu o1 na objetku o2 */
- void remove_object_relation(T_Object *o1, T_Object *o2)
- {
- unsigned int i, j;
- for(i = j = 0; i < o2->has_objects_count; i++, j++)
- {
- if(o2->has_objects[i] == o1)
- {
- i++;
- if(i == o2->has_objects_count) break;
- }
- o2->has_objects[j] = o2->has_objects[i];
- }
- if (i != j) o2->has_objects_count--;
- for(i = j = 0; i < o1->belongs_to_objects_count; i++, j++)
- {
- if(o1->belongs_to_objects[i] == o2)
- {
- i++;
- if(i == o1->belongs_to_objects_count) break;
- }
- o1->belongs_to_objects[j] = o1->belongs_to_objects[i];
- }
- if (i != j) o1->belongs_to_objects_count--;
- i = j = 0;
- while(o1->f_id && o1->f_id[i] != 0)
- {
- if(o2->id && o1->f_id[i] == o2->id)
- {
- i++;
- if(o1->f_id[i] == 0)
- break;
- }
- o1->f_id[j] = o1->f_id[i];
- i++; j++;
- }
- o1->f_id[j] = 0; //zarazka
- }
- /* Odstrani vsechny zavislosti objektu na jinych objektech*/
- void remove_all_object_relations(T_Object *o)
- {
- while(o->belongs_to_objects_count)
- {
- remove_object_relation(o, o->belongs_to_objects[0]);
- }
- while(o->has_objects_count)
- {
- remove_object_relation(o->has_objects[0], o);
- }
- }
- /* Odstrani objekt, ducha i vsechny zavislosti a vrati ukazatel na dalsi polozku seznamu */
- T_Object *destroy_object_and_bindings(T_ObjectList *list, T_Object *object)
- {
- //odstranit ducha
- if(object->ghost)
- destroy_object_and_bindings(list, object->ghost);
- //odstranit vazby
- remove_all_object_relations(object);
- //smazat objekt
- return destroy_object(list, object);
- }
- /* OVeri, zda o1 zavisi na o2 */
- bool o1_is_depend_on_o2(T_Object *o1, T_Object *o2)
- {
- for(unsigned int i = 0; i < o1->belongs_to_objects_count; i++)
- {
- if(o1->belongs_to_objects[i] == o2)
- return true;
- }
- return false;
- }
- /*Â Naalokuje ci realokuje pole objektu */
- int allocate_t_objects_array(T_Object ***objects, int use, int realloc_count)
- {
- T_Object **tmp;
- //alokace
- if(use == 0 && *objects == NULL)
- {
- *objects = (T_Object**) malloc(sizeof(T_Object*) * realloc_count);
- if(*objects == NULL)
- {
- fprintf(stderr, "allocate_t_objects_array: Cannot allocate memmory!\n");
- return EXIT_FAILURE;
- }
- }
- //realokace
- else if((use % realloc_count) == 0)
- {
- tmp = *objects;
- *objects = (T_Object**) realloc(*objects, sizeof(T_Object*) * (use + realloc_count));
- if (*objects == NULL)
- {
- fprintf(stderr, "allocate_t_objects_array: Cannot allocate memmory!\n");
- free(tmp);
- return EXIT_FAILURE;
- }
- }
- return EXIT_SUCCESS;
- }
- /* Vrati prvni foreign objekt daneho typu */
- /* Hodi se pouze tehdy, kdy se vice objektu neocekava / jsou chybou */
- T_Object * get_first_foreign_object_by_type(T_Object *object, Uint32 type)
- {
- for(unsigned int i=0; i<object->belongs_to_objects_count; i++)
- {
- if(object->belongs_to_objects[i]->type == type)
- return object->belongs_to_objects[i];
- }
- return NULL;
- }
- /* Vrati prvni vlastni objekt daneho typu */
- /* Hodi se pouze tehdy, kdy se vice objektu neocekava / jsou chybou */
- T_Object * get_first_own_object_by_type(T_Object *object, Uint32 type)
- {
- for(unsigned int i=0; i<object->has_objects_count; i++)
- {
- if(object->has_objects[i]->type == type)
- return object->has_objects[i];
- }
- return NULL;
- }
- /* Projde vsechny objekty a nastavi jim vazby podle klicu */
- /* Melo by stacit volat jen jednou */
- int regenerate_bindings(T_ObjectList *list)
- {
- T_Object *o1, *o2;
- o1 = list->first;
- unsigned int i;
- while(o1 != NULL)
- {
- o2 = list->first;
- o1->has_objects_count = 0;
- o1->belongs_to_objects_count = 0;
- free(o1->has_objects);
- free(o1->belongs_to_objects);
- o1->has_objects = NULL;
- o1->belongs_to_objects = NULL;
- while(o2 != NULL)
- {
- // stejne objekty
- if (o1 == o2)
- {
- o2 = o2->next;
- continue;
- }
- // poruseni integrity, dva objekty maji stejne id
- if (o1->id && o1->id == o2->id)
- {
- fprintf(stderr, "Integrity error: two objects has same id (%i)\n", o1->id);
- return EXIT_FAILURE;
- }
- // projdu foreign klice objektu o1
- i = 0;
- while(o1->f_id && o1->f_id[i])
- {
- // klic odkazuje na objekt o2
- if(o1->f_id[i] == o2->id)
- {
- //alokace
- if(allocate_t_objects_array(&o1->belongs_to_objects, o1->belongs_to_objects_count, KEYS_REALLOCATE_COUNT) == EXIT_FAILURE)
- return EXIT_FAILURE;
- o1->belongs_to_objects[o1->belongs_to_objects_count] = o2;
- o1->belongs_to_objects_count++;
- }
- i++;
- }
- // projdu foreign klice objektu o2
- i = 0;
- while(o2->f_id && o2->f_id[i])
- {
- // klic odkazuje na objekt o1
- if(o2->f_id[i] == o1->id)
- {
- //alokace
- if(allocate_t_objects_array(&o1->has_objects, o1->has_objects_count, KEYS_REALLOCATE_COUNT) == EXIT_FAILURE)
- return EXIT_FAILURE;
- o1->has_objects[o1->has_objects_count] = o2;
- o1->has_objects_count++;
- }
- i++;
- }
- o2 = o2->next;
- }
- i = 0; while(o1->f_id && o1->f_id[i]) i++;
- //Objekty o2, ke kteremu patri o1 se nepodarilo najit
- if (i != o1->belongs_to_objects_count)
- {
- fprintf(stderr, "Integrity error: object (%i) cannot find some foreign objects\n", o1->id);
- return EXIT_FAILURE;
- }
- o1 = o1->next;
- }
- return EXIT_SUCCESS;
- }
- /* Pro debug, vypise relace*/
- void print_relations(T_ObjectList *list)
- {
- printf("DEBUG - relations:\n\n");
- T_Object *o = list->first;
- while(o)
- {
- printf("id: %i, type: %s\n", o->id, obj_types[o->type].keyword);
-
- /*
- if(o->type == TYPE_PLAYER)
- {
- printf("\thp: %i, :max_hp: %i %s\n", o->number, o->max_number, o->msg);
- }*/
-
- if(o->belongs_to_objects_count) printf("belongs:\n");
- for(unsigned int i=0; i < o->belongs_to_objects_count;i++)
- printf("\tid: %i, type: %s\n", o->belongs_to_objects[i]->id, obj_types[o->belongs_to_objects[i]->type].keyword);
- if(o->has_objects_count) printf("has:\n");
- for(unsigned int i =0; i < o->has_objects_count;i++)
- printf("\tid: %i, type: %s\n", o->has_objects[i]->id, obj_types[o->has_objects[i]->type].keyword);
- int i=0;
- if(o->f_id) printf("f_id:\n");
- while(o->f_id && o->f_id[i])
- {
- printf("\tid: %i\n", o->f_id[i]);
- i++;
- }
- printf("=========\n");
- o = o->next;
- }
- }
- /* Prepocet souradnic z jedne vztazne soustavy na druhou */
- void obj_change_surface(T_Object *o, T_Object *new_surface)
- {
- Sint16 old_h_speed = o->surface == NULL ? 0 : o->surface->h_speed;
- Sint16 old_v_speed = o->surface == NULL ? 0 : o->surface->v_speed;
- Sint16 new_h_speed = new_surface == NULL ? 0 : new_surface->h_speed;
- Sint16 new_v_speed = new_surface == NULL ? 0 : new_surface->v_speed;
- o->h_speed += old_h_speed - new_h_speed;
- o->v_speed += old_v_speed - new_v_speed;
- o->surface = new_surface;
- }
- /* Naklonuje objekt vcetne textur krome internich parametru a relaci a vloziho do listu */
- T_Object *clone_object_base(T_Object *object, T_ObjectList *list, T_Textures_List *tex_list)
- {
- T_Object *tmp_object = malloc(sizeof(T_Object));
- memcpy(tmp_object, object, sizeof(T_Object));
-
- // Tohle se musi vynulovat, jinak to hezky rachne
- zero_object_internal_params(tmp_object);
- tmp_object->id = 0;
- tmp_object->f_id = NULL;
- tmp_object->str = NULL;
- tmp_object->msg = NULL;
- if(object->str)
- {
- tmp_object->str = (char*) malloc(sizeof(char) * (strlen(object->str) + 1));
- strcpy(tmp_object->str, object->str);
- }
- if(object->msg)
- {
- tmp_object->msg = (char*) malloc(sizeof(char) * (strlen(object->msg) + 1));
- strcpy(tmp_object->msg, object->msg);
- }
-
- if (object->texture_name != NULL)
- {
- tmp_object->texture_name = (char *) malloc(strlen(object->texture_name)+1);
- if (tmp_object->texture_name != NULL)
- {
- strcpy(tmp_object->texture_name, object->texture_name);
- }
- else
- {
- fprintf(stderr, "clone_object: Cannot allocate memory");
- exit(1);
- }
- }
- T_Object *inserted_object;
- inserted_object = add_to_object_list(list, tmp_object);
- free(tmp_object);
-
- if (inserted_object->texture_name != NULL)
- {
- if (update_object_textures(inserted_object, tex_list) == EXIT_FAILURE)
- exit(1);
- }
- return inserted_object;
- }