483 lines
16 KiB
C
483 lines
16 KiB
C
#include "Map.h"
|
|
#include "LiveMap.h"
|
|
#include "report.h"
|
|
#include "Animation.h"
|
|
#include "fifo.h"
|
|
#include "string.h"
|
|
#include "game_globals.h"
|
|
#include "Vector.h"
|
|
#include "Phys.h"
|
|
#include "EntityData.h"
|
|
|
|
#include <stdlib.h>
|
|
// Loading ================================
|
|
/*int loadLiveMap(struct LiveMap *map, const char *file) {
|
|
if (map == NULL) {
|
|
report(ERROR, "loadLiveMap", "passed map is NULL");
|
|
return 1;
|
|
}
|
|
if (file == NULL) {
|
|
report(ERROR, "loadLiveMap", "passed file name isNULL");
|
|
return 2;
|
|
}
|
|
// open file
|
|
FILE *input = fopen(file, "rb");
|
|
if (input == NULL) {
|
|
report(ERROR, "loadLiveMap", "cannot open map file \"%s\" for reading", file);
|
|
return 3;
|
|
}
|
|
// alright, start loading in map data!
|
|
uint32_t val;
|
|
readData(input, T_MAGIC, &val);
|
|
// check magick
|
|
if (((char *)val)[0] != 'N' || ((char *)val)[1] != 'b' || ((char *)val)[2] != 'M' || ((char *)val)[3] != 1) {
|
|
report(ERROR, "loadLiveMap", "Magic number mismatch, expected %d, got %d\n", 1, ((char *)val)[3]);
|
|
fclose(input);
|
|
return 4;
|
|
}
|
|
// read in name
|
|
map->name = readData(input, T_STRING, map->name);
|
|
map->session = readData(input, T_STRING, map->session);
|
|
// read in width & height
|
|
readData(input, T_INT, &map->location);
|
|
readData(input, T_INT, &map->width);
|
|
readData(input, T_INT, &map->height);
|
|
// create and load in cells
|
|
map->cells = malloc(map->width * sizeof(struct Cell));
|
|
if (map->cells == NULL) {
|
|
report(ERROR, "loadLiveMap", "could not malloc cells");
|
|
fclose(input);
|
|
return 5;
|
|
}
|
|
// allocate memory for cells
|
|
int x, y;
|
|
for (x = 0; x < map->width; x++) {
|
|
map->cells[x] = malloc(sizeof *map->cells[x] * map->height);
|
|
if (map->cells[x] == NULL) {
|
|
report(ERROR, "loadLiveMap", "could not alloc memory for cells[%d]", x);
|
|
// this is not actually y, I'm just (ab)using it.
|
|
for (y = 0; y < x; y++) {
|
|
free(map->cells[y]);
|
|
}
|
|
map->width = 0;
|
|
map->height = 0;
|
|
free(map->cells);
|
|
map->cells = NULL;
|
|
fclose(input);
|
|
return 6;
|
|
}
|
|
for (y = 0; y < map->height; y++) {
|
|
// load in cell flags
|
|
readData(input, T_INT, &map->cells[x][y].flags);
|
|
// load in decor count
|
|
readData(input, T_INT, &map->cells[x][y].decor_count);
|
|
// load in decors!
|
|
struct Cell *cell = &map->cells[x][y];
|
|
if (cell->decor_count > 0) {
|
|
if ((cell->decor = malloc(sizeof(struct Decor)*cell->decor_count)) == NULL) {
|
|
report(ERROR, "loadLiveMap", "could not malloc for %d decors in %dx%d", cell->decor_count, x, y);
|
|
// TODO: something
|
|
cell->decor_count = 0;
|
|
} else {
|
|
// read 'em in
|
|
int d;
|
|
for (d = 0; d < cell->decor_count; d++) {
|
|
// read in x
|
|
readData(input, T_INT, &cell->decor[d].x);
|
|
// read in y
|
|
readData(input, T_INT, &cell->decor[d].y);
|
|
// read in animation boolean
|
|
readData(input, T_INT, &cell->decor[d].animation.anim_bool);
|
|
// read in animation frame index
|
|
readData(input, T_INT, &cell->decor[d].animation.f);
|
|
// read in animation animation name
|
|
readData(input, T_INT, &cell->decor[d].animation.);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
fclose(input);
|
|
return 0;
|
|
}*/
|
|
// LiveMap ================================
|
|
struct LiveMap *newLiveMap() {
|
|
struct LiveMap *map = malloc(sizeof(struct LiveMap));
|
|
if (map == NULL) {
|
|
report(ERROR, "newLiveMap", "could not malloc LiveMap");
|
|
return NULL;
|
|
}
|
|
map->name = NULL;
|
|
map->session = NULL;
|
|
map->location = 0;
|
|
map->width = 0;
|
|
map->height = 0;
|
|
map->cells = NULL;
|
|
map->player.x = 0;
|
|
map->player.y = 0;
|
|
map->entities = NULL;
|
|
map->triggers = NULL;
|
|
map->active_triggers = NULL;
|
|
map->events = NULL;
|
|
cleanAnim(&map->player.animation);
|
|
return map;
|
|
}
|
|
int freeLiveMap(struct LiveMap *map) {
|
|
if (map == NULL) return 1;
|
|
if (map->name != NULL) free(map->name);
|
|
if (map->session != NULL) free(map->session);
|
|
if (map->cells != NULL) {
|
|
freeCells(map->cells, map->width, map->height);
|
|
int x;
|
|
for (x = 0; x < map->width; x++) {
|
|
free(map->cells[x]);
|
|
}
|
|
free(map->cells);
|
|
map->cells = NULL;
|
|
}
|
|
if (map->entities) {
|
|
struct Entity *entity;
|
|
while((entity = iterObject(map->entities)) != NULL) {
|
|
freeEntity(entity);
|
|
}
|
|
freeVoidMan(map->entities);
|
|
}
|
|
if (map->triggers) {
|
|
struct Trigger *trigger;
|
|
while((trigger = iterObject(map->triggers)) != NULL) {
|
|
freeTrigger(trigger);
|
|
}
|
|
freeVoidMan(map->triggers);
|
|
}
|
|
if (map->active_triggers) {
|
|
struct Trigger *trigger;
|
|
while((trigger = iterObject(map->active_triggers)) != NULL) {
|
|
freeTrigger(trigger);
|
|
}
|
|
freeVoidMan(map->active_triggers);
|
|
}
|
|
if (map->events) {
|
|
struct Event *event;
|
|
while((event = iterObject(map->events)) != NULL) {
|
|
freeEvent(event);
|
|
}
|
|
freeVoidMan(map->events);
|
|
}
|
|
free(map);
|
|
return 0;
|
|
}
|
|
int freeCells(struct Cell **cells, int width, int height) {
|
|
int x, y;
|
|
for (x = 0; x < width; x++) {
|
|
for (y = 0; y < height; y++) {
|
|
freeCell(&cells[x][y]);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// THIS SEEMS STUPID, but whatevs~
|
|
struct LiveMap *initLiveMap(struct MapData *map) {
|
|
if (map == NULL) return NULL;
|
|
struct LiveMap *live = newLiveMap();
|
|
live->location = map->location;
|
|
live->session = copyString(live->session, map->session);
|
|
live->name = copyString(live->name, map->name);
|
|
live->width = map->width;
|
|
live->height = map->height;
|
|
// allocate memory for cells
|
|
live->cells = malloc(live->width * sizeof(struct Cell));
|
|
if (live->cells == NULL) {
|
|
report(ERROR, "initLiveMap", "could not malloc cells");
|
|
freeLiveMap(live);
|
|
return NULL;
|
|
}
|
|
int x, y;
|
|
for (x = 0; x < live->width; x++) {
|
|
live->cells[x] = malloc(sizeof *live->cells[x] * live->height);
|
|
if (live->cells[x] == NULL) {
|
|
report(ERROR, "initLiveMap", "could not alloc memory for cells[%d]", x);
|
|
// this is not actually y, I'm just (ab)using it.
|
|
for (y = 0; y < x; y++) {
|
|
free(live->cells[y]);
|
|
}
|
|
live->width = 0;
|
|
live->height = 0;
|
|
free(live->cells);
|
|
live->cells = NULL;
|
|
freeLiveMap(live);
|
|
return NULL;
|
|
}
|
|
for (y = 0; y < live->height; y++) {
|
|
live->cells[x][y].flags = map->cells[x][y].flags;
|
|
live->cells[x][y].decor_count = map->cells[x][y].decor_count;
|
|
// load 'er up
|
|
struct Cell *cell = &live->cells[x][y];
|
|
if (cell->decor_count > 0) {
|
|
if ((cell->decor = malloc(sizeof(struct Decor)*cell->decor_count)) == NULL) {
|
|
report(ERROR, "loadLiveMap", "could not malloc for %d decors in %dx%d", cell->decor_count, x, y);
|
|
// TODO: something with freeing
|
|
cell->decor_count = 0;
|
|
} else {
|
|
int d;
|
|
for (d = 0; d < cell->decor_count; d++) {
|
|
cell->decor[d].x = map->cells[x][y].decor[d]->x;
|
|
cell->decor[d].y = map->cells[x][y].decor[d]->y;
|
|
cleanAnim(&cell->decor[d].animation);
|
|
// get full animation path name, as live_animations expects it
|
|
|
|
cell->decor[d].animation.anim = getResource(live_animations, map->cells[x][y].decor[d]->anim);
|
|
if (cell->decor[d].animation.anim == NULL) {
|
|
printf("getting anim %s was null\n", map->cells[x][y].decor[d]->anim);
|
|
}
|
|
cell->decor[d].animation.anim_bool = map->cells[x][y].decor[d]->animated;
|
|
setAnimSet(&cell->decor[d].animation, map->cells[x][y].decor[d]->set);
|
|
setAnimFace(&cell->decor[d].animation, map->cells[x][y].decor[d]->face);
|
|
setAnimFrame(&cell->decor[d].animation, map->cells[x][y].decor[d]->frame);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // done with cells, finally
|
|
live->player.x = map->player_data.x;
|
|
live->player.y = map->player_data.y;
|
|
live->player.animation.anim = getResource(live_animations, map->player_data.anim);
|
|
setAnimSet(&live->player.animation, map->player_data.set);
|
|
setAnimFace(&live->player.animation, map->player_data.face);
|
|
setAnimFrame(&live->player.animation, map->player_data.frame);
|
|
cleanPhys(&live->player.phys);
|
|
cleanPhys(&live->player.l_phys);
|
|
live->player.phys.position.x = map->player_data.x;
|
|
live->player.phys.position.y = map->player_data.y;
|
|
// gather entities
|
|
live->entities = newVoidMan(8);
|
|
struct EntityMapData *entity_map_data;
|
|
while((entity_map_data = iterObject(map->entities)) != NULL) {
|
|
struct Entity *entity = newEntity();
|
|
entity->phys.position.x = entity_map_data->x;
|
|
entity->phys.position.y = entity_map_data->y;
|
|
struct EntityData *entity_data = getResource(live_entities, entity_map_data->name);
|
|
if (entity_data == NULL) {
|
|
report(ERROR, "initLiveMap", "could not get EntityData for %s", entity_map_data->name);
|
|
freeEntity(entity);
|
|
continue;
|
|
}
|
|
entity->name = copyString(entity->name, entity_data->name);
|
|
// load entity animation
|
|
if ((entity->animation.anim = getResource(live_animations, entity_data->anim)) == NULL) {
|
|
report(ERROR, "initLiveMap", "could not get Animation %s for %s", entity_data->anim, entity->name);
|
|
freeEntity(entity);
|
|
continue;
|
|
}
|
|
setAnimSet(&entity->animation, entity_map_data->set);
|
|
setAnimFace(&entity->animation, entity_map_data->face);
|
|
setAnimFrame(&entity->animation, entity_map_data->frame);
|
|
if (entity->animation.sheet != NULL) {
|
|
if (entity->animation.sheet->surfaces[0] != NULL) {
|
|
entity->height = (entity->animation.sheet->surfaces[0]->h/2)-(entity->animation.sheet->surfaces[0]->h/4);
|
|
}
|
|
}
|
|
// load up logic
|
|
entity->logic = entity_data->behave;
|
|
entity->type = entity_data->type;
|
|
// physics
|
|
entity->phys.radius = entity_data->radius;
|
|
entity->phys.mass = entity_data->mass;
|
|
entity->speed = entity_data->speed;
|
|
entity->turn_rate = entity_data->turn;
|
|
// hp and sight
|
|
entity->max_hp = entity_data->hp;
|
|
entity->hp = entity_data->hp;
|
|
entity->sight = entity_data->sight;
|
|
// attack-related
|
|
entity->range = entity_data->range;
|
|
entity->attack = entity_data->attack;
|
|
entity->damage = entity_data->damage;
|
|
entity->spawn_data = getResource(live_entities, entity_data->spawn);
|
|
// despawn time if projectile type
|
|
entity->time = entity_data->time;
|
|
|
|
addObject(live->entities, entity);
|
|
}
|
|
|
|
// gather events, populate events, creating an array of strings to correlate name->index
|
|
live->events = newVoidMan(8);
|
|
char **event_names = malloc(sizeof(char*)*map->event_count);
|
|
struct EventMapData *event_data;
|
|
while((event_data = iterObject(map->events)) != NULL) {
|
|
struct Event *event = newEvent();
|
|
event->box.x = event_data->x;
|
|
event->box.y = event_data->y;
|
|
event->box.w = event_data->w;
|
|
event->box.h = event_data->h;
|
|
printf("set to: %dx%dby%dx%d\n", event->box.x, event->box.y, event->box.w, event->box.h);
|
|
event->type = event_data->type;
|
|
event->param_count = event_data->param_count;
|
|
event->params = malloc(event->param_count * sizeof(void*));
|
|
event->param_type = malloc(event->param_count * sizeof(int));
|
|
int i;
|
|
for(i = 0; i < event->param_count; i++) {
|
|
event->param_type[i] = event_data->param_type[i];
|
|
switch(event_data->param_type[i]) {
|
|
case T_CHAR:
|
|
event->params[i] = malloc(sizeof(char));
|
|
*(char*)event->params[i] = *(char*)event_data->params[i];
|
|
break;
|
|
case T_INT:
|
|
event->params[i] = malloc(sizeof(int));
|
|
*(int*)event->params[i] = *(int*)event_data->params[i];
|
|
break;
|
|
case T_FLOAT:
|
|
event->params[i] = malloc(sizeof(float));
|
|
*(float*)event->params[i] = *(float*)event_data->params[i];
|
|
break;
|
|
case T_STRING:
|
|
{}
|
|
int size = strlen((char*)event_data->params[i])+1;
|
|
event->params[i] = malloc(size);
|
|
memcpy(event->params[i], event_data->params[i], size);
|
|
break;
|
|
}
|
|
}
|
|
int id = addObject(live->events, event);
|
|
int size = strlen(event_data->name)+1;
|
|
event_names[id] = malloc(size);
|
|
memcpy(event_names[id], event_data->name, size);
|
|
}
|
|
// in trigger, strcmp trigger's event name to earlier array of strings, setting the target event to the returned index if it exists.
|
|
live->triggers = newVoidMan(8);
|
|
live->active_triggers = newVoidMan(8);
|
|
struct TriggerMapData *trigger_data;
|
|
while((trigger_data = iterObject(map->triggers)) != NULL) {
|
|
struct Trigger *trigger = newTrigger();
|
|
trigger->box.x = trigger_data->x;
|
|
trigger->box.y = trigger_data->y;
|
|
trigger->box.w = trigger_data->w;
|
|
trigger->box.h = trigger_data->h;
|
|
trigger->type = trigger_data->type;
|
|
trigger->behavior = trigger_data->behavior;
|
|
trigger->activator = trigger_data->activator;
|
|
trigger->time = trigger_data->time;
|
|
trigger->iter = trigger_data->iter;
|
|
trigger->event_count = trigger_data->event_count;
|
|
trigger->events = malloc(sizeof(int)*trigger->event_count);
|
|
int i;
|
|
for (i = 0; i < trigger_data->event_count; i++) {
|
|
trigger->events[i] = -1;
|
|
int j;
|
|
for (j = 0; j < map->event_count; j++) {
|
|
if (strcmp(trigger_data->events[i], event_names[j]) == 0) {
|
|
trigger->events[i] = j;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
addObject(live->triggers, trigger);
|
|
}
|
|
|
|
// free list of event names
|
|
int i;
|
|
for (i = 0; i < map->event_count; i++) {
|
|
free(event_names[i]);
|
|
}
|
|
free(event_names);
|
|
return live;
|
|
}
|
|
|
|
// Event ================================
|
|
struct Event *newEvent() {
|
|
struct Event *event = malloc(sizeof(struct Event));
|
|
event->type = 0;
|
|
event->param_count = 0;
|
|
event->param_type = NULL;
|
|
event->params = NULL;
|
|
return event;
|
|
}
|
|
int freeEvent(struct Event *event) {
|
|
int i;
|
|
for (i = 0; i < event->param_count; i++) {
|
|
free(event->params[i]);
|
|
}
|
|
if (event->params != NULL) free(event->params);
|
|
if (event->param_type != NULL) free(event->param_type);
|
|
//free(event); // voidman frees
|
|
return 0;
|
|
}
|
|
|
|
// Trigger ================================
|
|
struct Trigger *newTrigger() {
|
|
struct Trigger *trigger = malloc(sizeof(struct Trigger));
|
|
trigger->type = 0;
|
|
trigger->iter = 0;
|
|
trigger->activator = 0;
|
|
trigger->behavior = 0;
|
|
trigger->time = 0;
|
|
trigger->elapsed = 0;
|
|
trigger->runs = 0;
|
|
trigger->event_runs = 0;
|
|
trigger->events = NULL;
|
|
return trigger;
|
|
}
|
|
int freeTrigger(struct Trigger *trigger) {
|
|
if (trigger == NULL) return 1;
|
|
if (trigger->events != NULL) free(trigger->events);
|
|
//free(trigger); // voidman frees
|
|
return 0;
|
|
}
|
|
|
|
// Cell ================================
|
|
struct Cell *newCell(int flags, int decor_count) {
|
|
struct Cell *cell = malloc(sizeof(struct Cell));
|
|
cell->flags = flags;
|
|
cell->decor_count = decor_count;
|
|
cell->decor = malloc(sizeof(struct Decor)*decor_count);
|
|
int i;
|
|
for (i = 0; i < cell->decor_count; i++) {
|
|
cell->decor[i].x = 0;
|
|
cell->decor[i].y = 0;
|
|
cleanAnim(&cell->decor[i].animation);
|
|
}
|
|
return cell;
|
|
}
|
|
int freeCell(struct Cell *cell) {
|
|
if (cell == NULL) return 1;
|
|
if (cell->decor == NULL) return 2;
|
|
if (cell->decor_count > 0) {
|
|
free(cell->decor);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int delDecor(struct Cell *cell, int pos) {
|
|
if (cell == NULL) return 1;
|
|
if (pos < 0 || pos >= cell->decor_count) return 2;
|
|
struct Decor *temp = malloc((cell->decor_count-1)*sizeof(struct Decor));
|
|
|
|
memmove(temp, cell->decor, (pos+1)*sizeof(struct Decor));
|
|
memmove(temp+pos, cell->decor+(pos+1), (cell->decor_count-pos)*sizeof(struct Decor));
|
|
/*if (pos != 0) {
|
|
memcpy(temp, cell->decor, (pos-1)*sizeof(struct Decor));
|
|
}
|
|
if (pos != cell->decor_count-1) {
|
|
memcpy(temp+pos, cell->decor+pos+1, (cell->decor_count - pos -1)*sizeof(struct Decor));
|
|
}*/
|
|
free(cell->decor);
|
|
cell->decor = temp;
|
|
|
|
printf("deleting pos %d\n", pos);
|
|
cell->decor_count--;
|
|
printf("new decor_count is %d\n", cell->decor_count);
|
|
if (cell->decor_count <= 0) {
|
|
free(cell->decor);
|
|
cell->decor = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int collideCell(struct Cell *cell, struct Phys *phys) {
|
|
if (cell->flags & CELL_BLOCKS_ENTITY) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|