Example #1
0
File: mad.c Project: wangeek/Egoboo
//--------------------------------------------------------------------------------------------
int randomize_action( int action, int slot )
{
    /// @details BB@> this function actually determines whether the action fillows the
    ///               pattern of ACTION_?A, ACTION_?B, ACTION_?C, ACTION_?D, with
    ///               A and B being for the left hand, and C and D being for the right hand

    int diff = 0;

    // a valid slot?
    if ( slot < 0 || slot >= SLOT_COUNT ) return action;

    // a valid action?
    if ( action < 0 || action >= ACTION_COUNT ) return bfalse;

    diff = slot * 2;

    //---- non-randomizable actions
    if ( ACTION_MG == action ) return action;       // MG      = Open Chest
    else if ( ACTION_MH == action ) return action;       // MH      = Sit
    else if ( ACTION_MI == action ) return action;       // MI      = Ride
    else if ( ACTION_MJ == action ) return action;       // MJ      = Object Activated
    else if ( ACTION_MK == action ) return action;       // MK      = Snoozing
    else if ( ACTION_ML == action ) return action;       // ML      = Unlock
    else if ( ACTION_JA == action ) return action;       // JA      = Jump
    else if ( ACTION_RA == action ) return action;       // RA      = Roll
    else if ( ACTION_IS_TYPE( action, W ) ) return action;  // WA - WD = Walk

    //---- do a couple of special actions that have left/right
    else if ( ACTION_EA == action || ACTION_EB == action ) action = ACTION_JB + slot;   // EA/EB = Evade left/right
    else if ( ACTION_JB == action || ACTION_JC == action ) action = ACTION_JB + slot;   // JB/JC = Dropped item left/right
    else if ( ACTION_MA == action || ACTION_MB == action ) action = ACTION_MA + slot;   // MA/MB = Drop left/right item
    else if ( ACTION_MC == action || ACTION_MD == action ) action = ACTION_MC + slot;   // MC/MD = Slam left/right
    else if ( ACTION_ME == action || ACTION_MF == action ) action = ACTION_ME + slot;   // ME/MF = Grab item left/right
    else if ( ACTION_MM == action || ACTION_MN == action ) action = ACTION_MM + slot;   // MM/MN = Held left/right

    //---- actions that can be randomized, but are not left/right sensitive
    // D = dance
    else if ( ACTION_IS_TYPE( action, D ) ) action = ACTION_TYPE( D ) + generate_randmask( 0, 3 );

    //---- handle all the normal attack/defense animations
    // U = unarmed
    else if ( ACTION_IS_TYPE( action, U ) ) action = ACTION_TYPE( U ) + diff + generate_randmask( 0, 1 );
    // T = thrust
    else if ( ACTION_IS_TYPE( action, T ) ) action = ACTION_TYPE( T ) + diff + generate_randmask( 0, 1 );
    // C = chop
    else if ( ACTION_IS_TYPE( action, C ) ) action = ACTION_TYPE( C ) + diff + generate_randmask( 0, 1 );
    // S = slice
    else if ( ACTION_IS_TYPE( action, S ) ) action = ACTION_TYPE( S ) + diff + generate_randmask( 0, 1 );
    // B = bash
    else if ( ACTION_IS_TYPE( action, B ) ) action = ACTION_TYPE( B ) + diff + generate_randmask( 0, 1 );
    // L = longbow
    else if ( ACTION_IS_TYPE( action, L ) ) action = ACTION_TYPE( L ) + diff + generate_randmask( 0, 1 );
    // X = crossbow
    else if ( ACTION_IS_TYPE( action, X ) ) action = ACTION_TYPE( X ) + diff + generate_randmask( 0, 1 );
    // F = fling
    else if ( ACTION_IS_TYPE( action, F ) ) action = ACTION_TYPE( F ) + diff + generate_randmask( 0, 1 );
    // P = parry/block
    else if ( ACTION_IS_TYPE( action, P ) ) action = ACTION_TYPE( P ) + diff + generate_randmask( 0, 1 );
    // Z = zap
    else if ( ACTION_IS_TYPE( action, Z ) ) action = ACTION_TYPE( Z ) + diff + generate_randmask( 0, 1 );

    //---- these are passive actions
    // H = hurt
    else if ( ACTION_IS_TYPE( action, H ) ) action = ACTION_TYPE( H ) + generate_randmask( 0, 3 );
    // K = killed
    else if ( ACTION_IS_TYPE( action, K ) ) action = ACTION_TYPE( K ) + generate_randmask( 0, 3 );

    return action;
}
Example #2
0
void Enchantment::applyEnchantment(std::shared_ptr<Object> target)
{
    //Invalid target?
    if( target->isTerminated() || (!target->isAlive() && !_enchantProfile->_target._stay) ) {
		Log::get().warn("%s:%d: invalid target\n", __FILE__, __LINE__);
        requestTerminate();
        return;
    }

    //Already added to a target?
    if(_target.lock()) {
        throw std::logic_error("Enchantment::applyEnchantment() - Already applied\n");
    }

    // do retargeting, if necessary
    // Should it choose an inhand item?
    if (_enchantProfile->retarget) {
        // Left, right, or both are valid
        if (target->getRightHandItem()) {
            // Only right hand is valid
            target = target->getRightHandItem();
        }
        else if (target->getLeftHandItem()) {
            // Pick left hand
            target = target->getLeftHandItem();
        }
        else {
            // No weapons to pick, make it fail
			Log::get().debug("Enchantment::applyEnchantment() - failed because target has no valid items in hand\n");
            requestTerminate();
            return;
        }
    }

    //Set our target, stored as a weak_ptr
    _target = target;

    // Check damage type, 90% damage resistance is enough to resist the enchant
    if (_enchantProfile->required_damagetype < DAMAGE_COUNT) {
        if (target->getDamageReduction(_enchantProfile->required_damagetype) >= 0.90f) {
			Log::get().debug("Enchantment::applyEnchantment() - failed because the target is immune to the enchant.\n");
            requestTerminate();
            return;
        }
    }

    // Check if target has the required damage type we need
    if (_enchantProfile->require_damagetarget_damagetype < DAMAGE_COUNT) {
        if (target->damagetarget_damagetype != _enchantProfile->require_damagetarget_damagetype) {
			Log::get().warn("%s:%d: application of enchantment failed because the target not have the right damagetarget_damagetype.\n", __FILE__, __LINE__);
            requestTerminate();
            return;
        }
    }

    //modify enchant duration with damage resistance (bad resistance actually *increases* duration!)
    if ( _lifeTime > 0 && _enchantProfile->required_damagetype < DAMAGE_COUNT && target ) {
        _lifeTime -= std::ceil(target->getDamageReduction(_enchantProfile->required_damagetype) * _enchantProfile->lifetime);
    }

    // Create an overlay character?
    if (_enchantProfile->spawn_overlay)
    {
        std::shared_ptr<Object> overlay = _currentModule->spawnObject(target->getPosition(), _spawnerProfileID, target->team, 0, target->ori.facing_z, "", ObjectRef::Invalid );
        if (overlay)
        {
            _overlay = overlay;                             //Kill this character on end...
            overlay->ai.setTarget(target->getObjRef());
            overlay->is_overlay  = true;
            overlay->ai.state = _enchantProfile->spawn_overlay; // ??? WHY DO THIS ???

            // Start out with ActionMJ...  Object activated
            int action = overlay->getProfile()->getModel()->getAction(ACTION_MJ);
            if ( !ACTION_IS_TYPE( action, D ) )
            {
                chr_start_anim( overlay.get(), action, false, true );
            }

            // Assume it's transparent...
            overlay->setLight(254);
            overlay->setAlpha(128);
        }
    }

    //Check if this enchant has any set modifiers that conflicts with another enchant
    _modifiers.remove_if([this, &target](const EnchantModifier &modifier) {

        //Only set types can conflict
        if(!Ego::Attribute::isOverrideSetAttribute(modifier._type)) {
            return false;
        }

        //Is there no conflict?
        if(target->getTempAttributes().find(modifier._type) == target->getTempAttributes().end()) {
            return false;
        }

        //Ok there exist a conflict, so now we have to resolve it somehow
        //Does this enchant override other enchants?
        if(getProfile()->_override) {
            bool conflictResolved = false;

            //Find the active enchant that conflicts with us
            for(const std::shared_ptr<Ego::Enchantment> &conflictingEnchant : target->getActiveEnchants()) {
                conflictingEnchant->_modifiers.remove_if([this, &conflictingEnchant, &modifier, &conflictResolved](const EnchantModifier &otherModifier)
                    {
                        //Is this the one?
                        if(modifier._type == otherModifier._type) {
                            conflictResolved = true;

                            //Remove Enchants that conflict with this one?
                            if(getProfile()->remove_overridden) {
                                conflictingEnchant->requestTerminate();
                            }

                            return true;
                        }

                        //Nope, keep looking
                        return false;
                    });

                //Has it been resolved?
                if(conflictResolved) {
                    break;
                }
            }

            //We have higher priority than exiting enchants
            return false;
        }
        else {
            //The existing enchant has higher priority than ours
            return true;
        }
    });

    //Now actually apply the values to the target
    for(const EnchantModifier &modifier : _modifiers)
    {
        //These should never occur
        if(modifier._type == Ego::Attribute::NR_OF_PRIMARY_ATTRIBUTES ||
           modifier._type == Ego::Attribute::NR_OF_ATTRIBUTES) 
        {
            throw std::logic_error("Enchant.cpp - Invalid enchant type: meta-type as modifier");
        }

        //Morph is special and handled differently than others
        if(modifier._type == Ego::Attribute::MORPH) {
            //Store target's original armor
            target->getTempAttributes()[Ego::Attribute::MORPH] = target->skin;

            //Transform the object
            target->polymorphObject(_spawnerProfileID, 0);
        }

        //Is it a set type?
        else if(Ego::Attribute::isOverrideSetAttribute(modifier._type)) {
            target->getTempAttributes()[modifier._type] = modifier._value;
        }

        //It's a cumulative addition
        else {
            target->getTempAttributes()[modifier._type] += modifier._value;            
        }
    }

    //Finally apply boost values to owner as well
    std::shared_ptr<Object> owner = _owner.lock();
    if(owner != nullptr && !owner->isTerminated()) {
        owner->getTempAttributes()[Ego::Attribute::MANA_REGEN] += _ownerManaSustain;
        owner->getTempAttributes()[Ego::Attribute::LIFE_REGEN] += _ownerLifeSustain;
    }

    //Insert this enchantment into the Objects list of active enchants
    target->getActiveEnchants().push_front(shared_from_this());    
}