kettek2/wiki/games/newsboy/Newsboy_0x00/engine/LiveMap.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;
}