예제 #1
0
void TableShape::handleDamages(const QList<Damage*>& damages)
{
    QList<Damage*>::ConstIterator end(damages.end());
    for (QList<Damage*>::ConstIterator it = damages.begin(); it != end; ++it) {
        Damage* damage = *it;
        if (!damage) continue;

        if (damage->type() == Damage::Cell) {
            CellDamage* cellDamage = static_cast<CellDamage*>(damage);
            const Region region = cellDamage->region();

            if (cellDamage->changes() & CellDamage::Appearance)
                d->sheetView->invalidateRegion(region);
            continue;
        }

        if (damage->type() == Damage::Sheet) {
            SheetDamage* sheetDamage = static_cast<SheetDamage*>(damage);

            if (sheetDamage->changes() & SheetDamage::PropertiesChanged)
                d->sheetView->invalidate();
            continue;
        }
    }

    update();
}
예제 #2
0
파일: Attributs.cpp 프로젝트: anliec/Mosp
void Attributs::looseLiveFromDamage(const Damage &damage)
{
    for(int i=0 ; i<damage.getMaxIndex() ; i++)
    {
        live -= damage.getValue(i).getValue();
    }
}
예제 #3
0
파일: Damage.cpp 프로젝트: younthu/wagic
/* Damage Stack resolve process:
 1 - apply damages to targets. For each of them, send an event to the GameObserver (for Damage triggers)
 2 - Once this is done, send a "Damage Stakc Resolved" event to the GameObserver
 3 - Once that message is received on the DamageStack's side, do the "afterDamage" effects (send to graveyard, etc...)
 Using events in 2 and 3 guarantees that the "send to graveyard" effect will only apply AFTER Damaged triggers are applied
 */
int DamageStack::resolve()
{
    for (int i = (int)(mObjects.size()) - 1; i >= 0; i--)
    {
        Damage * damage = (Damage*) mObjects[i];
        if (damage->state == NOT_RESOLVED)
            damage->resolve();
    }
    ((Interruptible*)this)->getObserver()->receiveEvent(NEW WEventDamageStackResolved());
    return 1;
}
예제 #4
0
void Attack::loadAttackData(GameObjectData* dataObj)
{
	for(GameObjectData* damageData : dataObj->getObjectList("damages"))
	{
		Damage dam;
		dam.load(damageData);
		_damages.push_back(dam);
	}

	if(dataObj->hasFloat("duration"))
		_duration = dataObj->getFloat("duration");
}
예제 #5
0
void View::Rotate (Graphic* g, Event& e) {
    Coord l, b, r, t;
    float cx, cy;
    
    damage->Incur(g);
    g->GetBox(l, b, r, t);
    g->GetCenter(cx, cy);
    RotatingRect rr(output, canvas, l, b, r, t, round(cx), round(cy), e.x,e.y);

    Track(e, rr);
    g->Rotate(rr.CurrentAngle(), cx, cy);
    g->Touch();
    damage->Incur(g);
    Update();
}
예제 #6
0
파일: Attributs.cpp 프로젝트: anliec/Mosp
void Attributs::applyAttackRelativeBonnus(Damage &damage) const
{
    for(unsigned i=0; i<damage.getValues().size() ; i++)
    {
        for(unsigned a=0 ; a<relativeFightBonus.size() ; a++)
        {
            if(damage.getValues().at(i).getType() == relativeFightBonus.at(a).getType() )
            {
                int newDamage = damage.getValues().at(i).getValue();
                newDamage += (newDamage * relativeFightBonus.at(a).getValue()) / 100; //one value point -> add 1% damage
                damage.getValues().at(i).setValue(newDamage);
            }
        }
    }
}
예제 #7
0
파일: Damage.cpp 프로젝트: younthu/wagic
void DamageStack::Render()
{
    float currenty = y;
    for (size_t i = 0; i < mObjects.size(); i++)
    {
        Damage * damage = (Damage*) mObjects[i];
        if (damage->state == NOT_RESOLVED)
        {
            damage->x = x;
            damage->y = currenty;
            currenty += damage->mHeight;
            damage->Render();
        }
    }
}
예제 #8
0
파일: viewer.cpp 프로젝트: PNCG/neuron
void ViewerGraphic::Update () {
    GraphicComp* parent = (GraphicComp*) _view->GetGraphicComp()->GetParent();

    if (parent != nil) {
        FullGraphic gs;
        totalGSGraphic(parent->GetGraphic(), gs);

        if (Different(this, &gs)) {
            Damage* damage = _view->GetViewer()->GetDamage();
            
            damage->Incur(this);
            *(Graphic*)this = *(Graphic*)(&gs);
            damage->Incur(this);
        }
    }
}
예제 #9
0
void Attack::Act(IGame& game) const
{
	State attacker = game.Get(actor);
	auto& targetActor = dynamic_cast<const Identity&>(target);
	State victim(game.Get(targetActor));
	if (!part)
	{
		Engage(attacker);
		game.Adjust(actor, attacker, skill.name);
		game.Adjust(targetActor, victim, L"Miss " + skill.name);
		return;
	}
	auto skillLevel = attacker.SkillLevel(skill, &victim);
	if (skillLevel.Value() == 0)
	{
		Engage(attacker);
		game.Adjust(actor, attacker, skill.name);
		game.Adjust(targetActor, victim, L"Resist " + skill.name + L":" + skillLevel.Description());
		return;
	}
	auto damage = attacker.AttackDamage(skill, skillLevel);
	Damage pain = damage - victim.Mitigation(*part);
	if (!victim.Hurt(*part, pain, actor.Description()+L"'"+skill.description))	
	{
		Engage(attacker);
		game.Adjust(actor, attacker, skill.name);
		game.Adjust(targetActor, victim, L"Mitigate " + skill.name + L"@" + part->Name() + L":" + pain.ActionDescription());
		return;
	}
	Engage(attacker);
	game.Adjust(actor, attacker, skill.name);
	game.Adjust(targetActor, victim, L"Hit " + skill.name + L"@" + part->Name() + L":" + pain.ActionDescription());
}
예제 #10
0
int Character::takeDamage(Damage dmg)
{
  //TODO: handle damage resists
  int roll = dmg.roll();
  modifyHitPoints(-1 * roll);
  return roll;
}
예제 #11
0
void View::Scale (Graphic* g, Event& e) {
    Coord l, b, r, t;
    float cx, cy, scale;
    
    damage->Incur(g);
    g->GetBox(l, b, r, t);
    g->GetCenter(cx, cy);
    ScalingRect sr(output, canvas, l, b, r, t, round(cx), round(cy));

    Track(e, sr);
    scale = sr.CurrentScaling();
    g->Scale(scale, scale, cx, cy);
    g->Touch();
    damage->Incur(g);
    Update();
}
예제 #12
0
void View::Move (Graphic* g, Event& e) {
    Coord l, b, r, t, newl, newb;
    float dx, dy, mag = GetMagnification();
    
    damage->Incur(g);
    g->GetBox(l, b, r, t);
    SlidingRect sr(output, canvas, l, b, r, t, e.x, e.y);

    Track(e, sr);
    sr.GetCurrent(newl, newb, r, t);
    dx = (newl - l) / mag;  // get distance moved, corrected to reflect
    dy = (newb - b) / mag;  // current magnification
    g->Translate(dx, dy);
    g->Touch();		    // so that new position will be written out
    damage->Incur(g);
    Update();
}
예제 #13
0
파일: Attributs.cpp 프로젝트: anliec/Mosp
void Attributs::applyAttackFixBonnus(Damage &damage) const
{
    for(unsigned i=0; i<damage.getValues().size() ; i++)
    {
        int newDamage = damage.getValues().at(i).getValue();
        newDamage += fixDamageBonnus;
        for(unsigned a=0 ; a<fixFightBonus.size() ; a++)
        {
            if(damage.getValues().at(i).getType() == fixFightBonus.at(a).getType() )
            {
                newDamage += fixFightBonus.at(a).getValue(); //add fix attack bonnus
                //exit for loop: (there are only one couple)
                a = values.size();
            }
        }
        damage.getValues().at(i).setValue(newDamage);
    }
}
예제 #14
0
파일: Attributs.cpp 프로젝트: anliec/Mosp
void Attributs::applyDefenseRelativeResistances(Damage &damage) const
{
    for(unsigned i=0; i<damage.getValues().size() ; i++)
    {
        for(unsigned a=0 ; a<relativeResistances.size() ; a++)
        {
            if(damage.getValues().at(i).getType() == relativeResistances.at(a).getType() )
            {
                int newDamage = damage.getValues().at(i).getValue();
                newDamage -= (newDamage * relativeResistances.at(a).getValue()) / 100; //one value point -> add 1% resistances
                if(newDamage<0)
                {
                    newDamage = 0;
                }
                damage.getValues().at(i).setValue(newDamage);
            }
        }
    }
}
예제 #15
0
파일: Attributs.cpp 프로젝트: anliec/Mosp
void Attributs::applyDefenseFixResistances(Damage &damage) const
{
    for(unsigned i=0; i<damage.getValues().size() ; i++)
    {
        for(unsigned a=0 ; a<fixResistances.size() ; a++)
        {
            if(damage.getValues().at(i).getType() == fixResistances.at(a).getType() )
            {
                int newDamage = damage.getValues().at(i).getValue();
                newDamage -= fixResistances.at(a).getValue(); //add fix attack bonnus
                if(newDamage<0)
                {
                    newDamage = 0;
                }
                damage.getValues().at(i).setValue(newDamage);
            }
        }
    }
}
예제 #16
0
파일: Attributs.cpp 프로젝트: anliec/Mosp
void Attributs::applyAttackValues(Damage &damage) const
{
    for(unsigned i=0; i<damage.getValues().size() ; i++)
    {
        int newDamage = damage.getValues().at(i).getValue();
        int damageBonnus = powerBonnus;
        for(unsigned a=0 ; a<values.size() ; a++)
        {
            if(damage.getValues().at(i).getType() == values.at(a).getType() )
            {
                damageBonnus += values.at(a).getValue(); //one value point -> add 1% damage
                //exit for loop: (there are only one couple)
                a = values.size();
            }
        }
        newDamage += newDamage*damageBonnus/100;
        damage.getValues().at(i).setValue(newDamage);
    }
}
예제 #17
0
bool Creature::doReflectionDamage(Damage damage, Creature* target, ReflectedDamageType printZero) {
    int dmg = damage.getReflected() ? damage.getReflected() : damage.getPhysicalReflected();

    // don't quit if we want to print 0
    if(!dmg && printZero == REFLECTED_NONE)
        return(false);

    if(damage.getReflected() || printZero == REFLECTED_MAGIC) {
        target->printColor("Your shield of magic reflects %s%d^x damage.\n", target->customColorize("*CC:DAMAGE*").c_str(), dmg);
        printColor("%M's shield of magic flares up and hits you for %s%d^x damage.\n", target, customColorize("*CC:DAMAGE*").c_str(), dmg);
        broadcastGroup(false, this, "%M's shield of magic flares up and hits %N for *CC:DAMAGE*%d^x damage.\n",
            target, this, dmg);
    } else {
        switch(damage.getPhysicalReflectedType()) {
        case REFLECTED_FIRE_SHIELD:
        default:
            target->printColor("Your shield of fire reflects %s%d^x damage.\n", target->customColorize("*CC:DAMAGE*").c_str(), dmg);
            printColor("%M's shield of fire flares up and hits you for %s%d^x damage.\n", target, customColorize("*CC:DAMAGE*").c_str(), dmg);
            broadcastGroup(false, this, "%M's shield of fire flares up and hits %N for *CC:DAMAGE*%d^x damage.\n",
                target, this, dmg);
            break;
        }
    }

    if(damage.getDoubleReflected()) {
        Damage reflectedDamage;
        reflectedDamage.setReflected(damage.getDoubleReflected());
        target->doReflectionDamage(reflectedDamage, this);
    }

    // we may have gotten this far for printing reasons (even on zero), but really, go no further
    if(!dmg)
        return(false);

    if(target->isPlayer() && isMonster())
        getAsMonster()->adjustThreat(target, dmg);

    hp.decrease(dmg);
    if(hp.getCur() <= 0)
        return(true);
    return(false);
}
예제 #18
0
void SheetAccessModel::handleDamages(const QList<Damage*>& damages)
{
    QList<Damage*>::ConstIterator end(damages.end());
    for (QList<Damage*>::ConstIterator it = damages.begin(); it != end; ++it) {
        Damage* damage = *it;
        if (!damage) {
            continue;
        }

        if (damage->type() == Damage::Sheet) {
            SheetDamage* sheetDamage = static_cast<SheetDamage*>(damage);
            kDebug(36007) << "Processing\t" << *sheetDamage;

            if (sheetDamage->changes() & SheetDamage::Name) {
                Sheet *sheet = sheetDamage->sheet();
                // We should never receive signals from sheets that are not in our model
                Q_ASSERT(d->cols.contains(sheet));
                const int sheetIndex = d->cols[sheet];
                setHeaderData(sheetIndex, Qt::Horizontal, sheet->sheetName());
            }
            continue;
        }
    }
}
예제 #19
0
void CanvasItem::handleDamages(const QList<Damage*>& damages)
{
    QRegion paintRegion;
    enum { Nothing, Everything, Clipped } paintMode = Nothing;

    QList<Damage*>::ConstIterator end(damages.end());
    for (QList<Damage*>::ConstIterator it = damages.begin(); it != end; ++it) {
        Damage* damage = *it;
        if (!damage) continue;

        if (damage->type() == Damage::Cell) {
            CellDamage* cellDamage = static_cast<CellDamage*>(damage);
            kDebug(36007) << "Processing\t" << *cellDamage;
            Sheet* const damagedSheet = cellDamage->sheet();

            if (cellDamage->changes() & CellDamage::Appearance) {
                const Region& region = cellDamage->region();
                sheetView(damagedSheet)->invalidateRegion(region);
                paintMode = Everything;
            }
            continue;
        }

        if (damage->type() == Damage::Sheet) {
            SheetDamage* sheetDamage = static_cast<SheetDamage*>(damage);
            kDebug(36007) << *sheetDamage;
            const SheetDamage::Changes changes = sheetDamage->changes();
            if (changes & (SheetDamage::Name | SheetDamage::Shown)) {
//                d->tabBar->setTabs(doc()->map()->visibleSheets());
                paintMode = Everything;
            }
            if (changes & (SheetDamage::Shown | SheetDamage::Hidden)) {
//                updateShowSheetMenu();
                paintMode = Everything;
            }
            // The following changes only affect the active sheet.
            if (sheetDamage->sheet() != d->activeSheet) {
                continue;
            }
            if (changes.testFlag(SheetDamage::ContentChanged)) {
                update();
                paintMode = Everything;
            }
            if (changes.testFlag(SheetDamage::PropertiesChanged)) {
                sheetView(d->activeSheet)->invalidate();
                paintMode = Everything;
            }
            if (sheetDamage->changes() & SheetDamage::ColumnsChanged)
                columnHeader()->update();
            if (sheetDamage->changes() & SheetDamage::RowsChanged)
                rowHeader()->update();
            continue;
        }

        if (damage->type() == Damage::Selection) {
            SelectionDamage* selectionDamage = static_cast<SelectionDamage*>(damage);
            kDebug(36007) << "Processing\t" << *selectionDamage;
            const Region region = selectionDamage->region();

            if (paintMode == Clipped) {
                const QRectF rect = cellCoordinatesToView(region.boundingRect());
                paintRegion += rect.toRect().adjusted(-3, -3, 4, 4);
            } else {
                paintMode = Everything;
            }
            continue;
        }

        kDebug(36007) << "Unhandled\t" << *damage;
    }

    // At last repaint the dirty cells.
    if (paintMode == Clipped) {
        update(paintRegion.boundingRect());
    } else if (paintMode == Everything) {
        update();
    }
}
예제 #20
0
/**
* @param damage damage description for this weapon detonation
* Point defense and air cannons should use a different model
*/
void tcDamageModel::CalculateTotalDamage(tcWeaponObject* weapon, tcGameObject* target, Damage& damage)
{
    if ((weapon == 0) || (target == 0))
    {
        wxASSERT(false);
        return;
    }

    bool goodDetonation = weapon->IsGoodDetonation();

    damage.Clear();


    const tcWeaponDamage* weaponDamage = GetWeaponDamageModel(weapon);


    /* if missile is targeted and has scored direct hit, then apply
    ** kinetic damage from missile (big fragment) and apply
    ** internal damage assuming missile has delayed warhead that explodes
    ** after penetrating target exterior
    */
    if (weapon->IsDirectHit() && (weapon->GetIntendedTarget() == target->mnID))
    {
        float speed_collide = weapon->mcKin.CalculateRangeRate(target->mcKin);
        if (speed_collide < 0)
        {
            wxASSERT(false);
            speed_collide = 0; // opening range rate case, shouldnt happen
        }

        float kinEnergy_J = 0.5*weapon->GetMassKg()*speed_collide*speed_collide;

        // fractional damage from kinetic energy of impact
        damage.kinetic_J = kinEnergy_J;

        damage.isPenetration = weaponDamage->isPenetration;

        // treat blast and frag as the same for now
        damage.explosive_kg = weaponDamage->blastCharge_kg + weaponDamage->fragCharge_kg + weaponDamage->fragMetal_kg; 
        return;
    }

    // no damage for direct hit weapons to other targets, or if weapon is a dud
    if (weapon->IsDirectHit() || (!goodDetonation)) return;

	tcBallisticWeapon* ballistic = dynamic_cast<tcBallisticWeapon*>(weapon);
	if ((ballistic != 0) && ballistic->IsClusterBomb())
	{
		CalculateTotalDamageCluster(ballistic, target, damage);
		return;
	}


    // determine if this is an underwater or underground explosion
    bool underwaterExplosion = ((weapon->mcKin.mfAlt_m <= -1.0f) && (weapon->mcTerrain.mfHeight_m < -1.0f));
    bool targetUnderwater = (target->mcKin.mfAlt_m <= 0) && (target->mcTerrain.mfHeight_m < -1.0f);
    bool targetAbovewater = (target->mcKin.mfAlt_m >= -3.0f); // target can be both under and above water
    
    bool affectsTarget = (underwaterExplosion && targetUnderwater) || (!underwaterExplosion && targetAbovewater);
    if (!affectsTarget) return;


    float range_m = 1000.0f * weapon->mcKin.RangeToKmAlt(target->mcKin);

    //float cumulativeDamage = 0;

    if (underwaterExplosion)
    {
        float damageRange_m = range_m;
        Vec3 collisionPoint;
        float collisionRange_m;

        if (damageRange_m < 250.0f) // dont check collisions for distance platforms affected by blast
        {
            // check collision along ray to origin
            if (target->CalculateCollisionPointOrigin(weapon, collisionPoint, collisionRange_m))
            {
                // wxASSERT(collisionRange_m < damageRange_m);
                damageRange_m = std::min(damageRange_m, collisionRange_m);
            }

            // check collision along "up" ray
            if (target->CalculateCollisionPointDir(weapon, Vec3(0, 1, 0), collisionPoint, collisionRange_m))
            {
                damageRange_m = std::min(damageRange_m, collisionRange_m);
            }
        }

        damageRange_m = std::max(damageRange_m, 10.0f); // don't allow anything closer than 10 m

        damage.waterBlast_psi = CalculateWaterBlastOverpressure(damageRange_m, weaponDamage->blastCharge_kg);
#ifdef _DEBUG
        fprintf(stdout, "Underwater explosion, %s, range: %.1f m, blast: %.1f PSI\n", target->mzClass.c_str(), damageRange_m, damage.waterBlast_psi);
#endif
        return; // no thermal or frag damage underwater
    }

    float minRange_m = std::min(0.05f * target->GetSpan(), 50.0f);
    minRange_m = std::max(minRange_m, 5.0f);

    range_m = std::max(range_m, minRange_m);

    damage.blast_psi = CalculateBlastOverpressure(range_m, weaponDamage->blastCharge_kg);

    damage.thermal_J_cm2 = CalculateRadiationIntensity(range_m, weaponDamage->radCharge_kg);

    if (weaponDamage->fragCharge_kg > 0)
    {
        FragWeapon fragWeap;
        fragWeap.charge_kg = weaponDamage->fragCharge_kg;
        fragWeap.metal_kg = weaponDamage->fragMetal_kg;
        fragWeap.fragment_kg = weaponDamage->fragFragment_kg;
        fragWeap.spread_factor = weaponDamage->fragSpread;

        float targetRadius_m = 0.5*target->GetSpan();
        float targetArea_m2 = 0.5 * C_PI * targetRadius_m * targetRadius_m; // approx for now, 0.5 for rect shape
        float fragRange_m = std::max(range_m, targetRadius_m);

        tcDamageModel::FragHits fragHits = 
            CalculateFragmentImpact(fragRange_m, target->mcKin.mfAlt_m, fragWeap, targetArea_m2);

        damage.fragHits = fragHits.hits;
        damage.fragEnergy_J = fragHits.ke_J;
    }

    return;
}
예제 #21
0
파일: player.cpp 프로젝트: hoij/PrettyDD
Damage Player::getTotalDamageReceived() const {
    Damage total = affectedPlayers->getTotalDamageDealtOnPlayer(getName());
    int dpm = amountPerMinute(total.getTotal());
    total.setDPM(dpm);
    return total;
}
예제 #22
0
void View::Draw () {
    damage->Reset();
    GraphicBlock::Draw();
}
예제 #23
0
void View::Update () {
    UpdatePerspective();
    damage->Repair();
}
예제 #24
0
// This is a NPC implementation of damage system (incomplete)
bool NPC::ApplyDamage(Damage &d) {
	_log(ITEM__TRACE, "%u: Applying %.1f total damage from %u", GetID(), d.GetTotal(), d.source->GetID());
 	
	double total_damage = 0;
	bool killed = false;
	int random_damage = 0;
	double random_damage_mult = 1.0;
	
	//apply resistances...
	//damageResistance?
	
	//Shield:
	double available_shield = m_shieldCharge;
	Damage shield_damage = d.MultiplyDup(
		m_self->GetAttribute(AttrShieldKineticDamageResonance).get_float(),
		m_self->GetAttribute(AttrShieldThermalDamageResonance).get_float(),
		m_self->GetAttribute(AttrShieldEmDamageResonance).get_float(),
		m_self->GetAttribute(AttrShieldExplosiveDamageResonance).get_float()
	);
	//other:
	//emDamageResistanceBonus
	//explosiveDamageResistanceBonus
	//kineticDamageResistanceBonus
	//thermalDamageResistanceBonus
	// 



	//TODO: deal with seepage from shield into armor.
 	//shieldUniformity
	//uniformity (chance of seeping through to armor)
 
	/*
	 * Here we calculates the uniformity thing.
	 * I think this must be calculated based on
	 * the type of damage -> resistance basis.
	*
	double shield_uniformity = available_shield / m_self->shieldCapacity();
	if( shield_uniformity < ( 1.0  - m_self->shieldUniformity() ) )
	{
		/*
		 * As far i can see mostly npc/entities have a 
		 * chance of transpassing when the shield is below 25%
		/
	}
	*/

	// Make a random value to use in msg's and attack multiplier
	random_damage = static_cast<int32>(MakeRandomInt(0, 5));
	random_damage_mult = (double)(random_damage / 10.0);

	// Not sure about this, but with this we get some random hits... :)
	//total_shield_damage += total_shield_damage * random_damage_mult;
	shield_damage.SumWithMultFactor( random_damage_mult );
	double total_shield_damage = shield_damage.GetTotal();

	if(total_shield_damage <= available_shield)
	{
		//we can take all this damage with our shield...
		double new_charge = m_shieldCharge - total_shield_damage;

		m_shieldCharge = new_charge;
		total_damage += total_shield_damage;
		_log(ITEM__TRACE, "%s(%u): Applying entire %.1f damage to shields. New charge: %.1f", GetName(), GetID(), total_shield_damage, new_charge);
	}
	else
	{
		//first determine how much we can actually apply to 
		//the shield, the rest goes further down.
		double consumed_shield_ratio = available_shield / shield_damage.GetTotal();
		d *= 1.0 - consumed_shield_ratio;
		if(available_shield > 0) {
			total_damage += available_shield;
			
			_log(ITEM__TRACE, "%s(%us): Shield depleated with %.1f damage. %.1f damage remains.", GetName(), GetID(), available_shield, d.GetTotal());
			
			//set shield to 0, it is fully depleated.
			m_shieldCharge = 0;
		}
		
		//Armor:
		double available_armor = m_self->GetAttribute(AttrArmorHP).get_float() - m_armorDamage;
		Damage armor_damage = d.MultiplyDup(
			m_self->GetAttribute(AttrArmorKineticDamageResonance).get_float(),
			m_self->GetAttribute(AttrArmorThermalDamageResonance).get_float(),
			m_self->GetAttribute(AttrArmorEmDamageResonance).get_float(),
			m_self->GetAttribute(AttrArmorExplosiveDamageResonance).get_float()
		);
		//other:
		//activeEmResistanceBonus
		//activeExplosiveResistanceBonus
		//activeThermicResistanceBonus
		//activeKineticResistanceBonus
		//passiveEmDamageResistanceBonus
		//passiveExplosiveDamageResistanceBonus
		//passiveKineticDamageResistanceBonus
		//passiveThermicDamageResistanceBonus

		//TODO: figure out how much passes through to structure/modules.
		//armorUniformity
		
		// Not sure about this, but with this we get some random hits... :)
		//total_armor_damage += total_armor_damage * random_damage_mult;
		armor_damage.SumWithMultFactor( random_damage_mult );
		double total_armor_damage = armor_damage.GetTotal();
		
		if(total_armor_damage <= available_armor)
		{
			//we can take all this damage with our armor...
			double new_damage = m_armorDamage + total_armor_damage;
			m_armorDamage = new_damage;
			
			total_damage += total_armor_damage;
			_log(ITEM__TRACE, "%s(%u): Applying entire %.1f damage to armor. New armor damage: %.1f", GetName(), GetID(), total_armor_damage, new_damage);
		}
		else
		{
			//first determine how much we can actually apply to 
			//the armor, the rest goes further down.
			double consumed_armor_ratio = available_armor / armor_damage.GetTotal();
			d *= 1.0 - consumed_armor_ratio;

			if(available_armor > 0)
			{
				total_damage += available_armor;
				
				_log(ITEM__TRACE, "%s(%u): Armor depleated with %.1f damage. %.1f damage remains.", GetName(), GetID(), available_armor, d.GetTotal());
				
				//all armor has been penetrated.
				m_armorDamage = m_self->GetAttribute(AttrArmorHP).get_float();
			}
			
			
			//Hull/Structure:
			
			//The base hp and damage attributes represent structure.
			double available_hull = m_self->GetAttribute(AttrHp).get_float() - m_hullDamage;
			Damage hull_damage = d.MultiplyDup(
				m_self->GetAttribute(AttrHullKineticDamageResonance).get_float(),
				m_self->GetAttribute(AttrHullThermalDamageResonance).get_float(),
				m_self->GetAttribute(AttrHullEmDamageResonance).get_float(),
				m_self->GetAttribute(AttrHullExplosiveDamageResonance).get_float()
			);
			//other:
			//passiveEmDamageResonanceMultiplier
			//passiveThermalDamageResonanceMultiplier
			//passiveKineticDamageResonanceMultiplier
			//passiveExplosiveDamageResonanceMultiplier
			//activeEmDamageResonance
			//activeThermalDamageResonance
			//activeKineticDamageResonance
			//activeExplosiveDamageResonance
			//structureUniformity

			// Not sure about this, but with this we get some random hits... :)
			//total_hull_damage += total_hull_damage * random_damage_mult;
			hull_damage.SumWithMultFactor( random_damage_mult );
			double total_hull_damage = hull_damage.GetTotal();
			total_damage += total_hull_damage;

			if(total_hull_damage < available_hull)
			{

				//we can take all this damage with our hull...
				double new_damage = m_hullDamage + total_hull_damage;
				m_hullDamage = new_damage;
				_log(ITEM__TRACE, "%s(%u): Applying entire %.1f damage to structure. New structure damage: %.1f", GetName(), GetID(), total_hull_damage, new_damage);
			}
			else
			{
				//dead....
				_log(ITEM__TRACE, "%s(%u): %.1f damage has depleated our structure. Time to explode.", GetName(), GetID(), total_hull_damage);
				killed = true;
				//m_hullDamage = m_self->hp();
                m_hullDamage = m_self->GetAttribute(AttrHp).get_float();
			}
			
			//TODO: deal with damaging modules. no idea the mechanics on this.
		}
	}
	
	//if( total_damage <= 0.0 )
	//	return(killed);
	
	PyTuple *up;

	//Notifications to ourself:
	Notify_OnEffectHit noeh;
	noeh.itemID = d.source->GetID();
	noeh.effectID = d.effect;
	noeh.targetID = GetID();
	noeh.damage = total_damage;

	up = noeh.Encode();
	QueueDestinyEvent(&up);
	PySafeDecRef( up );

	//NOTE: could send out the RD version of this message instead of the R version, which
	//includes "weapon" and "owner" instead of "source".
	Notify_OnDamageMessage_Self ondam;
	//ondam.messageID = "AttackHit2R";	//TODO: randomize/select this somehow.
	ondam.messageID = DamageMessageIDs_Self[random_damage];
	ondam.damage = total_damage;
	ondam.source = d.source->GetID();
	ondam.splash = "";
	up = ondam.Encode();
	QueueDestinyEvent(&up);
	PySafeDecRef( up );

	//Notifications to others:
	//I am not sure what the correct scope of this broadcast
	//should be. For now, it goes to anybody targeting us.
	if(targets.IsTargetedBySomething()) {
		up = noeh.Encode();
		targets.QueueTBDestinyEvent(&up);
		PySafeDecRef( up );

		Notify_OnDamageMessage_Other ondamo;
		//ondamo.messageID = "AttackHit3";		//TODO: select this based on the severity of the hit...
		ondamo.messageID = DamageMessageIDs_Other[random_damage];
		ondamo.format_type = fmtMapping_itemTypeName;
		ondamo.weaponType = d.weapon->typeID();
		ondamo.damage = total_damage;
		ondamo.target = GetID();
		ondamo.splash = "";

		up = ondamo.Encode();
		targets.QueueTBDestinyEvent(&up);
		PySafeDecRef( up );
	}
	
	if(killed == true)
	{
		Killed(d);
	}
	else
	{
		_SendDamageStateChanged();
	}

	return(killed);

}
예제 #25
0
int splDispelAlign(Creature* player, cmd* cmnd, SpellData* spellData, const char* spell, int align) {
    Creature* target=0;
    Damage damage;


    if((target = player->findMagicVictim(cmnd->str[2], cmnd->val[2], spellData, true, false, "Cast on what?\n", "You don't see that here.\n")) == nullptr)
        return(0);

    if(player == target) {
        // mobs can't cast on themselves!
        if(!player->getAsPlayer())
            return(0);

        // turn into a boolean!
        // are they in alignment?
        if(align == PINKISH)
            align = player->getAlignment() <= align;
        else
            align = player->getAlignment() >= align;

        if(spellData->how == CastType::CAST || spellData->how == CastType::SCROLL || spellData->how == CastType::WAND)
            player->print("You cannot cast that spell on yourself.\n");
        else if(spellData->how == CastType::POTION && !align)
            player->print("Nothing happens.\n");
        else if(spellData->how == CastType::POTION && align) {
            player->smashInvis();

            damage.set(mrand(spellData->level * 2, spellData->level * 4));
            damage.add(MAX(0, bonus((int) player->piety.getCur())));
            player->modifyDamage(player, MAGICAL, damage);

            player->print("You feel as if your soul is savagely ripped apart!\n");
            player->printColor("You take %s%d^x points of damage!\n", player->customColorize("*CC:DAMAGE*").c_str(), damage.get());
            broadcast(player->getSock(), player->getParent(), "%M screams and doubles over in pain!", player);
            player->hp.decrease(damage.get());
            if(player->hp.getCur() < 1) {
                player->print("Your body explodes. You're dead!\n");
                broadcast(player->getSock(), player->getParent(), "%M's body explodes! %s's dead!", player,
                        player->upHeShe());
                player->getAsPlayer()->die(EXPLODED);
            }
        }

    } else {
        if(player->spellFail( spellData->how))
            return(0);

        cmnd->str[2][0] = up(cmnd->str[2][0]);
        target = player->getParent()->findCreature(player, cmnd->str[2], cmnd->val[2], false);

        if(!target) {
            player->print("That's not here.\n");
            return(0);
        }

        if(!player->canAttack(target))
            return(0);

        if( (target->getLevel() > spellData->level + 7) ||
            (!player->isStaff() && target->isStaff())
        ) {
            player->print("Your magic would be too weak to harm %N.\n", target);
            return(0);
        }

        player->smashInvis();
        // turn into a boolean!
        // are they in alignment?
        if(align == PINKISH)
            align = target->getAlignment() <= align;
        else
            align = target->getAlignment() >= align;



        if(spellData->how == CastType::CAST || spellData->how == CastType::SCROLL || spellData->how == CastType::WAND) {
            player->print("You cast %s on %N.\n", spell, target);
            broadcast(player->getSock(), target->getSock(), player->getParent(), "%M casts a %s spell on %N.", player, spell, target);

            if(target->getAsPlayer()) {
                target->wake("Terrible nightmares disturb your sleep!");
                target->print("%M casts a %s spell on you.\n", player, spell);
            }

            if(!align) {
                player->print("Nothing happens.\n");
            } else {
                damage.set(mrand(spellData->level * 2, spellData->level * 4));
                damage.add(abs(player->getAlignment()/100));
                damage.add(MAX(0, bonus((int) player->piety.getCur())));
                target->modifyDamage(player, MAGICAL, damage);

                if(target->chkSave(SPL, player,0))
                    damage.set(damage.get() / 2);

                player->printColor("The spell did %s%d^x damage.\n", player->customColorize("*CC:DAMAGE*").c_str(), damage.get());
                player->print("%M screams in agony as %s soul is ripped apart!\n",
                    target, target->hisHer());
                target->printColor("You take %s%d^x points of damage as your soul is ripped apart!\n", target->customColorize("*CC:DAMAGE*").c_str(), damage.get());
                broadcastGroup(false, target, "%M cast a %s spell on ^M%N^x for *CC:DAMAGE*%d^x damage, %s%s\n",
                    player, spell, target, damage.get(), target->heShe(), target->getStatusStr(damage.get()));

                broadcast(player->getSock(), target->getSock(), player->getParent(), "%M screams and doubles over in pain!", target);

                // if the target is reflecting magic, force printing a message (it will say 0 damage)
                player->doReflectionDamage(damage, target, target->isEffected("reflect-magic") ? REFLECTED_MAGIC : REFLECTED_NONE);

                if(spellData->how == CastType::CAST && player->isPlayer())
                    player->getAsPlayer()->statistics.offensiveCast();

                player->doDamage(target, damage.get(), NO_CHECK);
                if(target->hp.getCur() < 1) {
                    target->print("Your body explodes! You die!\n");
                    broadcast(player->getSock(), target->getSock(), player->getParent(),
                        "%M's body explodes! %s's dead!", target, target->upHeShe());
                    player->print("%M's body explodes! %s's dead!\n", target, target->upHeShe());
                    target->die(player);
                    return(2);
                }
            }

        }
    }

    return(1);
}
예제 #26
0
	void CSubStructure::hit(const b2Transform& trafo, Damage damage, vector2d position, vector2d direction)
	{
		// check that position is not inside the ship, otherwise move!


		// first, raytrace against armour to find hit segment
		b2RayCastInput rcin{position, position + direction, 1000};
		b2RayCastOutput rcout;
		ArmourSegment* armour_hit{};
		for(auto& seg : mArmour)
		{
			b2EdgeShape temp;
			temp.Set(seg.p1, seg.p2);
			if(temp.RayCast(&rcout, rcin, trafo, 0))
			{
				rcin.maxFraction = rcout.fraction;
				armour_hit = seg.armour.get();
			}
		}

		// if there was an armour segment that was hit.
		if(armour_hit)
		{
			damage = armour_hit->hit(damage);
		}

		// now, for the internal segments
		struct HitCell
		{
			float frac;
			IStructureCell* cell;
		};
		rcin.maxFraction = 10000;
		std::vector<HitCell> hit_cells;
		for(auto& cell : mCells)
		{
			if(physics::raycast(rcout, cell->shape(), rcin, trafo))
			{
				rcin.maxFraction = rcout.fraction;
				hit_cells.push_back(HitCell{rcout.fraction, cell.get()});
			}
		}

		// sort hits
		std::sort( hit_cells.begin(), hit_cells.end(), [](HitCell a, HitCell b) { return a.frac < b.frac; } );

		// now go through all cells and hit the components
		/// \todo make damage processing more interesting here!
		float internal_damage = 0.5 * damage.getTotalDamage();
		mStructurePoints -= internal_damage;
		for(auto& hc : hit_cells)
		{
			IStructureCell* cell = hc.cell;
			std::size_t comp_count = cell->component_count();
			float cmp_dmg = internal_damage / comp_count;
			for(auto& c : cell->components())
			{
				internal_damage -= c.damage(cmp_dmg);
			}
		}

		/// \todo hit event listener, including ship destruction
	}