Beispiel #1
0
bool item::is_food(player *u)
{
 if (u == NULL)
  return is_food();

 if (type->is_food())
  return true;

 if (u->has_bionic(bio_batteries) && is_ammo() &&
     (dynamic_cast<it_ammo*>(type))->type == AT_BATT)
  return true;
 if (u->has_bionic(bio_furnace) && is_flammable(type->m1) &&
     is_flammable(type->m2) && type->id != itm_corpse)
  return true;
 return false;
}
Beispiel #2
0
void
BadGuy::collision_tile(uint32_t tile_attributes)
{
  // Don't kill badguys that have already been killed
  if (!is_active()) return;

  if (tile_attributes & Tile::WATER && !is_in_water())
  {
    m_in_water = true;
    SoundManager::current()->play("sounds/splash.ogg", get_pos());
  }
  if (!(tile_attributes & Tile::WATER) && is_in_water())
  {
    m_in_water = false;
  }

  if (tile_attributes & Tile::HURTS && is_hurtable()) {
    if (tile_attributes & Tile::FIRE) {
      if (is_flammable()) ignite();
    }
    else if (tile_attributes & Tile::ICE) {
      if (is_freezable()) freeze();
    }
    else {
      kill_fall();
    }
  }
}
Beispiel #3
0
bool item::is_food(player *u) const
{
 if (!u)
  return is_food();

 if( is_null() )
  return false;

 if (type->is_food())
  return true;

 if (u->has_bionic("bio_batteries") && is_ammo() &&
     (dynamic_cast<it_ammo*>(type))->type == AT_BATT)
  return true;
 if (u->has_bionic("bio_furnace") && is_flammable(type->m1) &&
     is_flammable(type->m2) && typeId() != "corpse")
  return true;
 return false;
}
void
BadGuy::collision_tile(uint32_t tile_attributes)
{
  if(tile_attributes & Tile::HURTS) {
    if (tile_attributes & Tile::FIRE) {
      if (is_flammable()) ignite();
    }
    else if (tile_attributes & Tile::ICE) {
      if (is_freezable()) freeze();
    }
    else {
      kill_fall();
    }
  }
}
Beispiel #5
0
void
BadGuy::ignite()
{
  if (!is_flammable() || m_ignited) {
    return;
  }

  m_physic.enable_gravity(true);
  m_physic.set_velocity_x(0);
  m_physic.set_velocity_y(0);
  set_group(COLGROUP_MOVING_ONLY_STATIC);
  m_sprite->stop_animation();
  m_ignited = true;

  if (m_sprite->has_action("melting-left")) {

    // melt it!
    if (m_sprite->has_action("ground-melting-left") && on_ground()) {
      m_sprite->set_action(m_dir == Direction::LEFT ? "ground-melting-left" : "ground-melting-right", 1);
      SoundManager::current()->play("sounds/splash.ogg", get_pos());
      set_state(STATE_GROUND_MELTING);
    } else {
      m_sprite->set_action(m_dir == Direction::LEFT ? "melting-left" : "melting-right", 1);
      SoundManager::current()->play("sounds/sizzle.ogg", get_pos());
      set_state(STATE_MELTING);
    }

    run_dead_script();

  } else if (m_sprite->has_action("burning-left")) {
    // burn it!
    m_glowing = true;
    SoundManager::current()->play("sounds/fire.ogg", get_pos());
    m_sprite->set_action(m_dir == Direction::LEFT ? "burning-left" : "burning-right", 1);
    set_state(STATE_BURNING);
    run_dead_script();
  } else if (m_sprite->has_action("inside-melting-left")) {
    // melt it inside!
    SoundManager::current()->play("sounds/splash.ogg", get_pos());
    m_sprite->set_action(m_dir == Direction::LEFT ? "inside-melting-left" : "inside-melting-right", 1);
    set_state(STATE_INSIDE_MELTING);
    run_dead_script();
  } else {
    // Let it fall off the screen then.
    kill_fall();
  }
}
Beispiel #6
0
HitResponse
BadGuy::collision_bullet(Bullet& bullet, const CollisionHit& hit)
{
  if (is_frozen()) {
    if (bullet.get_type() == FIRE_BONUS) {
      // fire bullet thaws frozen badguys
      unfreeze();
      bullet.remove_me();
      return ABORT_MOVE;
    } else {
      // other bullets ricochet
      bullet.ricochet(*this, hit);
      return FORCE_MOVE;
    }
  }
  else if (is_ignited()) {
    if (bullet.get_type() == ICE_BONUS) {
      // ice bullets extinguish ignited badguys
      extinguish();
      bullet.remove_me();
      return ABORT_MOVE;
    } else {
      // other bullets are absorbed by ignited badguys
      bullet.remove_me();
      return FORCE_MOVE;
    }
  }
  else if (bullet.get_type() == FIRE_BONUS && is_flammable()) {
    // fire bullets ignite flammable badguys
    ignite();
    bullet.remove_me();
    return ABORT_MOVE;
  }
  else if (bullet.get_type() == ICE_BONUS && is_freezable()) {
    // ice bullets freeze freezable badguys
    freeze();
    bullet.remove_me();
    return ABORT_MOVE;
  }
  else {
    // in all other cases, bullets ricochet
    bullet.ricochet(*this, hit);
    return FORCE_MOVE;
  }
}
Beispiel #7
0
void
BadGuy::collision_tile(uint32_t tile_attributes)
{
  // Don't kill badguys that have already been killed
  if (!is_active()) return;

  if(tile_attributes & Tile::HURTS) {
    if (tile_attributes & Tile::FIRE) {
      if (is_flammable()) ignite();
    }
    else if (tile_attributes & Tile::ICE) {
      if (is_freezable()) freeze();
    }
    else {
      kill_fall();
    }
  }
}
Beispiel #8
0
struct obj *
mksobj(int otyp, boolean init, boolean artif)
{
    int mndx, tryct;
    struct obj *otmp;
    char let = objects[otyp].oc_class;

    otmp = newobj(0);
    *otmp = zeroobj;
    otmp->age = monstermoves;
    otmp->o_id = flags.ident++;
    if (!otmp->o_id) otmp->o_id = flags.ident++;	/* ident overflowed */
    otmp->quan = 1L;
    otmp->oclass = let;
    otmp->otyp = otyp;
    otmp->where = OBJ_FREE;
    otmp->dknown = index(dknowns, let) ? 0 : 1;
    if (otmp->otyp == AMULET_OF_YENDOR)
        otmp->orecursive = FALSE;
    if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD) ||
            otmp->otyp == SHIELD_OF_REFLECTION)
        otmp->dknown = 0;
    if (!objects[otmp->otyp].oc_uses_known)
        otmp->known = 1;
    if (is_rustprone(otmp) || is_corrodeable(otmp) || is_flammable(otmp))
        otmp->rknown = 1;
#ifdef INVISIBLE_OBJECTS
    otmp->oinvis = !rn2(1250);
#endif
    if (init) switch (let) {
        case WEAPON_CLASS:
            otmp->quan = is_multigen(otmp) ? (long) rn1(6,6) : 1L;
            if(!rn2(11)) {
                otmp->spe = rne(3);
                otmp->blessed = rn2(2);
            } else if(!rn2(10)) {
                curse(otmp);
                otmp->spe = -rne(3);
            } else	blessorcurse(otmp, 10);
            if (is_poisonable(otmp) && !rn2(100))
                otmp->opoisoned = 1;

            if (artif && !rn2(20))
                otmp = mk_artifact(otmp, (aligntyp)A_NONE);
            break;
        case FOOD_CLASS:
            otmp->odrained = 0;
            otmp->oeaten = 0;
            switch(otmp->otyp) {
            case CORPSE:
                /* possibly overridden by mkcorpstat() */
                tryct = 50;
                do otmp->corpsenm = undead_to_corpse(rndmonnum());
                while ((mvitals[otmp->corpsenm].mvflags & G_NOCORPSE) && (--tryct > 0));
                if (tryct == 0) {
                    /* perhaps rndmonnum() only wants to make G_NOCORPSE monsters on
                       this level; let's create an adventurer's corpse instead, then */
                    otmp->corpsenm = PM_HUMAN;
                }
                /* timer set below */
                break;
            case EGG:
                otmp->corpsenm = NON_PM;	/* generic egg */
                if (!rn2(3)) for (tryct = 200; tryct > 0; --tryct) {
                        mndx = can_be_hatched(rndmonnum());
                        if (mndx != NON_PM && !dead_species(mndx, TRUE)) {
                            otmp->corpsenm = mndx;		/* typed egg */
                            attach_egg_hatch_timeout(otmp);
                            break;
                        }
                    }
                break;
            case TIN:
                otmp->corpsenm = NON_PM;	/* empty (so far) */
                if (!rn2(6))
                    otmp->spe = 1;		/* spinach */
                else for (tryct = 200; tryct > 0; --tryct) {
                        mndx = undead_to_corpse(rndmonnum());
                        if (mons[mndx].cnutrit &&
                                !(mvitals[mndx].mvflags & G_NOCORPSE)) {
                            otmp->corpsenm = mndx;
                            break;
                        }
                    }
                blessorcurse(otmp, 10);
                break;
            case SLIME_MOLD:
                otmp->spe = current_fruit;
                break;
            case KELP_FROND:
                otmp->quan = (long) rnd(2);
                break;
            }
            if (otmp->otyp == CORPSE || otmp->otyp == MEAT_RING ||
                    otmp->otyp == KELP_FROND) break;
            /* fall into next case */

        case GEM_CLASS:
            if (otmp->otyp == LOADSTONE) curse(otmp);
            else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6);
            else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L;
            else otmp->quan = 1L;
            break;
        case TOOL_CLASS:
            switch(otmp->otyp) {
            case TALLOW_CANDLE:
            case WAX_CANDLE:
                otmp->spe = 1;
                otmp->age = 20L * /* 400 or 200 */
                            (long)objects[otmp->otyp].oc_cost;
                otmp->lamplit = 0;
                otmp->quan = 1L +
                             (long)(rn2(2) ? rn2(7) : 0);
                blessorcurse(otmp, 5);
                break;
            case BRASS_LANTERN:
            case OIL_LAMP:
                otmp->spe = 1;
                otmp->age = (long) rn1(500,1000);
                otmp->lamplit = 0;
                blessorcurse(otmp, 5);
                break;
            case MAGIC_LAMP:
                otmp->spe = 1;
                otmp->lamplit = 0;
                blessorcurse(otmp, 2);
                break;
            case IRON_SAFE:
                otmp->olocked = 1;
            case CHEST:
            case LARGE_BOX:
                if (otmp->otyp != IRON_SAFE) {
                    otmp->olocked = !!(rn2(5));  /* clumsy tweak */
                }
                otmp->otrapped = !(rn2(10));
            case ICE_BOX:
            case SACK:
            case OILSKIN_SACK:
            case BAG_OF_HOLDING:
                mkbox_cnts(otmp);
                break;
#ifdef TOURIST
            case EXPENSIVE_CAMERA:
#endif
            case TINNING_KIT:
            case MAGIC_MARKER:
                otmp->spe = rn1(60,20);
                break;
            case CAN_OF_GREASE:
                otmp->spe = rnd(25);
                blessorcurse(otmp, 10);
                break;
            case CRYSTAL_BALL:
                otmp->spe = rnd(5);
                blessorcurse(otmp, 2);
                break;
            case HORN_OF_PLENTY:
            case BAG_OF_TRICKS:
                otmp->spe = rnd(20);
                break;
            case FIGURINE:	{
                int tryct2 = 0;
                do
                    otmp->corpsenm = rndmonnum();
                while(is_human(&mons[otmp->corpsenm])
                        && tryct2++ < 30);
                blessorcurse(otmp, 4);
                break;
            }
            case BELL_OF_OPENING:
                otmp->spe = 3;
                break;
            case MAGIC_FLUTE:
            case MAGIC_HARP:
            case FROST_HORN:
            case FIRE_HORN:
            case DRUM_OF_EARTHQUAKE:
                otmp->spe = rn1(5,4);
                break;
            }
            break;
        case AMULET_CLASS:
            if (otmp->otyp == AMULET_OF_YENDOR) flags.made_amulet = TRUE;
            if(rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION ||
                           otmp->otyp == AMULET_OF_CHANGE ||
                           otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) {
                curse(otmp);
            } else	blessorcurse(otmp, 10);
        case VENOM_CLASS:
        case CHAIN_CLASS:
        case BALL_CLASS:
            break;
        case POTION_CLASS:
            if (otmp->otyp == POT_OIL)
                otmp->age = MAX_OIL_IN_FLASK;	/* amount of oil */
            /* fall through */
        case SCROLL_CLASS:
#ifdef MAIL
            if (otmp->otyp != SCR_MAIL)
#endif
                blessorcurse(otmp, 4);
            break;
        case SPBOOK_CLASS:
            blessorcurse(otmp, 17);
            break;
        case ARMOR_CLASS:
            if(rn2(10) && (otmp->otyp == FUMBLE_BOOTS ||
                           otmp->otyp == LEVITATION_BOOTS ||
                           otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT ||
                           otmp->otyp == GAUNTLETS_OF_FUMBLING ||
                           otmp->otyp == TINFOIL_HAT ||
                           !rn2(11))) {
                curse(otmp);
                otmp->spe = -rne(3);
            } else if(!rn2(10)) {
                otmp->blessed = rn2(2);
                otmp->spe = rne(3);
            } else	blessorcurse(otmp, 10);
            if (artif && !rn2(40))
                otmp = mk_artifact(otmp, (aligntyp)A_NONE);
            /* simulate lacquered armor for samurai */
            if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL &&
                    (moves <= 1 || In_quest(&u.uz))) {
#ifdef UNIXPC
                /* optimizer bitfield bug */
                otmp->oerodeproof = 1;
                otmp->rknown = 1;
#else
                otmp->oerodeproof = otmp->rknown = 1;
#endif
            }
            break;
        case WAND_CLASS:
            if (otmp->otyp == WAN_WISHING) {
                otmp->spe = (rnf(2,3) ? 1 : rnf(1,2) ? 0 : 2);
                otmp->recharged = 1;
            } else {
                otmp->spe = rn1(5,
                                (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
                otmp->recharged = 0; /* used to control recharging */
            }
            blessorcurse(otmp, 17);
            break;
        case RING_CLASS:
            if(objects[otmp->otyp].oc_charged) {
                blessorcurse(otmp, 3);
                if(rn2(10)) {
                    if(rn2(10) && bcsign(otmp))
                        otmp->spe = bcsign(otmp) * rne(3);
                    else otmp->spe = rn2(2) ? rne(3) : -rne(3);
                }
                /* make useless +0 rings much less common */
                if (otmp->spe == 0) otmp->spe = rn2(4) - rn2(3);
                /* negative rings are usually cursed */
                if (otmp->spe < 0 && rn2(5)) curse(otmp);
            } else if(rn2(10) && (otmp->otyp == RIN_TELEPORTATION ||
                                  otmp->otyp == RIN_POLYMORPH ||
                                  otmp->otyp == RIN_AGGRAVATE_MONSTER ||
                                  otmp->otyp == RIN_HUNGER || !rn2(9))) {
                curse(otmp);
            }
            break;
        case ROCK_CLASS:
            switch (otmp->otyp) {
            case STATUE:
                /* possibly overridden by mkcorpstat() */
                otmp->corpsenm = rndmonnum();
                if (!verysmall(&mons[otmp->corpsenm]) &&
                        rn2(level_difficulty()/2 + 10) > 10)
                    (void) add_to_container(otmp,
                                            mkobj(SPBOOK_CLASS,FALSE));
            }
            break;
        case COIN_CLASS:
            break;	/* do nothing */
        default:
            warning("impossible mkobj %d, sym '%c'.", otmp->otyp,
                    objects[otmp->otyp].oc_class);
            return (struct obj *)0;
        }

    /* Some things must get done (timers) even if init = 0 */
    switch (otmp->otyp) {
    case CORPSE:
        start_corpse_timeout(otmp);
        break;
    }

    /* unique objects may have an associated artifact entry */
    if (objects[otyp].oc_unique && !otmp->oartifact)
        otmp = mk_artifact(otmp, (aligntyp)A_NONE);
    otmp->owt = weight(otmp);
    return(otmp);
}