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"); }
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"); }
/* * 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); }