Exemplo n.º 1
0
void thing_reached_teleport (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 = 
                &server_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;
            }

            const char *tcol;
            const char *col;

            if (teleport->data) {
                tcol = teleport->data->col_name;
            } else {
                tcol = 0;
            }

            col = tile->data.col_name;

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

            if (!strcmp(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(server_level, nx, ny)) {
        return;
    }

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

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

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

    THING_LOG(t, "teleport");

    wid_move_end(t->wid);

    thing_server_wid_update(t, nx, ny, true /* is_new */);
    thing_update(t);

    /*
     * Make sure the client sees the jump
     */
    t->needs_tx_refresh_xy_and_template_id = 1;

    thing_handle_collisions(wid_game_map_server_grid_container, t);

    MSG_SERVER_SHOUT_AT_ALL_PLAYERS(SOUND, t->x, t->y, "teleport");
}
Exemplo n.º 2
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");
}
Exemplo n.º 3
0
/*
 * Try to fall down
 */
int thing_fall (levelp level, thingp t)
{
    double x = t->x;
    double y = t->y + 0.015;
    thingp it;

    if (thing_is_monst(t)  ||
        thing_is_ladder(t) ||
        thing_is_player(t)) {

        it = thing_overlaps(level, t, t->x, t->y, thing_is_ladder);
        if (it) {
            thing_hit_ground(level, t, it);
            return (false);
        }
    }

    if (t->jump_speed) {
        t->fall_speed = 0;
        return (false);
    }

    if (thing_is_monst(t)  ||
        thing_is_player(t)) {

        if (t->fall_speed > THING_FALL_SPEED_HIT_SPIKES) {
            it = thing_overlaps(level, t, t->x, t->y, thing_is_spikes);
            if (it) {
                THING_LOG(t, "fell onto spikes (%f)", t->fall_speed);

                (void) thing_hit(level, t, it, 1);
            }
        }
    }

    it = thing_hit_fall_obstacle(level, t, x, y);
    if (it) {
        thing_hit_ground(level, t, it);
        return (false);
    }

    t->fall_speed += THING_FALL_SPEED_GRAVITY;

    t->falling_too_fast = false;
    if (t->fall_speed - t->jump_speed > THING_FALL_SPEED_TOO_FAST) {
        t->falling_too_fast = true;
    }

    if (t->fall_speed > 1) {
        t->fall_speed = 1;
    }

    y = t->y + t->fall_speed;
    it = thing_hit_fall_obstacle(level, t, x, y);
    if (it) {
        y = t->y + t->fall_speed / 2;
        it = thing_hit_fall_obstacle(level, t, x, y);
        if (it) {
            y = t->y + t->fall_speed / 4;
            it = thing_hit_fall_obstacle(level, t, x, y);
            if (it) {
                y = t->y + t->fall_speed / 4;
                it = thing_hit_fall_obstacle(level, t, x, y);
                if (it) {
                    thing_hit_ground(level, t, it);
                    return (false);
                }
            }
        }
    }

    thing_wid_update(level, t, x, y, true, false /* is new */);

    thing_handle_collisions(level, t);

    return (true);
}