bool spell_causticblast(int sn, int level, CHAR_DATA * ch, void * vo, int target)
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam(dice(level, 4));

    // Blast them
    act("$n unleashes a blast of hissing acid upon $N!", ch, NULL, victim, TO_NOTVICT);
    act("You unleash a blast of hissing acid upon $N!", ch, NULL, victim, TO_CHAR);
    act("$n unleashes a blast of hissing acid upon you!", ch, NULL, victim, TO_VICT);
    
    if (saves_spell(level, ch, victim, DAM_ACID))
    {
        damage_old(ch, victim, dam / 2, sn, DAM_ACID, true);
        return true;
    }

    damage_old(ch, victim, dam, sn, DAM_ACID, true);
    if (!IS_VALID(victim) || victim->in_room != ch->in_room)
        return true;

    act("The acid eats away at you, leaving painful, ugly scars!", victim, NULL, NULL, TO_CHAR);
    act("The acid eats away at $m, leaving painful, ugly scars!", victim, NULL, NULL, TO_ROOM);
    
    // Apply -charisma
    AFFECT_DATA af = {0};
    af.where    = TO_AFFECTS;
    af.type     = sn;
    af.level    = level;
    af.duration = level / 2;
    af.location = APPLY_CHR;
    af.modifier = -1;
    affect_to_char(victim, &af);

    // Apply burning
    for (AFFECT_DATA * paf(get_affect(victim, sn)); paf != NULL; paf = get_affect(victim, sn, paf))
    {
        if (paf->location == APPLY_NONE)
        {
            paf->duration = UMAX(2, paf->duration);
            paf->modifier = UMIN(100, paf->modifier + 1);
            return true;
        }
    }

    af.duration = 2;
    af.location = APPLY_NONE;
    af.modifier = 1;
    affect_to_char(victim, &af);
    return true;
}
void DamageCoefficients<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  Intrepid2::Tensor<ScalarT> diffusivity(num_dims_);
  Intrepid2::Tensor<ScalarT> I(Intrepid2::eye<ScalarT>(num_dims_));
  Intrepid2::Tensor<ScalarT> tensor;
  Intrepid2::Tensor<ScalarT> F(num_dims_);

  ScalarT dt = delta_time_(0);
  if (dt == 0.0) dt = 1.e-15;
  Albany::MDArray damage_old = (*workset.stateArrayPtr)[damage_name_];
  for (int cell = 0; cell < workset.numCells; ++cell) {
    for (int pt = 0; pt < num_pts_; ++pt) {
      damage_dot_(cell,pt) =
        (damage_(cell,pt) - damage_old(cell,pt)) / dt;
    }
  }

  if (have_mech_) {
    for (int cell = 0; cell < workset.numCells; ++cell) {
      for (int pt = 0; pt < num_pts_; ++pt) {
        F.fill(def_grad_,cell, pt,0,0);
        tensor = Intrepid2::inverse(Intrepid2::transpose(F) * F);
        damage_transient_coeff_(cell, pt) = transient_coeff_;
        diffusivity = diffusivity_coeff_ * tensor;
        for (int i = 0; i < num_dims_; ++i) {
          for (int j = 0; j < num_dims_; ++j) {
            damage_diffusivity_(cell, pt, i, j) = diffusivity(i, j);
          }
        }
      }
    }
  } else {
    for (int cell = 0; cell < workset.numCells; ++cell) {
      for (int pt = 0; pt < num_pts_; ++pt) {
        damage_transient_coeff_(cell, pt) = transient_coeff_;
        diffusivity = diffusivity_coeff_ * I;
        for (int i = 0; i < num_dims_; ++i) {
          for (int j = 0; j < num_dims_; ++j) {
            damage_diffusivity_(cell, pt, i, j) = diffusivity(i, j);
          }
        }
      }
    }
  }
}
void Character::update() {
    AFFECT_DATA *paf;
    AFFECT_DATA *paf_next;

    if ( this->desc && this->desc->connected == CON_PLAYING )
        send_to_char("\n\r",this);

    if ( this->position >= POS_STUNNED )
    {
        if ( this->hit  < this->max_hit )
            this->hit  += this->hit_gain();
        else
            this->hit = this->max_hit;

        if ( this->mana < this->max_mana )
            this->mana += this->mana_gain();
        else
            this->mana = this->max_mana;

        if ( this->move < this->max_move )
            this->move += this->move_gain();
        else
            this->move = this->max_move;
    }

    if ( this->position == POS_STUNNED )
        update_pos( this );

    for ( paf = this->affected; paf != NULL; paf = paf_next )
    {
        paf_next	= paf->next;
        if ( paf->duration > 0 )
        {
            paf->duration--;
            if (number_range(0,4) == 0 && paf->level > 0)
                paf->level--;  /* spell strength fades with time */
        }
        else if ( paf->duration < 0 )
            ;
        else
        {
            if ( paf_next == NULL
                    ||   paf_next->type != paf->type
                    ||   paf_next->duration > 0 )
            {
                if ( paf->type > 0 && skill_table[paf->type].msg_off )
                {
                    send_to_char( skill_table[paf->type].msg_off, this );
                    send_to_char( "\n\r", this );
                }
            }

            affect_remove( this, paf );
        }
    }

    /*
     * Careful with the damages here,
     *   MUST NOT refer to ch after damage taken,
     *   as it may be lethal damage (on NPC).
     */

    if (is_affected(this, gsn_plague) && this != NULL)
    {
        if (this->in_room == NULL)
            return;

        ::act("$n writhes in agony as plague sores erupt from $s skin.",
                this,NULL,NULL,TO_ROOM);
        send_to_char("You writhe in agony from the plague.\n\r",this);

        AFFECT_DATA *af;
        for ( af = this->affected; af != NULL; af = af->next )
        {
            if (af->type == gsn_plague)
                break;
        }

        if (af == NULL)
        {
            REMOVE_BIT(this->affected_by,AFF_PLAGUE);
            return;
        }

        if (af->level == 1)
            return;

        AFFECT_DATA plague;
        plague.where		= TO_AFFECTS;
        plague.type 		= gsn_plague;
        plague.level 		= af->level - 1;
        plague.duration 	= number_range(1,2 * plague.level);
        plague.location		= APPLY_STR;
        plague.modifier 	= -5;
        plague.bitvector 	= AFF_PLAGUE;

        for ( Character* vch = this->in_room->people; vch != NULL; vch = vch->next_in_room)
        {
            if (!saves_spell(plague.level - 2,vch,DAM_DISEASE)
                    &&  !IS_IMMORTAL(vch)
                    &&  !IS_AFFECTED(vch,AFF_PLAGUE) && number_bits(4) == 0)
            {
                send_to_char("You feel hot and feverish.\n\r",vch);
                ::act("$n shivers and looks very ill.",vch,NULL,NULL,TO_ROOM);
                affect_join(vch,&plague);
            }
        }

        int dam = UMIN(this->level,af->level/5+1);
        this->mana -= dam;
        this->move -= dam;
        damage_old( this, this, dam, gsn_plague,DAM_DISEASE,FALSE);
    }
    else if ( IS_AFFECTED(this, AFF_POISON) && this != NULL
            &&   !IS_AFFECTED(this,AFF_SLOW))

    {
        AFFECT_DATA *poison;

        poison = affect_find(this->affected,gsn_poison);

        if (poison != NULL)
        {
            ::act( "$n shivers and suffers.", this, NULL, NULL, TO_ROOM );
            send_to_char( "You shiver and suffer.\n\r", this );
            damage_old(this,this,poison->level/10 + 1,gsn_poison,
                    DAM_POISON,FALSE);
        }
    }

    else if ( this->position == POS_INCAP && number_range(0,1) == 0)
    {
        ::damage( this, this, 1, TYPE_UNDEFINED, DAM_NONE,FALSE);
    }
    else if ( this->position == POS_MORTAL )
    {
        ::damage( this, this, 1, TYPE_UNDEFINED, DAM_NONE,FALSE);
    }
}