Esempio n. 1
0
void move_unit(unit * u, region * r, unit ** ulist)
{
  assert(u && r);

  assert(u->faction || !"this unit is dead");
  if (u->region == r)
    return;
  if (!ulist)
    ulist = (&r->units);
  if (u->region) {
    setguard(u, GUARD_NONE);
    fset(u, UFL_MOVED);
    if (u->ship || u->building) {
      /* can_leave must be checked in travel_i */
#ifndef NDEBUG
      bool result = leave(u, false);
      assert(result);
#else
      leave(u, false);
#endif
    }
    translist(&u->region->units, ulist, u);
  } else {
    addlist(ulist, u);
  }

#ifdef SMART_INTERVALS
  update_interval(u->faction, r);
#endif
  u->region = r;
}
Esempio n. 2
0
static void move_iceberg(region * r)
{
  attrib *a;
  direction_t dir;
  region *rc;

  a = a_find(r->attribs, &at_iceberg);
  if (!a) {
    dir = (direction_t) (rng_int() % MAXDIRECTIONS);
    a = a_add(&r->attribs, make_iceberg(dir));
  } else {
    if (rng_int() % 100 < 20) {
      dir = (direction_t) (rng_int() % MAXDIRECTIONS);
      a->data.i = dir;
    } else {
      dir = (direction_t) a->data.i;
    }
  }

  rc = rconnect(r, dir);

  if (rc && !fval(rc->terrain, ARCTIC_REGION)) {
    if (fval(rc->terrain, SEA_REGION)) {        /* Eisberg treibt */
      ship *sh, *shn;
      unit *u;
      int x, y;

      for (u = r->units; u; u = u->next)
        freset(u->faction, FFL_SELECT);
      for (u = r->units; u; u = u->next)
        if (!fval(u->faction, FFL_SELECT)) {
          fset(u->faction, FFL_SELECT);
          ADDMSG(&u->faction->msgs, msg_message("iceberg_drift",
              "region dir", r, dir));
        }

      x = r->x;
      y = r->y;

      runhash(r);
      runhash(rc);
      r->x = rc->x;
      r->y = rc->y;
      rc->x = x;
      rc->y = y;
      rhash(rc);
      rhash(r);

      /* rc ist der Ozean (Ex-Eisberg), r der Eisberg (Ex-Ozean) */

      /* Schiffe aus dem Zielozean werden in den Eisberg transferiert
       * und nehmen Schaden. */

      for (sh = r->ships; sh; sh = sh->next)
        freset(sh, SF_SELECT);

      for (sh = r->ships; sh; sh = sh->next) {
        /* Meldung an Kapitän */
        float dmg =
          get_param_flt(global.parameters, "rules.ship.damage.intoiceberg",
          0.10F);
        damage_ship(sh, dmg);
        fset(sh, SF_SELECT);
      }

      /* Personen, Schiffe und Gebäude verschieben */
      while (rc->buildings) {
        rc->buildings->region = r;
        translist(&rc->buildings, &r->buildings, rc->buildings);
      }
      while (rc->ships) {
        float dmg =
          get_param_flt(global.parameters, "rules.ship.damage.withiceberg",
          0.10F);
        fset(rc->ships, SF_SELECT);
        damage_ship(rc->ships, dmg);
        move_ship(rc->ships, rc, r, NULL);
      }
      while (rc->units) {
        building *b = rc->units->building;
        u = rc->units;
        u->building = 0; /* prevent leaving in move_unit */
        move_unit(rc->units, r, NULL);
        u_set_building(u, b); /* undo leave-prevention */
      }

      /* Beschädigte Schiffe können sinken */

      for (sh = r->ships; sh;) {
        shn = sh->next;
        if (fval(sh, SF_SELECT)) {
          u = ship_owner(sh);
          if (sh->damage >= sh->size * DAMAGE_SCALE) {
            if (u != NULL) {
              ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg_des",
                  "ship", sh));
            }
            remove_ship(&sh->region->ships, sh);
          } else if (u != NULL) {
            ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg",
                "ship", sh));
          }
        }
        sh = shn;
      }

    } else if (rng_int() % 100 < 20) {  /* Eisberg bleibt als Gletscher liegen */
      unit *u;

      rsetterrain(r, T_GLACIER);
      a_remove(&r->attribs, a);

      for (u = r->units; u; u = u->next)
        freset(u->faction, FFL_SELECT);
      for (u = r->units; u; u = u->next)
        if (!fval(u->faction, FFL_SELECT)) {
          fset(u->faction, FFL_SELECT);
          ADDMSG(&u->faction->msgs, msg_message("iceberg_land", "region", r));
        }
    }
  }
}