/*
   * eDamageState values:
    * 0 dsUnaffected    - not affected (100% health)
    * 1 dsUnchanged     - didn't change state
    * 2 dsNowYellow     - changed to yellow (only if was in green, otherwise remains unchanged)
    * 3 dsNowRed        - changed to red
    * 4 dsDeath         - changed to dead, Health = 0
    * 5 dsPostMortem    - dead, just cleaning up
  */

eDamageState ObjectClass::ReceiveDamage(int &damage, int unknown, WarheadTypeClass *WH, TechnoClass *attacker, bool ignoreDefenses, int arg10, HouseClass *attackerHouse) {

  eDamageState TransitionState = dsUnaffected;
  int preDmgHealth = this->Health;

  if( preDmgHealth <= 0 )
    return TransitionState;

  int actualDamage = damage;
  if( !damage )
    return TransitionState;

  if( !ignoreDefenses && this->GetType()->Immune )
    return TransitionState;

  ObjectTypeClass *objType = this->GetType();
  int Strength = objType->Strength;
  if ( !ignoreDefenses ) {
    TechnoTypeClass *Type = this->GetType();
    actualDamage = GetVersedDamage(actualDamage, WH, Type->Armor, unknown);
  }

  if ( this ) {
    if ( this->What_Am_I() == IS_BUILDING ) {
      if ( !this->BuildingType->CanC4 ) {
        actualDamage = max(actualDamage, 1);
      }
    }
  }

  if ( !actualDamage )
    return dsUnaffected;

  if ( actualDamage >= 0 ) {
    TransitionState = dsUnchanged;
    if ( preDmgHealth <= realDamage ) {
      actualDamage = preDmgHealth;
    } else {
      if ( preDmgHealth >= Strength / 2 ) {
        if ( preDmgHealth - realDamage < strength / 2 )
          TransitionState = dsNowYellow;
      }
    }

    if ( preDmgHealth > Rules->ConditionRed ) {
      if ( (preDmgHealth - actualDamage) <= Rules->ConditionRed )
        tmpTransitionState = dsNowRed;
    }

    int remainHealth = preDmgHealth - actualDamage;
    this->Health = remainHealth;
    if ( remainHealth > 0
      || this->What_Am_I() != eInfantry
      || ignoreDefenses
      || !((InfantryClass *)this)->InfantryType
      || this->IsCyborgRespawn ) {
      transitionState = tmpTransitionState;
    } else { // Cyborg death
      new AnimClass(
        Rules->InfantryExplode,
        this->pos,
        0,
        1,
        sizeof(AnimClass),
        0,
        0);
      int tmpHealth = FloatToInt(this->InfantryType->Strength * 0.25);
      this->Health = tmpHealth;
      if ( tmpHealth <= 1 )
        tmpHealth = 1;
      this->Health = tmpHealth;
      this->IsCyborgRespawn = 1;
      this->PlayAnim(ANIM_CRAWL);
      TransitionState = dsNowRed;
    }
    int preTagHealth = this->Health;
    if ( TransitionState == dsNowYellow ) {
      if ( source ) {
        if ( this->Tag )
          this->Tag->RaiseEvent(ekHalfHealth_combatonly, this, blankCoords, 0, NULL);
      }
      if ( !this->Alive )
        return dsPostMortem;
      if ( this->Tag )
        this->Tag->RaiseEvent(ekHalfHealth_anysource, this, blankCoords, 0, NULL);
    }
    if ( this->Alive ) {
      if ( transitionState == dsNowRed ) {
        if ( source ) {
          if ( this->Tag )
            this->Tag->RaiseEvent(ekQuarterHealth_combatonly, this, blankCoords, 0, NULL);
        }
        if ( !this->Alive )
          return dsPostMortem;
        if ( this->Tag )
          this->Tag->RaiseEvent(ekQuarterHealth_anysource, this, blankCoords, 0, NULL);
      }
      if ( this->Alive ) {
        if ( this->Health != preDmgHealth ) {
          if ( this->vt->GetType() ) {
            if ( predmgHealth == this->GetType()->Strength ) {
              if ( source ) {
                if ( this->Tag )
                  this->Tag->RaiseEvent(ekFirstDamaged_combatonly, this, blankCoords, 0, NULL);
              }
              if ( this->Tag ) {
                if ( this->Alive )
                  this->Tag->RaiseEvent(ekFirstDamaged_anysource, this, blankCoords, 0, NULL);
              }
              if ( this->Tag )
              {
                if ( !this->Alive )
                  return dsPostMortem;
                if ( source )
                  this->Tag->RaiseEvent(ekFirstDamaged_anysource, this, blankCoords, 0, source);
              }
            }
          }
        }
        if ( this->Alive && (preTagHealth <= 0 || this->Health > 0) ) {
          unknown = 0;
          if ( !this->Health ) {
            if ( source )
              srcHouse = source->t.OwningPlayer;
            if ( House || source && House == srcHouse )
              this->RegisterDestruction();
            else
              this->Techno_E4();
            TransitionState = dsNowDead;
            this->Object_DC();
          }
          if ( this->Alive ) {
            if ( source ) {
              if ( this->Tag ) {
                if ( TransitionState != dsNowDead )
                  this->Tag->RaiseEvent(v30, ekAttackedByAnybody, this, blankCoords, 0, source);
              }
            }
            if ( this->Alive ) {
              if ( source ) {
                if ( this->Tag ) {
                  if ( TransitionState != dsNowDead )
                    this->Tag->RaiseEvent(v31, ekAttackedByHouse, this, blankCoords, 0, source);
                }
              }
              if ( this->Alive ) {
                if ( transitionState ) {
                  if ( this->Selected )
                    this->vt->SetLayer(LAYER_GROUND);
                }
              }
            }
          }
          return TransitionState;
        }
      }
    }
    return dsPostMortem;
  }
  int curHealth = this->Health;
  this->Health = curHealth - realDamage;
  if ( curHealth - realDamage > Strength )
    this->Health = Strength;
  if ( curHealth != this->Health )
    this->BlinkDisguise(7);
  return dsUnaffected;
}