/*
 * Map a trigger to a slot number if it has not been done so already
 */
void level_trigger_alloc (levelp level, color c)
{
    if (color_none(c)) {   
        c = default_trigger;
    }

    int i;

    if (level_trigger2slot(level, c) != -1) {
        return;
    }

    /*
     * See if the trigger exists
     */
    for (i = 0; i < ARRAY_SIZE(level->trigger); i++) {
        if (color_none(level->trigger[i].c)) {
            level->trigger[i].c = c;

            LEVEL_LOG(level, "Allocate trigger, %u.%u.%u.%u", c.a, c.r, c.g, c.a);
            return;
        }
    }

    ERR("out of level triggers trying to add %u.%u.%u.%u", c.a, c.r, c.g, c.a);
}
/*
 * Find an existing trigger and which slot it is in
 */
int level_trigger2slot (levelp level, color c)
{
    if (color_none(c)) {   
        c = default_trigger;
    }

    int i;

    /*
     * See if the trigger exists
     */
    for (i = 0; i < ARRAY_SIZE(level->trigger); i++) {
        if (color_none(level->trigger[i].c)) {
            break;
        }

        if (color_cmp(c, level->trigger[i].c)) {
            return (i);
        }
    }

    return (-1);
}
static void level_trigger_mark_activate (levelp level, color c)
{
    if (color_none(c)) {   
        c = default_trigger;
    }

    int slot;

    slot = level_trigger2slot(level, c);
    if (slot == -1) {
        ERR("Cannot activate trigger %u.%u.%u.%u", c.a, c.r, c.g, c.a);
    }

    level->trigger[slot].activated = 1;
}
int level_trigger_is_activated (levelp level, color c)
{
    if (color_none(c)) {   
        c = default_trigger;
    }

    int slot;

    slot = level_trigger2slot(level, c);
    if (slot == -1) {
        ERR("cannot check if activated, name %u.%u.%u.%u", c.a, c.r, c.g, c.a);
    }

    return (level->trigger[slot].activated);
}
Exemple #5
0
/* plot areas */
int PS_vareas_plot(struct Map_info *P_map, int vec)
{
    int na, area, ret;
    double e, w, n, s, aw, shift;
    double llx, lly, urx, ury, sc;
    char pat[50];
    struct line_cats *Cats;
    struct bound_box box;
    struct varray *Varray = NULL;
    PSCOLOR color;
    int centroid;

    /* rgbcol */
    dbCatValArray cvarr_rgb;

    fprintf(PS.fp, "1 setlinejoin\n");	/* set line join to round */

    Cats = Vect_new_cats_struct();

    /* Create vector array if required */
    if (vector.layer[vec].cats != NULL || vector.layer[vec].where != NULL) {
	Varray = Vect_new_varray(Vect_get_num_areas(P_map));
	if (vector.layer[vec].cats != NULL) {
	    ret =
		Vect_set_varray_from_cat_string(P_map,
						vector.layer[vec].field,
						vector.layer[vec].cats,
						GV_AREA, 1, Varray);
	}
	else {
	    ret = Vect_set_varray_from_db(P_map, vector.layer[vec].field,
					  vector.layer[vec].where, GV_AREA, 1,
					  Varray);
	}
	G_debug(3, "%d items selected for vector %d", ret, vec);
	if (ret == -1)
	    G_fatal_error(_("Cannot load data from table"));
    }

    /* load attributes if rgbcol used */
    if (vector.layer[vec].rgbcol != NULL) {
	load_catval_array_rgb(P_map, vec, &cvarr_rgb);
    }

    shift = 0;
    /* read and plot areas */
    na = Vect_get_num_areas(P_map);
    for (area = 1; area <= na; area++) {
	G_debug(4, "area = %d", area);

	if (Varray != NULL && Varray->c[area] == 0)
	    continue;		/* is not in array */

	if (!Vect_area_alive(P_map, area))
	    continue;

	centroid = Vect_get_area_centroid(P_map, area);
	G_debug(4, "centroid = %d", centroid);
	if (centroid < 1)  /* area is an island */
	    continue;

	Vect_get_area_box(P_map, area, &box);
	n = box.N;
	s = box.S;
	e = box.E;
	w = box.W;
	if (PS.w.proj == PROJECTION_LL) {
	    aw = G_adjust_easting(w, &PS.w);
	    if (aw > PS.w.east)
		aw -= 360.0;
	    shift = aw - w;
	    e += shift;
	    w += shift;
	}
	/* check if in window */
	if (n < PS.w.south || s > PS.w.north || e < PS.w.west ||
	    w > PS.w.east)
	    continue;

	fprintf(PS.fp, "NP\n");
	if (PS.w.proj == PROJECTION_LL) {
	    /* plot area while in window */
	    while (e > PS.w.west) {
		ret = plot_area(P_map, area, shift);
		if (ret != 1)
		    return 0;
		shift -= 360.0;
		e -= 360.0;
	    }
	}
	else {
	    ret = plot_area(P_map, area, shift);
	    if (ret != 1)
		return 0;
	}

	if (vector.layer[vec].pat != NULL ||
	    (!color_none(&vector.layer[vec].fcolor) ||
	     vector.layer[vec].rgbcol != NULL)) {

	    if (vector.layer[vec].rgbcol != NULL) {
		/* load fill color from rgbcol */
		/* if data column is empty or cat is missing don't fill */
		if (get_ps_color_rgbcol_varea(P_map, vec, area, &cvarr_rgb, &color) != 1)
		    return 0;
	    }
	    else {
		color = vector.layer[vec].fcolor;
	    }

	    if (vector.layer[vec].pat != NULL) {	/* use pattern */
		sc = vector.layer[vec].scale;
		/* DEBUG */
		/*
		   printf("\n eps pattern = %s\n", vector.layer[vec].eps);
		   printf("       scale = %f\n", vector.layer[vec].scale);
		 */
		/* load pattern */
		eps_bbox(vector.layer[vec].pat, &llx, &lly, &urx, &ury);
		sprintf(pat, "APATTEPS%d", vec);
		pat_save(PS.fp, vector.layer[vec].pat, pat);
		fprintf(PS.fp,
			"<<  /PatternType 1\n    /PaintType 1\n    /TilingType 1\n");
		fprintf(PS.fp, "    /BBox [%f %f %f %f]\n", llx * sc,
			lly * sc, urx * sc, ury * sc);
		fprintf(PS.fp, "    /XStep %f\n    /YStep %f\n",
			(urx - llx) * sc, (ury - lly) * sc);
		fprintf(PS.fp, "    /PaintProc\n      { begin\n");
		fprintf(PS.fp, "        %f %f scale\n", sc, sc);

		set_ps_color(&color);

		fprintf(PS.fp, "        %.8f W\n", vector.layer[vec].pwidth);
		fprintf(PS.fp, "        %s\n", pat);
		fprintf(PS.fp, "        end\n");
		fprintf(PS.fp, "      } bind\n>>\n");
		sprintf(pat, "APATT%d", vec);
		fprintf(PS.fp, " matrix\n makepattern /%s exch def\n", pat);
		fprintf(PS.fp, "/Pattern setcolorspace\n %s setcolor\n", pat);
	    }
	    else {
		set_ps_color(&color);
	    }

	    fprintf(PS.fp, "F\n");
	}
	if (vector.layer[vec].width > 0 &&
	    !(color_none(&vector.layer[vec].color))) {
	    fprintf(PS.fp, "%.8f W\n", vector.layer[vec].width);
	    set_ps_color(&(vector.layer[vec].color));
	    fprintf(PS.fp, "stroke\n");
	}
    }
    fprintf(PS.fp, "\n");
    fprintf(PS.fp, "0 setlinejoin\n");	/* reset line join to miter */
    return 1;
}
Exemple #6
0
int read_text(char *east, char *north, char *text)
{
    PSCOLOR color, hcolor, background, border;
    int r, g, b;
    int ret;
    int xoffset;
    int yoffset;
    float size;
    int fontsize;
    double width;
    double hwidth;
    double rotate;
    int xref, yref;
    int opaque;
    char t1[128];
    char buf[1024];
    char *key, *data;
    FILE *fd;
    char fontname[128];

    set_color(&color, 0, 0, 0);	/* black */
    unset_color(&hcolor);
    unset_color(&background);
    unset_color(&border);
    opaque = TRUE;
    size = 0.0;
    fontsize = 0;
    xoffset = 0;
    yoffset = 0;
    width = 1.;
    hwidth = 0.;
    rotate = 0.0;
    xref = CENTER;
    yref = CENTER;
    G_strcpy(fontname, "Helvetica");

    while (*text == ' ' || *text == '\t')
	text++;
    if (*text == '\\')
	text++;
    if (*text == 0) {
	error("text", "", "no text given");
	gobble_input();
	return 0;
    }

    while (input(2, buf, help)) {
	if (!key_data(buf, &key, &data))
	    continue;

	if (KEY("font")) {
	    get_font(data);
	    strcpy(fontname, data);
	    continue;
	}

	if (KEY("color")) {
	    ret = G_str_to_color(data, &r, &g, &b);
	    if (ret == 1)
		set_color(&color, r, g, b);
	    else if (ret == 2)
		error(key, data, "primary color cannot be \"none\"");
	    else
		error(key, data, "illegal color request");

	    continue;
	}

	if (KEY("hcolor")) {
	    ret = G_str_to_color(data, &r, &g, &b);
	    if (ret == 1)
		set_color(&hcolor, r, g, b);
	    else if (ret == 2)
		unset_color(&hcolor);
	    else
		error(key, data, "illegal hcolor request");

	    if (color_none(&hcolor) || hwidth <= 0.)
		hwidth = 0.;
	    continue;
	}

	if (KEY("background")) {
	    ret = G_str_to_color(data, &r, &g, &b);
	    if (ret == 1)
		set_color(&background, r, g, b);
	    else if (ret == 2) {
		unset_color(&background);
		opaque = FALSE;
	    }
	    else
		error(key, data, "illegal background color request");

	    continue;
	}

	if (KEY("border")) {
	    ret = G_str_to_color(data, &r, &g, &b);
	    if (ret == 1)
		set_color(&border, r, g, b);
	    else if (ret == 2)
		unset_color(&border);
	    else
		error(key, data, "illegal border color request");

	    continue;
	}

	if (KEY("opaque")) {
	    opaque = yesno(key, data);
	    continue;
	}

	if (KEY("width")) {
	    width = -1.;
	    *t1 = 0;
	    if (sscanf(data, "%lf%1s", &width, t1) < 1 || width < 0.) {
		width = 1.;
		error(key, data, "illegal width request");
	    }
	    if (t1 && t1[0] == 'i')
		width = width / 72.0;
	    continue;
	}

	if (KEY("hwidth")) {
	    hwidth = -1.;
	    *t1 = 0;
	    if (sscanf(data, "%lf%1s", &hwidth, t1) < 1 || hwidth < 0.) {
		hwidth = 0.;
		error(key, data, "illegal width request");
	    }
	    if (t1 && t1[0] == 'i')
		hwidth = hwidth / 72.0;
	    continue;
	}

	if (KEY("size")) {
	    double x;

	    if (!scan_resolution(data, &x)) {
		size = 0.0;
		error(key, data, "illegal size request");
	    }
	    else
		size = x;
	    continue;
	}

	if (KEY("fontsize")) {
	    if (sscanf(data, "%d", &fontsize) != 1 || fontsize <= 0) {
		error(key, data, "illegal fontsize request");
	    }
	    else
		continue;
	}

	if (KEY("xoffset")) {
	    *t1 = 0;
	    if (sscanf(data, "%d%1s", &xoffset, t1) != 1 || *t1) {
		xoffset = 0;
		error(key, data, "illegal request (text)");
	    }
	    continue;
	}

	if (KEY("yoffset")) {
	    *t1 = 0;
	    if (sscanf(data, "%d%1s", &yoffset, t1) != 1 || *t1) {
		yoffset = 0;
		error(key, data, "illegal request (text)");
	    }
	    continue;
	}

	if (KEY("rotate")) {
	    if (sscanf(data, "%lf", &rotate) != 1) {
		rotate = 0.0;
		error(key, data, "illegal rotate request");
	    }
	    continue;
	}

	if (KEY("ref")) {
	    if (!scan_ref(data, &xref, &yref)) {
		xref = CENTER;
		yref = CENTER;
		error(key, data, "illegal ref request");
	    }
	    continue;
	}

	error(key, data, "illegal request (text)");
    }

    /* if file doesn't exist create it and close it */
    if (labels.other == NULL) {
	labels.other = G_tempfile();
	if ((fd = fopen(labels.other, "w")) != NULL)
	    fclose(fd);
    }

    /* open file in append mode */
    fd = fopen(labels.other, "a");
    if (fd == NULL) {
	error("misc labels file", "", "can't open");
	return 1;
    }

    /* write the file */
    fprintf(fd, "font: %s\n", fontname);
    fprintf(fd, "east: %s\n", east);
    fprintf(fd, "north: %s\n", north);
    fprintf(fd, "xoffset: %d\n", xoffset);
    fprintf(fd, "yoffset: %d\n", yoffset);
    fprintf(fd, "width: %f\n", width);
    fprintf(fd, "hwidth: %f\n", hwidth);
    fprintf(fd, "size: %f\n", size);
    fprintf(fd, "fontsize: %d\n", fontsize);
    fprintf(fd, "opaque: %s\n", opaque ? "yes" : "no");
    if (rotate != 0)
	fprintf(fd, "rotate: %f\n", rotate);

    fprintf(fd, "color: ");
    if (!color_none(&color))
	fprintf(fd, "%d:%d:%d\n", color.r, color.g, color.b);
    else
	fprintf(fd, "black\n");

    fprintf(fd, "hcolor: ");
    if (!color_none(&hcolor))
	fprintf(fd, "%d:%d:%d\n", hcolor.r, hcolor.g, hcolor.b);
    else
	fprintf(fd, "none\n");

    fprintf(fd, "background: ");
    if (!color_none(&background))
	fprintf(fd, "%d:%d:%d\n", background.r, background.g, background.b);
    else
	fprintf(fd, "none\n");


    fprintf(fd, "border: ");
    if (!color_none(&border))
	fprintf(fd, "%d:%d:%d\n", border.r, border.g, border.b);
    else
	fprintf(fd, "none\n");

    fprintf(fd, "ref: ");
    switch (yref) {
    case UPPER:
	fprintf(fd, "upper");
	break;
    case LOWER:
	fprintf(fd, "lower");
	break;
    case CENTER:
	fprintf(fd, "center");
	break;
    }
    switch (xref) {
    case LEFT:
	fprintf(fd, " left");
	break;
    case RIGHT:
	fprintf(fd, " right");
	break;
    case CENTER:
	fprintf(fd, "%s", (xref == CENTER) ? "" : " center");
	break;
    }
    fprintf(fd, "\n");
    fprintf(fd, "text:%s\n\n", text);
    fclose(fd);

    return 0;
}
void thing_reached_teleport (levelp level,
                             thingp t, 
                             thingp teleport)
{
    int tx[MAP_WIDTH*MAP_HEIGHT];
    int ty[MAP_WIDTH*MAP_HEIGHT];
    int poss = 0;

    int x, y;

    int delay = 20;

    if (!thing_is_player(t)) {
        /*
         * Only move other things sometimes.
         */
        if ((myrand() % 100) < 95) {
            return;
        }
    }

    if (!time_have_x_tenths_passed_since(delay, 
                                         t->timestamp_last_teleport)) {
        return;
    }

    for (x = 0; x < MAP_WIDTH; x++) {
        for (y = 0; y < MAP_HEIGHT; y++) {

            level_map_tile *tile = 
                &level->map_grid.tile[x][y][MAP_DEPTH_EXPLOSION];

            tpp it = tile->tp;
            if (!it) {
                continue;
            }

            if (!tp_is_teleport(it)) {
                continue;
            }

            if (DISTANCE(t->x, t->y, x, y) < 2.0) {
                continue;
            }

            color tcol;
            color col;

            tcol = teleport->data.col;

            col = tile->data.col;

            if (color_none(col) || color_none(tcol)) {
                tx[poss] = x;
                ty[poss] = y;
                poss++;
                continue;
            }

            if (color_cmp(col, tcol)) {
                tx[poss] = x;
                ty[poss] = y;
                poss++;
                continue;
            }
        }
    }

    if (!poss) {
        return;
    }

    t->timestamp_last_teleport = time_get_time_ms();

    poss = myrand() % poss;

    double nx = tx[poss];
    double ny = ty[poss];

    /*
     * Don't let lava spawn continually on top of itself.
     */
    if (thing_is_lava(t) && map_is_lava_at(level, nx, ny)) {
        return;
    }

    /*
     * Don't let water spawn continually on top of itself.
     */
    if (thing_is_water(t) && map_is_water_at(level, nx, ny)) {
        return;
    }

    /*
     * Don't let acid spawn continually on top of itself.
     */
    if (thing_is_acid(t) && map_is_acid_at(level, nx, ny)) {
        return;
    }

    /*
     * Don't let water spawn continually on top of itself.
     */
    if (thing_is_water(t) && map_is_water_at(level, nx, ny)) {
        return;
    }

    /*
     * Don't let monsters spawn continually on top of themselves.
     */
    if (thing_is_monst(t) && map_is_monst_at(level, nx, ny)) {
        return;
    }

    THING_LOG(t, "Teleport");

    wid_move_end(t->wid);

    thing_wid_update(level,
                     t, nx, ny, 
                     false /* smooth */,
                     true /* is_new */);

    /*
     * Make sure the client sees the jump
     */
    thing_handle_collisions(level, t);

    MSG_SHOUT_AT(SOUND, t, t->x, t->y, "teleport");
}
/*
 * Activate any triggers that don't have anything to activate them! i.e. a 
 * move trigger without any activate triogger.
 */
void level_trigger_activate_default_triggers (levelp level)
{
    int x, y;

    level_trigger_alloc(level, default_trigger);

    for (x = 0; x < MAP_WIDTH; x++) {
        for (y = 0; y < MAP_HEIGHT; y++) {

            level_map_tile *tile = 
                            &level->map_grid.tile[x][y][MAP_DEPTH_ACTIONS];

            tpp it = tile->tp;
            if (!it) {
                continue;
            }

            if (tp_is_action(it)) {
                color c = tile->data.col;

                LEVEL_LOG(level, "Found action color %u.%u.%u.%u", c.a, c.r, c.g, c.a);

                level_trigger_alloc(level, c);
            }

            if (tp_is_action_trigger(it)) {
                color c = tile->data.col;

                LEVEL_LOG(level, "Found action trigger, %u.%u.%u.%u", c.a, c.r, c.g, c.a);

                level_trigger_mark_activate_exists(level, c);
                continue;
            }
        }
    }

    int i;

    for (i = 0; i < ARRAY_SIZE(level->trigger); i++) {
        color c = level->trigger[i].c;

        if (color_none(c)) {
            break;
        }

        if (!level->trigger[i].activate_exists) {
            /*
             * If nothing exists to activate it, activate it now.
             */
            LEVEL_LOG(level, "No action trigger exists, activate trigger, %u.%u.%u.%u", 
                      c.a, c.r, c.g, c.a);

            level_trigger_activate(level, c);
        } else {
            /*
             * Else we wait to be activated.
             */
            LEVEL_LOG(level, "Sleeping trigger, %u.%u.%u.%u", c.a, c.r, c.g, c.a);
        }
    }
}
void level_trigger_activate (levelp level, color c)
{
    int x, y, z;
    int spawned = false;
    int zapped = false;

    if (level_trigger_is_activated(level, c)) {
        return;
    }

    LEVEL_LOG(level, "Activate trigger, %u.%u.%u.%u", c.a, c.r, c.g, c.a);

    level_trigger_mark_activate(level, c);

    /*
     * Look for any items to be spawned.
     *
     * We don't need to activate movement tiles as they will be activated by 
     * the move tiles themselves during collision testing.
     */
    for (x = 0; x < MAP_WIDTH; x++) {
        for (y = 0; y < MAP_HEIGHT; y++) {

            level_map_tile *tile = 
                            &level->map_grid.tile[x][y][MAP_DEPTH_ACTIONS];

            tpp tile_tp = tile->tp;
            if (!tile_tp) {
                continue;
            }

            color it_trigger = tile->data.col;
            if (color_none(it_trigger)) {
                it_trigger = default_trigger;
            }

            if (!color_cmp(it_trigger, c)) {
                continue;
            }

            /*
             * Look for the original thing that it looks like we wanted to 
             * destroy. Then try and find it on the map.
             */
            tpp triggerd_tp = 0;

            for (z = MAP_DEPTH_ACTIONS - 1; z >= 0; z--) {
                triggerd_tp = level->map_grid.tile[x][y][z].tp;
                if (triggerd_tp) {
                    break;
                }
            }

            if (!triggerd_tp) {
                continue;
            }

            /*
             * Any sleeping things that need to be awoken? Actually they don't 
             * exist yet, so we need to create them. It's best not to waste 
             * resources with sleeping things until they are needed.
             */
            if (tp_is_action_sleep(tile_tp)) {
                LEVEL_LOG(level, "Spawn %s via movement trigger %u.%u.%u.%u", 
                          tp_name(triggerd_tp),
                          c.a, c.r, c.g, c.a);

                widp w = wid_game_map_replace_tile(level,
                                                   x,
                                                   y,
                                                   0, /* thing */
                                                   triggerd_tp,
                                                   0 /* tpp data */
                                                   );
                /*
                 * For things like bombs and the like, make them active.
                 */
                thingp t = wid_get_thing(w);
                if (t) {
                    thing_wake(level, t);
                }

                spawned = 1;
            }

            /*
             * Any things that need to be zapped?
             */
            if (tp_is_action_zap(tile_tp)) {
                thingp t = map_is_tp_at(level, x, y, triggerd_tp);
                if (t) {
                    LEVEL_LOG(level, "Kill %s via movement trigger %u.%u.%u.%u", 
                              thing_logname(t), 
                              c.a, c.r, c.g, c.a);

                    thing_dead(level, t, 0, "killed by zap trigger");

                    zapped = true;
                }
            }

            /*
             * Activate any blocks sitting on movement actions. This will
             * allow them to do collision testing with the action block and
             * then move.
             */
            if (tp_is_action_left(tile_tp)  ||
                tp_is_action_right(tile_tp) ||
                tp_is_action_up(tile_tp)    ||
                tp_is_action_down(tile_tp)) {

                thingp t = map_is_tp_at(level, x, y, triggerd_tp);
                if (t) {
                    LEVEL_LOG(level, "Active %s via movement trigger %u.%u.%u.%u", 
                              thing_logname(t), 
                              c.a, c.r, c.g, c.a);

                    level_trigger_move_thing(level, tile_tp, t);
                }
            }
        }
    }

    if (spawned) {
        sound_play_slime();
    }
}