Exemplo n.º 1
0
BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
                               bool checkDefense /* = false */, bool checkArmor /* = false */, bool /* field  = false */)
{
	BlockType_t blockType = BLOCK_NONE;

	if (isImmune(combatType)) {
		damage = 0;
		blockType = BLOCK_IMMUNITY;
	} else if (checkDefense || checkArmor) {
		bool hasDefense = false;

		if (blockCount > 0) {
			--blockCount;
			hasDefense = true;
		}

		if (checkDefense && hasDefense) {
			int32_t defense = getDefense();
			damage -= uniform_random(defense / 2, defense);
			if (damage <= 0) {
				damage = 0;
				blockType = BLOCK_DEFENSE;
				checkArmor = false;
			}
		}

		if (checkArmor) {
			int32_t armorValue = getArmor();
			if (armorValue > 1) {
				double armorFormula = armorValue * 0.475;
				int32_t armorReduction = static_cast<int32_t>(std::ceil(armorFormula));
				damage -= uniform_random(
					armorReduction,
					armorReduction + static_cast<int32_t>(std::floor(armorFormula))
				);
			} else if (armorValue == 1) {
				--damage;
			}

			if (damage <= 0) {
				damage = 0;
				blockType = BLOCK_ARMOR;
			}
		}

		if (hasDefense && blockType != BLOCK_NONE) {
			onBlockHit();
		}
	}

	if (attacker) {
		attacker->onAttackedCreature(this);
		attacker->onAttackedCreatureBlockHit(blockType);
	}

	onAttacked();
	return blockType;
}
Exemplo n.º 2
0
void Creature::drainMana(Creature* attacker, int32_t manaLoss)
{
	onAttacked();
	changeMana(-manaLoss);

	if (attacker) {
		addDamagePoints(attacker, manaLoss);
	}
}
Exemplo n.º 3
0
void Creature::drainMana(const CombatSource& combatSource, int32_t points, bool showtext)
{
	onAttacked();
	changeMana(-points);

	if(combatSource.isSourceCreature()){
		combatSource.getSourceCreature()->onAttackedCreatureDrainMana(this, points);
	}
}
Exemplo n.º 4
0
void Creature::drainMana(Creature* attacker, CombatType_t combatType, int32_t damage)
{
	lastDamageSource = combatType;
	onAttacked();

	changeMana(-damage);
	if(attacker)
		attacker->onTargetDrainMana(this, damage);
}
Exemplo n.º 5
0
void Creature::drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage)
{
	lastDamageSource = combatType;
	onAttacked();

	changeHealth(-damage);
	if(attacker)
		attacker->onAttackedCreatureDrainHealth(this, damage);
}
Exemplo n.º 6
0
void Creature::onAttacking(uint32_t interval)
{
	if(!attackedCreature)
		return;

	onAttacked();
	attackedCreature->onAttacked();
	if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true))
		doAttacking(interval);
}
Exemplo n.º 7
0
BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
                               bool checkDefense /* = false */, bool checkArmor /* = false */, bool /* field  = false */)
{
	BlockType_t blockType = BLOCK_NONE;

	if (isImmune(combatType)) {
		damage = 0;
		blockType = BLOCK_IMMUNITY;
	} else if (checkDefense || checkArmor) {
		bool hasDefense = false;

		if (blockCount > 0) {
			--blockCount;
			hasDefense = true;
		}

		if (checkDefense && hasDefense && canUseDefense) {
			int32_t defense = getDefense();
			damage -= uniform_random(defense / 2, defense);
			if (damage <= 0) {
				damage = 0;
				blockType = BLOCK_DEFENSE;
				checkArmor = false;
			}
		}

		if (checkArmor) {
			int32_t armor = getArmor();
			if (armor > 3) {
				damage -= uniform_random(armor / 2, armor - (armor % 2 + 1));
			} else if (armor > 0) {
				--damage;
			}

			if (damage <= 0) {
				damage = 0;
				blockType = BLOCK_ARMOR;
			}
		}

		if (hasDefense && blockType != BLOCK_NONE) {
			onBlockHit();
		}
	}

	if (attacker) {
		attacker->onAttackedCreature(this);
		attacker->onAttackedCreatureBlockHit(blockType);
	}

	onAttacked();
	return blockType;
}
Exemplo n.º 8
0
void Creature::onAttacking(uint32_t interval)
{
	if(attackedCreature){

		onAttacked();
		attackedCreature->onAttacked();

		if(g_game.onCreatureAttack(this, attackedCreature)){
			//handled by script
			return;
		}

		if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true)){
			doAttacking(interval);
		}
	}
}
Exemplo n.º 9
0
void SGSHero::handleMessage(SGMessage* message)
{
  unsigned int what = message->what();
  switch (what)
  {
  case kWhatAttack:
    onAttack(message);
    break;
  case kWhatAttacked:
    onAttacked(message);
    break;
  case kWhatMove:
    onMoveTo(message);
    break;
  case kWhatDelay:
    onDelay(message);
    break;
  default:
    break;
  }
}
Exemplo n.º 10
0
void Creature::onAttacking(uint32_t interval)
{
	if(!attackedCreature || attackedCreature->getHealth() < 1 || interval < 100)
		return;

	bool deny = false;
	CreatureEventList attackEvents = getCreatureEvents(CREATURE_EVENT_ATTACK);
	for(CreatureEventList::iterator it = attackEvents.begin(); it != attackEvents.end(); ++it)
	{
		if(!(*it)->executeAction(this, attackedCreature) && !deny)
			deny = true;
	}

	if(deny)
		setAttackedCreature(NULL);

	if(!attackedCreature)
		return;

	onAttacked();
	attackedCreature->onAttacked();
	if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true))
		doAttacking(interval);
}
Exemplo n.º 11
0
BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
                               bool checkDefense /* = false */, bool checkArmor /* = false */)
{
	BlockType_t blockType = BLOCK_NONE;

	if (isImmune(combatType)) {
		damage = 0;
		blockType = BLOCK_IMMUNITY;
	} else if (checkDefense || checkArmor) {
		bool hasDefense = false;

		if (blockCount > 0) {
			--blockCount;
			hasDefense = true;
		}

		if (checkDefense && hasDefense) {
			int32_t maxDefense = getDefense();
			int32_t minDefense = maxDefense / 2;
			damage -= random_range(minDefense, maxDefense);

			if (damage <= 0) {
				damage = 0;
				blockType = BLOCK_DEFENSE;
				checkArmor = false;
			}
		}

		if (checkArmor) {
			int32_t armorValue = getArmor();
			int32_t minArmorReduction = 0;
			int32_t maxArmorReduction = 0;

			if (armorValue > 1) {
				minArmorReduction = (int32_t)std::ceil(armorValue * 0.475);
				maxArmorReduction = (int32_t)std::ceil(((armorValue * 0.475) - 1) + minArmorReduction);
			} else if (armorValue == 1) {
				minArmorReduction = 1;
				maxArmorReduction = 1;
			}

			damage -= random_range(minArmorReduction, maxArmorReduction);

			if (damage <= 0) {
				damage = 0;
				blockType = BLOCK_ARMOR;
			}
		}

		if (hasDefense && blockType != BLOCK_NONE) {
			onBlockHit(blockType);
		}
	}

	if (attacker) {
		attacker->onAttackedCreature(this);
		attacker->onAttackedCreatureBlockHit(this, blockType);
	}

	onAttacked();
	return blockType;
}
Exemplo n.º 12
0
void Creature::drainMana(Creature* attacker, int32_t manaLoss)
{
	onAttacked();
	changeMana(-manaLoss);
}
Exemplo n.º 13
0
void NounShip::inflictDamage( dword nWhen, Noun * pFrom, int damage, dword type, const Vector3 & direction )
{
	if ( isDestroyed() )		// don't bother if ship is already destroyed!
		return;

	// only increase timer if an enemy is attacking us - we don't want to promote griefing
	if ( isEnemy( pFrom ) )
		setOutOfCombat(); // update combat timer

	// if we are not the server, then halve the damage applied to avoid over estimatation the damage we are
	// inflicting on another ship.. 
	if (! isServer() )
		damage = damage * CLIENT_SIDE_DAMAGE;

	Facing eFacing = getFacing( atan2( direction.x, direction.z ), false );

	// apply any damage modifiers
	damage = damage * calculateModifier( MT_DAMAGE_REDUCTION, true );

	LOG_DEBUG_LOW( "NounShip", CharString().format("Damaged inflicted, When: %u, From: %s, Damage: %d, Type: 0x%X, Facing: %u", 
		nWhen, pFrom != NULL ? pFrom->name() : "NULL", damage, type, eFacing) );

	// callback so AI controlled ships can receive notification that they have been damaged by someone
	onAttacked( pFrom, damage, type );

	// calculate the points we're going to award to the attacker now before shields/armor reduce 
	// the damage applied to the hull.
	float fDamagePoints = float( damage ) / DAMAGE_POINTS_DIV; 

	// check shields
	if( damage > 0 )
	{	
		for(int i=0;i<m_Shields.size();i++)
			damage = m_Shields[i]->deflect( type, damage, eFacing, direction );
	}

	// check armor
	if ( damage > 0 )
	{
		for(int i=0;i<m_Armor.size();i++)
			damage = m_Armor[i]->deflect( type, damage, eFacing );
	}

	int internalDamage = damage;

	// inflict internal damage if hull is 50% or less
	int halfHull = maxDamage() >> 1;
	if ( damage > 0 && m_Damage > halfHull && (type & DAMAGE_EMP) == 0 )
	{
		// once hull is under 50%, start causing internal damage
		type |= DAMAGE_EMP;
		// scale internal damage up based on how much under 50% the hull 
		internalDamage = (damage * (m_Damage - halfHull)) / halfHull;
	}

	if ( damage > 0 && (type & (DAMAGE_EMP|DAMAGE_ELF)) )
	{
		// get the radius of this ship
		float myRadius = radius();
		ASSERT( myRadius > 0.0f );

		// calculate the hit position in object space of this ship
		Vector3 hitPosition( direction );
		hitPosition.normalize();				// direction is not normalized, it's the delta from the projectile/explosion, to the center of the ship
		hitPosition *= -(myRadius * 0.5f);		// flip the direction so it goes away from the center of the ship

		if ( isServer() && m_Gadgets.size() > 0 )
		{
			// seed with the time-stamp of the damage so we get the same gadget damaged
			// on all clients.
			srand( nWhen );
			int nPicked = rand() % m_Gadgets.size();

			NounGadget * pDamageGadget = m_Gadgets[ nPicked ];
			if ( pDamageGadget != NULL )
			{
				float fDistance = (pDamageGadget->position() - hitPosition).magnitude();
				float fScale = (1.0f - (fDistance / myRadius));

				if ( fScale > 0.0f )
					pDamageGadget->inflictDamage( nWhen, pFrom, fScale * internalDamage, type, direction );
			}
		}
	}

	if ( damage > 0 && (type & DAMAGE_ELF) )
	{
		// drain energy from main energy bank
		int drained = Min( energy(), damage );
		setEnergy( energy() - drained );

		// give energy to attacking ship
		if ( WidgetCast<NounShip>( pFrom ) )
			((NounShip *)pFrom)->setEnergy( ((NounShip *)pFrom)->energy() + drained );
	}

	// update the stats if it is another ship - NOTE this needs to happen before the DestroyShip
	// code below otherwise a player who is damaging this ship may not get credit/loot.
	if ( WidgetCast<NounShip>( pFrom ) )
	{
		NounShip * pFromShip = (NounShip *)pFrom;
		ASSERT( pFromShip );

		// set combat timer on attacking ship
		pFromShip->setOutOfCombat();

		// non-hull damages gives a lessor percentage of points..
		if ( damage <= 0 )
			fDamagePoints *= NOHULL_DAMAGE_POINTS_SCALE;

		if (! isFriend( pFrom ) )
		{
			// if the attacking ship is destroyed, then treat this as kamikaze points
			if ( pFromShip->isDestroyed() )
				gameContext()->gameUser()->onKamikaze( pFrom, 1.0f );
			else
				gameContext()->gameUser()->onDamageShip( pFrom, fDamagePoints, this);
		}
		else
		{
			gameContext()->gameUser()->onFriendlyFire( pFrom, fDamagePoints );
		}
	}

	if ( damage > 0 && (type & (DAMAGE_KINETIC|DAMAGE_ENERGY)) )
	{
		ASSERT( context() );

		// cap the damage, 
		damage = Min( maxDamage() - m_Damage, damage );

		// add the damage to the hull
		m_Damage = Min( m_Damage + damage, maxDamage() );
		// update the damage bits
		updateDamageBits();

		// check if the ship was destroyed
		if ( isServer() && isDestroyed() )
		{
			// ship is destroyed, send out verb to destroy this ship to all local clients
			Verb::Ref( new VerbDestroyShip( this, pFrom, false ) );
		}
	}
}