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; }
void Creature::drainMana(Creature* attacker, int32_t manaLoss) { onAttacked(); changeMana(-manaLoss); if (attacker) { addDamagePoints(attacker, manaLoss); } }
void Creature::drainMana(const CombatSource& combatSource, int32_t points, bool showtext) { onAttacked(); changeMana(-points); if(combatSource.isSourceCreature()){ combatSource.getSourceCreature()->onAttackedCreatureDrainMana(this, points); } }
void Creature::drainMana(Creature* attacker, CombatType_t combatType, int32_t damage) { lastDamageSource = combatType; onAttacked(); changeMana(-damage); if(attacker) attacker->onTargetDrainMana(this, damage); }
void Creature::drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage) { lastDamageSource = combatType; onAttacked(); changeHealth(-damage); if(attacker) attacker->onAttackedCreatureDrainHealth(this, damage); }
void Creature::onAttacking(uint32_t interval) { if(!attackedCreature) return; onAttacked(); attackedCreature->onAttacked(); if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true)) doAttacking(interval); }
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; }
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); } } }
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; } }
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); }
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; }
void Creature::drainMana(Creature* attacker, int32_t manaLoss) { onAttacked(); changeMana(-manaLoss); }
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 ) ); } } }