Beispiel #1
0
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;
}
Beispiel #2
0
// 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;

}