arcus_atlas *atlas_from_xml(scew_element *element) { arcus_atlas *atlas; scew_list *list, *i; int expected_transforms, ii, jj, kk; if (!element) { set_error_string("atlas_from_xml: NULL element"); return NULL; } if (strcmp(scew_element_name(element), "atlas") != 0) { set_error_string("atlas_from_xml: element name != 'atlas'"); return NULL; } atlas = atlas_create(); if (!atlas) return NULL; list = scew_element_list_by_name(element, "system"); if (!list) { set_error_string("atlas_from_xml: no systems in atlas"); atlas_destroy(atlas); return NULL; } for (i = list ; i ; i = scew_list_next(i)) { scew_element *e; arcus_system *s; e = (scew_element *)scew_list_data(i); s = system_from_xml(e); if (!s) { atlas_destroy(atlas); return NULL; } atlas->systems = (arcus_system **)realloc(atlas->systems, (atlas->num_systems + 1) * sizeof(arcus_system *)); atlas->systems[atlas->num_systems] = s; atlas->num_systems++; } // If there's only one system, ignore the transforms if (atlas->num_systems == 1) return atlas; // Figure out how many transforms we should have (n choose k, both directions) expected_transforms = binomial(atlas->num_systems, 2) * 2; // Load transforms list = scew_element_list_by_name(element, "transform"); if (!list) { set_error_string("atlas_from_xml: no transforms in atlas when expected"); atlas_destroy(atlas); return NULL; } if (scew_list_size(list) != expected_transforms) { set_error_string("atlas_from_xml: wrong number of transforms in atlas"); atlas_destroy(atlas); return NULL; } for (i = list ; i ; i = scew_list_next(i)) { scew_element *e; arcus_transform *t; e = (scew_element *)scew_list_data(i); t = transform_from_xml(e); if (!t) { atlas_destroy(atlas); return NULL; } atlas->transforms = (arcus_transform **)realloc(atlas->transforms, (atlas->num_transforms + 1) * sizeof(arcus_transform *)); atlas->transforms[atlas->num_transforms] = t; atlas->num_transforms++; } // Load differential transforms list = scew_element_list_by_name(element, "transform_diff"); if (!list) { set_error_string("atlas_from_xml: no differential transforms in atlas when expected"); atlas_destroy(atlas); return NULL; } if (scew_list_size(list) != expected_transforms) { set_error_string("atlas_from_xml: wrong number of differential transforms in atlas"); atlas_destroy(atlas); return NULL; } for (i = list ; i ; i = scew_list_next(i)) { scew_element *e; arcus_transform *t; e = (scew_element *)scew_list_data(i); t = transform_from_xml(e); if (!t) { atlas_destroy(atlas); return NULL; } atlas->diff_transforms = (arcus_transform **)realloc(atlas->diff_transforms, (atlas->num_diff_transforms + 1) * sizeof(arcus_transform *)); atlas->diff_transforms[atlas->num_diff_transforms] = t; atlas->num_diff_transforms++; } // Check the accuracy and completeness of the transform lists for (ii = 0 ; ii < expected_transforms ; ii++) { arcus_transform *t, *dt; int found_t_from = 0, found_t_to = 0; int found_dt_from = 0, found_dt_to = 0; t = atlas->transforms[ii]; dt = atlas->diff_transforms[ii]; for (jj = 0 ; jj < atlas->num_systems ; jj++) { if (strcmp(system_id(atlas->systems[jj]), transform_from(t)) == 0) found_t_from = 1; if (strcmp(system_id(atlas->systems[jj]), transform_from(dt)) == 0) found_dt_from = 1; if (strcmp(system_id(atlas->systems[jj]), transform_to(t)) == 0) found_t_to = 1; if (strcmp(system_id(atlas->systems[jj]), transform_to(dt)) == 0) found_dt_to = 1; } if (!found_t_from || !found_t_to) { set_error_string("atlas_from_xml: transform has invalid from/to"); atlas_destroy(atlas); return NULL; } if (!found_dt_from || !found_dt_to) { set_error_string("atlas_from_xml: transform_diff has invalid from/to"); atlas_destroy(atlas); return NULL; } } for (ii = 0 ; ii < atlas->num_systems ; ii++) { for (jj = 0 ; jj < atlas->num_systems ; jj++) { int found_ij = 0, found_ji = 0, found_ij_d = 0, found_ji_d = 0; if (ii == jj) continue; arcus_system *si, *sj; si = atlas->systems[ii]; sj = atlas->systems[jj]; for (kk = 0 ; kk < expected_transforms ; kk++) { arcus_transform *t = atlas->transforms[kk]; if (strcmp(system_id(si), transform_from(t)) == 0 && strcmp(system_id(sj), transform_to(t)) == 0) found_ij = 1; else if (strcmp(system_id(sj), transform_from(t)) == 0 && strcmp(system_id(si), transform_to(t)) == 0) found_ji = 1; t = atlas->diff_transforms[kk]; if (strcmp(system_id(si), transform_from(t)) == 0 && strcmp(system_id(sj), transform_to(t)) == 0) found_ij_d = 1; else if (strcmp(system_id(sj), transform_from(t)) == 0 && strcmp(system_id(si), transform_to(t)) == 0) found_ji_d = 1; } if (!found_ij || !found_ji) { set_error_string("atlas_from_xml: no transforms found for one pair of systems"); atlas_destroy(atlas); return NULL; } if (!found_ij_d || !found_ji_d) { set_error_string("atlas_from_xml: no differential transforms found for one pair of systems"); atlas_destroy(atlas); return NULL; } } } return atlas; }
// death is called when an object dies (weapon destructed, etc.) // for special effects .. short weap::death() { // Note that the 'dead' variable should ALREADY be set by the // time this function is called, so that we can easily reverse // the decision :) walker *newob = NULL; if (death_called) // Make sure we don't get multiple deaths return 0; death_called = 1; switch (family) { case FAMILY_KNIFE: // for returning knife if (owner && owner->query_family() != FAMILY_SOLDIER) break; // only soldiers get returning knives newob = screenp->add_ob(ORDER_FX, FAMILY_KNIFE_BACK); newob->owner = owner; newob->center_on(this); newob->lastx = lastx; newob->lasty = lasty; newob->stepsize = stepsize; newob->ani_type = ANI_ATTACK; newob->damage = damage; break; // end of soldier returning knife case FAMILY_ROCK: // used for the elf's bouncing rock, etc. if (!do_bounce || !lineofsight || collide_ob) // died of natural causes break; dead = 0; // first, un-dead us so we can collide .. // Did we hit a barrier? if (screenp->query_grid_passable(xpos+lastx, ypos+lasty, this)) { dead = 1; break; // if not, die like normal } if (screenp->query_grid_passable(xpos-lastx, ypos+lasty, this)) { setxy(xpos-lastx, ypos+lasty); // bounce 'down-left' lastx = -lastx; death_called = 0; break; } if (screenp->query_grid_passable(xpos+lastx, ypos-lasty, this)) { setxy(xpos+lastx, ypos-lasty); // bounce 'up-right' lasty = -lasty; death_called = 0; break; } if (screenp->query_grid_passable(xpos-lastx, ypos-lasty, this)) { setxy(xpos-lastx, ypos-lasty); lastx = -lastx; lasty = -lasty; death_called = 0; break; } // Else we're really stuck, so die :) dead = 1; break; case FAMILY_FIRE_ARROW: // only for exploding, really case FAMILY_BOULDER: if (!skip_exit) break; // skip_exit means we're supposed to explode :) if (!owner || owner->dead) owner = this; newob = screenp->add_ob(ORDER_FX, FAMILY_EXPLOSION, 1); if (!newob) break; // failsafe if (on_screen()) screenp->soundp->play_sound(SOUND_EXPLODE); newob->owner = owner; newob->stats->hitpoints = 0; newob->stats->level = owner->stats->level; newob->ani_type = ANI_EXPLODE; newob->center_on(this); newob->damage = damage*2; break; // end fire (exploding) arrows case FAMILY_WAVE: // grow to wave2 dead = 0; transform_to(ORDER_WEAPON, FAMILY_WAVE2); stats->hitpoints = stats->max_hitpoints; break; // end wave -> wave2 case FAMILY_WAVE2: // grow to wave3 dead = 0; transform_to(ORDER_WEAPON, FAMILY_WAVE3); stats->hitpoints = stats->max_hitpoints; break; // end wave2 -> wave3 case FAMILY_DOOR: // display open picture newob = screenp->add_weap_ob(ORDER_FX, FAMILY_DOOR_OPEN); if (!newob) break; newob->ani_type = ANI_DOOR_OPEN; newob->setxy(xpos, ypos); newob->stats->level = stats->level; newob->team_num = team_num; // newob->ignore = 1; // What way are we 'facing'? if (mysmoother->query_genre_x_y((xpos/GRID_SIZE),(ypos/GRID_SIZE)-1) == TYPE_WALL) // a wall above us? { newob->curdir = FACE_RIGHT; // newob->setxy(xpos, ypos-12); // and move us 'up' } else { curdir = FACE_UP; } break; // end open the door .. default: break; } return 1; }