Exemplo n.º 1
0
static void godcurse(void)
{
    region *r;

    for (r = regions; r; r = r->next) {
        if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) {
            unit *u;
            for (u = r->units; u; u = u->next) {
                skill *sv = u->skills;
                while (sv != u->skills + u->skill_size) {
                    int weeks = 1 + rng_int() % 3;
                    reduce_skill(u, sv, weeks);
                    ++sv;
                }
            }
            if (fval(r->terrain, SEA_REGION)) {
                ship *sh;
                for (sh = r->ships; sh;) {
                    ship *shn = sh->next;
                    double dmg = config_get_flt("rules.ship.damage.godcurse", 0.1);
                    damage_ship(sh, dmg);
                    if (sh->damage >= sh->size * DAMAGE_SCALE) {
                        unit *u = ship_owner(sh);
                        if (u)
                            ADDMSG(&u->faction->msgs,
                                   msg_message("godcurse_destroy_ship", "ship", sh));
                        remove_ship(&sh->region->ships, sh);
                    }
                    sh = shn;
                }
            }
        }
    }

}
Exemplo n.º 2
0
/* updates positions of fires and also checks for collisions */
void update_fire(void) {
	int i, j;

	/* first loop to update all fires */
	for (i = 0; i < MAX_FIRES; i++) {
		if (fires[i].surface) {
			/* if the laser has expired, free the surface and set it as off, otherwise, update its information */
			if (current_time > fires[i].expire_time) {
				/* fire has expired */
				free_fire(i);
			} else {
				float factor = (((float)loop_length / 1000.0f) * (float)fires[i].velocity);
				fires[i].world_x += get_cos(fires[i].angle) * factor;
				fires[i].world_y += get_neg_sin(fires[i].angle) * factor;

				/* update the fire, hasnt expired yet */
				fires[i].screen_x = (short int)((int)fires[i].world_x - camera_x);
				fires[i].screen_y = (short int)((int)fires[i].world_y - camera_y);
			}
		}
	}

	/* second loop to check for collisions */
	for (i = 0; i < MAX_FIRES; i++) {
		if (fires[i].surface) {
			for (j = 0; j < MAX_SHIPS; j++) {
				if (ships[j]) {
					if ((current_time >= ships[j]->creation_delay) && (!ships[j]->landed) && (ships[j]->hull_strength > 0)) {
						if (fires[i].owner != ships[j]) {
							if (get_distance_sqrd(fires[i].world_x, fires[i].world_y, ships[j]->world_x, ships[j]->world_y) < (ships[j]->model->radius * ships[j]->model->radius)) {
								/* collision has occured */
								damage_ship(ships[j], &fires[i]);
								free_fire(i);
								/* do a check, it's possible the ship was destroyed and freed (and now null) in damage_ship() */
								if (ships[j])
									ship_was_fired_upon(ships[j]);
								j = num_ships; /* dont need to continue checking for more collisions, one is enough */
							}
						}
					}
				}
			}
		}
		/* need to recheck as a destroyed fire could have occured and 'i' may have been incremented */
		if (fires[i].surface) {
			for (j = 0; j < MAX_ASTEROIDS; j++) {
				if (asteroids[j].on) {
					if (get_distance_sqrd(fires[i].world_x, fires[i].world_y, asteroids[j].x, asteroids[j].y) < 2500) {
						/* collision has occured */
						damage_asteroid(j, fires[i].weapon->strength);
						free_fire(i);
						j = MAX_SHIPS; /* dont need to continue checking for more collisions, one is enough */
					}
				}
			}
		}
		/* need to recheck as a destroyed fire could have occured and 'i' may have been incremented */
		if (fires[i].surface) {
			if (fires[i].owner != player.ship) {
				if (get_distance_from_player_sqrd(fires[i].world_x, fires[i].world_y) < (player.ship->model->radius * player.ship->model->radius)) {
					damage_ship(player.ship, &fires[i]);
					free_fire(i);
				}
			}
		}
	}
}
Exemplo n.º 3
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));
        }
    }
  }
}
Exemplo n.º 4
0
void chaos(region * r)
{
  if (rng_int() % 100 < 8) {
    switch (rng_int() % 3) {
      case 0:                  /* Untote */
        if (!fval(r->terrain, SEA_REGION)) {
          unit *u = random_unit(r);
          if (u && playerrace(u_race(u))) {
            ADDMSG(&u->faction->msgs, msg_message("chaos_disease", "unit", u));
            u_setfaction(u, get_monsters());
            u_setrace(u, get_race(RC_GHOUL));
          }
        }
        break;
      case 1:                  /* Drachen */
        if (random_unit(r)) {
          int mfac = 0;
          unit *u;
          switch (rng_int() % 3) {
            case 0:
              mfac = 100;
              u =
                createunit(r, get_monsters(), rng_int() % 8 + 1,
                get_race(RC_FIREDRAGON));
              break;
            case 1:
              mfac = 500;
              u =
                createunit(r, get_monsters(), rng_int() % 4 + 1,
                get_race(RC_DRAGON));
              break;
            default:
              mfac = 1000;
              u =
                createunit(r, get_monsters(), rng_int() % 2 + 1,
                get_race(RC_WYRM));
              break;
          }
          if (mfac)
            set_money(u, u->number * (rng_int() % mfac));
          fset(u, UFL_ISNEW | UFL_MOVED);
        }
      case 2:                  /* Terrainveränderung */
        if (!fval(r->terrain, FORBIDDEN_REGION)) {
          if (!fval(r->terrain, SEA_REGION)) {
            direction_t dir;
            for (dir = 0; dir != MAXDIRECTIONS; ++dir) {
              region *rn = rconnect(r, dir);
              if (rn && fval(rn->terrain, SEA_REGION))
                break;
            }
            if (dir != MAXDIRECTIONS) {
              ship *sh = r->ships;
              unit **up;

              while (sh) {
                ship *nsh = sh->next;
                float dmg =
                  get_param_flt(global.parameters, "rules.ship.damage.atlantis",
                  0.50);
                damage_ship(sh, dmg);
                if (sh->damage >= sh->size * DAMAGE_SCALE) {
                  remove_ship(&sh->region->ships, sh);
                }
                sh = nsh;
              }

              for (up = &r->units; *up;) {
                unit *u = *up;
                if (u_race(u) != get_race(RC_SPELL) && u->ship == 0 && !canfly(u)) {
                  ADDMSG(&u->faction->msgs, msg_message("tidalwave_kill",
                      "region unit", r, u));
                  remove_unit(up, u);
                }
                if (*up == u)
                  up = &u->next;
              }
              ADDMSG(&r->msgs, msg_message("tidalwave", "region", r));

              while (r->buildings) {
                remove_building(&r->buildings, r->buildings);
              }
              terraform_region(r, newterrain(T_OCEAN));
            }
          } else {
            direction_t dir;
            for (dir = 0; dir != MAXDIRECTIONS; ++dir) {
              region *rn = rconnect(r, dir);
              if (rn && fval(rn->terrain, SEA_REGION))
                break;
            }
            if (dir != MAXDIRECTIONS) {
              terraform_region(r, chaosterrain());
            }
          }
        }
    }
  }
}
Exemplo n.º 5
0
Arquivo: gx.c Projeto: LWSS/gx
static void tick_physics(struct GameState *game_state, float dt)
{
    // Projectile kinematics.
    for (uint32 i = 0; i < game_state->projectile_count; ++i)
    {
        struct Projectile *projectile = &game_state->projectiles[i];

        // r = r0 + (v*t) + (a*t^2)/2
        projectile->position = vec2_add(projectile->position, vec2_mul(projectile->velocity, dt));
    }

    // Ship kinematics.
    for (uint32 i = 0; i < game_state->ship_count; ++i)
    {
        struct Ship *ship = &game_state->ships[i];

        vec2 move_acceleration = vec2_zero();

        // v = v0 + (a*t)
        ship->move_velocity = vec2_add(ship->move_velocity, vec2_mul(move_acceleration, dt));

        // r = r0 + (v*t) + (a*t^2)/2
        ship->position = vec2_add(vec2_add(ship->position, vec2_mul(ship->move_velocity, dt)), vec2_div(vec2_mul(move_acceleration, dt * dt), 2.0f));
    }

    //
    // TODO: spatial hashing
    //

    // Projectile collision.
    for (uint32 i = 0; i < game_state->projectile_count; ++i)
    {
        struct Projectile *projectile = &game_state->projectiles[i];
        struct AABB projectile_aabb = aabb_from_transform(projectile->position, projectile->size);

        // Projectile-building collision.
        for (uint32 j = 0; j < game_state->building_count; ++j)
        {
            struct Building *building = &game_state->buildings[j];
            struct AABB building_aabb = aabb_from_transform(building->position, building->size);

            if (aabb_aabb_intersection(projectile_aabb, building_aabb))
            {
                // TODO: damage building if not friendly
                destroy_projectile(game_state, projectile);
                break;
            }
        }

        // NOTE: owner may be dead and destroyed at this point, so checking for NULL might be required.
        struct Ship *owner = get_ship_by_id(game_state, projectile->owner);

        // Projectile-ship collision.
        for (uint32 j = 0; j < game_state->ship_count; ++j)
        {
            struct Ship *ship = &game_state->ships[j];
            if (ship->id == projectile->owner)
                continue;

#if 0
            // Allow projectiles to pass through teammates.
            if (ship->team == projectile->team)
                continue;
#endif

            struct AABB ship_aabb = aabb_from_transform(ship->position, ship->size);

            if (aabb_aabb_intersection(projectile_aabb, ship_aabb))
            {
                // Disable friendly fire.
                if (ship->team != projectile->team)
                    damage_ship(game_state, ship, projectile->damage);

                destroy_projectile(game_state, projectile);
                break;
            }
        }
    }

    // TODO: optimize
    // Ship collision.
    if (game_state->ship_count >= 2)
    {
        for (uint32 i = 0; i < game_state->ship_count - 1; ++i)
        {
            struct Ship *a = &game_state->ships[i];
            struct AABB a_aabb = aabb_from_transform(a->position, a->size);
            vec2 a_center = vec2_div(vec2_add(a_aabb.min, a_aabb.max), 2.0f);
            vec2 a_half_extents = vec2_div(vec2_sub(a_aabb.max, a_aabb.min), 2.0f);

            // Ship-building collision.
            for (uint32 j = 0; j < game_state->building_count; ++j)
            {
                struct Building *building = &game_state->buildings[j];
                struct AABB b_aabb = aabb_from_transform(building->position, building->size);

                if (aabb_aabb_intersection(a_aabb, b_aabb))
                {
                    vec2 b_center = vec2_div(vec2_add(b_aabb.min, b_aabb.max), 2.0f);
                    vec2 b_half_extents = vec2_div(vec2_sub(b_aabb.max, b_aabb.min), 2.0f);

                    vec2 intersection = vec2_sub(vec2_abs(vec2_sub(b_center, a_center)), vec2_add(a_half_extents, b_half_extents));
                    if (intersection.x > intersection.y)
                    {
                        a->move_velocity.x = 0.0f;

                        if (a->position.x < building->position.x)
                            a->position.x += intersection.x/2.0f;
                        else
                            a->position.x -= intersection.x/2.0f;
                    }
                    else
                    {
                        a->move_velocity.y = 0.0f;

                        if (a->position.y < building->position.y)
                            a->position.y += intersection.y/2.0f;
                        else
                            a->position.y -= intersection.y/2.0f;
                    }
                }
            }

            // Ship-ship collision.
            for (uint32 j = i + 1; j < game_state->ship_count; ++j)
            {
                struct Ship *b = &game_state->ships[j];
                struct AABB b_aabb = aabb_from_transform(b->position, b->size);

                if (aabb_aabb_intersection(a_aabb, b_aabb))
                {
                    vec2 b_center = vec2_div(vec2_add(b_aabb.min, b_aabb.max), 2.0f);
                    vec2 b_half_extents = vec2_div(vec2_sub(b_aabb.max, b_aabb.min), 2.0f);

                    vec2 intersection = vec2_sub(vec2_abs(vec2_sub(b_center, a_center)), vec2_add(a_half_extents, b_half_extents));
                    if (intersection.x > intersection.y)
                    {
                        if (abs_float(a->move_velocity.x) > abs_float(b->move_velocity.x))
                            a->move_velocity.x = 0.0f;
                        else
                            b->move_velocity.x = 0.0f;

                        if (a->position.x < b->position.x)
                        {
                            a->position.x += intersection.x/2.0f;
                            b->position.x -= intersection.x/2.0f;
                        }
                        else
                        {
                            a->position.x -= intersection.x/2.0f;
                            b->position.x += intersection.x/2.0f;
                        }
                    }
                    else
                    {
                        if (abs_float(a->move_velocity.y) > abs_float(b->move_velocity.y))
                            a->move_velocity.y = 0.0f;
                        else
                            b->move_velocity.y = 0.0f;

                        if (a->position.y < b->position.y)
                        {
                            a->position.y += intersection.y/2.0f;
                            b->position.y -= intersection.y/2.0f;
                        }
                        else
                        {
                            a->position.y -= intersection.y/2.0f;
                            b->position.y += intersection.y/2.0f;
                        }
                    }
                }
            }
        }
    }
}