Пример #1
0
uint8 CombatManager::_executeAttack(CreatureObject* attacker,CreatureObject* defender,ObjectControllerCmdProperties *cmdProperties,Weapon* weapon)
{
	uint8	randomHitPool			= 100;
	//uint8	randomPoolHitChance		= 100;
	uint8	stateApplied			= 0;
	int32	multipliedDamage		= 0;
	BString	combatSpam				= "melee";

	// first see if we actually hit our target
	uint8 attackResult = _hitCheck(attacker,defender,cmdProperties,weapon);

	// only proceed, if so
	if(!attackResult)
	{
		// TODO: retrieve from weapon
		int32 baseMinDamage	= 50;
		int32 baseMaxDamage	= 100;

		// NOTE: Some weapon data just for tesing and to give the npc a fair chance...

		if (weapon->hasAttribute("cat_wpn_damage.wpn_damage_min"))
		{
			baseMinDamage = weapon->getAttribute<int32>("cat_wpn_damage.wpn_damage_min");
		}
		if (weapon->hasAttribute("cat_wpn_damage.wpn_damage_max"))
		{
			baseMaxDamage = weapon->getAttribute<int32>("cat_wpn_damage.wpn_damage_max");
		}


		//Sanity checks of db data
		if (baseMinDamage < 1)
			baseMinDamage = 1;

		if (baseMaxDamage < 1)
			baseMaxDamage = 1;

		if(baseMaxDamage <= baseMinDamage)
		{
			baseMaxDamage = baseMinDamage +1;
		}

		int32 baseDamage	= -((gRandom->getRand()%(baseMaxDamage - baseMinDamage)) + baseMinDamage);

		// apply damage multiplier
		if(cmdProperties->mDamageMultiplier)
		{
			multipliedDamage = static_cast<uint32>(static_cast<float>(baseDamage) * cmdProperties->mDamageMultiplier);
		}
		else
		{
			multipliedDamage = baseDamage;
		}

		// mitigation
		multipliedDamage = _mitigateDamage(attacker,defender,cmdProperties,multipliedDamage,weapon);

		// state effects
		stateApplied = _tryStateEffects(attacker,defender,cmdProperties,weapon);


		// Here is the deal. When a player makes damage to a npc, we have to register the player, its group, damage done and what (kind of) weapon used.
		NPCObject* npc = dynamic_cast<NPCObject*>(defender);
		if (!defender->isDead() && npc)
		{
			PlayerObject* player = dynamic_cast<PlayerObject*>(attacker);
			if (player)
			{
                npc->updateDamage(player->getId(), player->getGroupId(), weapon->getGroup(), -multipliedDamage, player->GetPosture(), glm::distance(defender->mPosition, player->mPosition));
			}
		}

		// ham damage
		// if no target pool set, pick a random one
		if(!cmdProperties->mHealthHitChance && !cmdProperties->mActionHitChance && !cmdProperties->mMindHitChance)
		{
			switch(gRandom->getRand()%3)
			{
				case 0: randomHitPool = HamBar_Health;	break;
				case 1: randomHitPool = HamBar_Action;	break;
				case 2: randomHitPool = HamBar_Mind;	break;

				default: randomHitPool = 0;				break;
			}
		}

		auto ham = gWorldManager->getKernel()->GetServiceManager()->GetService<swganh::ham::HamService>("HamService");

		//this is pure idiocy in my eyes. Why for gods sake should an object be a creature ?
		// is there precedent through SOE???????????
		if (defender->getCreoGroup() != CreoGroup_AttackableObject)
		{
			// random pool attack
			if(randomHitPool != 100)
			{
				ham->UpdateCurrentHitpoints(defender,randomHitPool,multipliedDamage);
				//defender->getHam()->updatePropertyValue(randomHitPool,HamProperty_CurrentHitpoints,multipliedDamage,true);
			}
			// direct pool attack
			else
			{
				// health hit
				if(cmdProperties->mHealthHitChance)
				{
					ham->UpdateCurrentHitpoints(defender,HamBar_Health,multipliedDamage);
					//defender->getHam()->updatePropertyValue(HamBar_Health,HamProperty_CurrentHitpoints,multipliedDamage,true);
				}
				// action hit
				else if(cmdProperties->mActionHitChance)
				{
					ham->UpdateCurrentHitpoints(defender,HamBar_Action,multipliedDamage);
					//defender->getHam()->updatePropertyValue(HamBar_Action,HamProperty_CurrentHitpoints,multipliedDamage,true);
				}
				// mind hit
				else if(cmdProperties->mMindHitChance)
				{
					ham->UpdateCurrentHitpoints(defender,HamBar_Mind,multipliedDamage);
					//defender->getHam()->updatePropertyValue(HamBar_Mind,HamProperty_CurrentHitpoints,multipliedDamage,true);
				}
			}
		}
		else
		{
			ham->UpdateCurrentHitpoints(defender,HamBar_Health,multipliedDamage);
			//defender->getHam()->updateSingleHam(multipliedDamage, true);
		}
		if (defender->isIncapacitated())
		{
			PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker);
			if (playerAttacker && playerAttacker->isConnected())
			{
                gMessageLib->SendSystemMessage(::common::OutOfBand("base_player", "prose_target_incap", 0, defender->getId(), 0), playerAttacker);
            }
        }
        if (defender->isDead())
        {
            PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker);
            if (playerAttacker && playerAttacker->isConnected())
            {
                gMessageLib->SendSystemMessage(::common::OutOfBand("base_player", "killer_target_dead"), playerAttacker, true);
            }
        }
    }


    // fly text and animations
    // default attack(s)
    if(cmdProperties->mCmdCrc == 0xa8fef90a)
    {
        uint32 animCrc = getDefaultAttackAnimation(weapon->getGroup());

        switch(attackResult)
        {
            // hit
        case 0:
        case 2:
        case 3:
        case 4:
        {
            gMessageLib->sendCombatAction(attacker,defender,animCrc,0,0,1);
        }
        break;

        // miss
        case 1:
        {
            gMessageLib->sendCombatAction(attacker,defender,animCrc);
        }
        break;
        }
    }
    // special attack
    else
    {
        switch(attackResult)
        {
            // hit
        case 0:
        case 2:
        case 3:
        case 4:
        {
            gMessageLib->sendCombatAction(attacker,defender,cmdProperties->mAnimationCrc,cmdProperties->mTrail1,cmdProperties->mTrail2,1);
        }
        break;

        //miss
        case 1:
        {
            gMessageLib->sendCombatAction(attacker,defender,cmdProperties->mAnimationCrc,cmdProperties->mTrail1,cmdProperties->mTrail2);
        }
        break;
        }
    }

    switch(attackResult)
    {
    case 0:
    {
        // Defender got hit.
    }
    break;

    case 1:
    {
        gMessageLib->sendFlyText(defender,"combat_effects","miss",255,255,255);
    }
    break;

    case 2:
        // We cant block yet, can we?
    {
        gMessageLib->sendFlyText(defender,"combat_effects","block",0,255,0);
        gMessageLib->sendCombatAction(defender,attacker,0xe430ff04);
    }
    break;

    case 3:
    {
        gMessageLib->sendFlyText(defender,"combat_effects","dodge",0,255,0);
        gMessageLib->sendCombatAction(defender,attacker,0xe430ff04);	// Dodge
    }
    break;

    case 4:
    {
        gMessageLib->sendFlyText(defender,"combat_effects","counterattack",0,255,0);	// I can's see this effect working?
    }
    break;
    }

    // send combat spam
    // default attack
    if(cmdProperties->mCmdCrc == 0xa8fef90a)
    {
        combatSpam = getDefaultSpam(weapon->getGroup());
    }
    // special attack
    else
    {
        if(cmdProperties->mCbtSpam.getLength())
        {
            combatSpam = cmdProperties->mCbtSpam.getAnsi();
        }
    }

    switch(attackResult)
    {
    case 0:
        combatSpam << "_hit";
        break;
    case 1:
        combatSpam << "_miss";
        break;
    case 2:
        combatSpam << "_block";
        break;
    case 3:
        combatSpam << "_evade";
        break;
    case 4:
        combatSpam << "_counter";
        break;

    default:
        break;
    }
    gMessageLib->sendCombatSpam(attacker,defender,-multipliedDamage,"cbt_spam",combatSpam);


    return(0);
}
Пример #2
0
// uint8 CombatManager::_executeAttack(CreatureObject* attacker,CreatureObject* defender,ObjectControllerCmdProperties *cmdProperties,Weapon* weapon)
uint8 NpcManager::_executeAttack(CreatureObject* attacker,CreatureObject* defender,Weapon* weapon)
{
    uint8	randomHitPool			= 100;
    //uint8	randomPoolHitChance		= 100;
    //uint8	stateApplied			= 0;
    int32	multipliedDamage		= 0;
    BString	combatSpam				= "melee";

    // first see if we actually hit our target
    // uint8 attackResult = _hitCheck(attacker,defender,cmdProperties,weapon);
    uint8 attackResult = _hitCheck(attacker,defender,weapon);

    // only proceed, if so
    if (!attackResult)
    {
        // TODO: retrieve from weapon
        AttackableCreature* attackerNpc = dynamic_cast<AttackableCreature*>(attacker);
        if (!attackerNpc)
        {
            return 0;
        }

        int32 baseMinDamage	= attackerNpc->getMinDamage();
        int32 baseMaxDamage	= attackerNpc->getMaxDamage();

        int32 baseDamage	= -((gRandom->getRand()%(baseMaxDamage - baseMinDamage)) + baseMinDamage);

        // apply damage multiplier
        /*
        if(cmdProperties->mDamageMultiplier)
        {
        	multipliedDamage = baseDamage * cmdProperties->mDamageMultiplier;
        }
        else
        {
        	multipliedDamage = baseDamage;
        }
        */
        multipliedDamage = baseDamage;

        // mitigation
        // multipliedDamage = _mitigateDamage(attacker,defender,cmdProperties,multipliedDamage,weapon);

        // state effects
        // stateApplied = _tryStateEffects(attacker,defender,cmdProperties,weapon);

        // ham damage
        // if no target pool set, pick a random one
        // if (!cmdProperties->mHealthHitChance && !cmdProperties->mActionHitChance && !cmdProperties->mMindHitChance)
        {
            switch(gRandom->getRand()%3)
            {
            case 0:
                randomHitPool = HamBar_Health;
                break;
            case 1:
                randomHitPool = HamBar_Action;
                break;
            case 2:
                randomHitPool = HamBar_Mind;
                break;

            default:
                randomHitPool = 0;
                break;
            }
        }

		auto ham = gWorldManager->getKernel()->GetServiceManager()->GetService<swganh::ham::HamService>("HamService");

        if (defender->getCreoGroup() != CreoGroup_AttackableObject)
        {
            // random pool attack
            if(randomHitPool != 100)
            {
				ham->UpdateCurrentHitpoints(defender, randomHitPool, multipliedDamage);
               
            }
            // direct pool attack
            /*
            else
            {
            	// health hit
            	if(cmdProperties->mHealthHitChance)
            	{
            		defender->getHam()->updatePropertyValue(HamBar_Health,HamProperty_CurrentHitpoints,multipliedDamage,true);
            	}
            	// action hit
            	else if(cmdProperties->mActionHitChance)
            	{
            		defender->getHam()->updatePropertyValue(HamBar_Action,HamProperty_CurrentHitpoints,multipliedDamage,true);
            	}
            	// mind hit
            	else if(cmdProperties->mMindHitChance)
            	{
            		defender->getHam()->updatePropertyValue(HamBar_Mind,HamProperty_CurrentHitpoints,multipliedDamage,true);
            	}
            }
            */
        }
        else
        {
            ham->UpdateCurrentHitpoints(defender, HamBar_Health, multipliedDamage);
        }
        /*
        if (defender->isIncapacitated())
        {
        	PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker);
        	if (playerAttacker && playerAttacker->isConnected())
        	{
        		if (defender->getType() == ObjType_Player)
        		{
        			int8 str[128];
        			if (defender->getLastName().getLength())
        			{
        				sprintf(str,"%s %s", defender->getFirstName().getAnsi(), defender->getLastName().getAnsi());
        			}
        			else
        			{
        				sprintf(str,"%s", defender->getFirstName().getAnsi());
        			}
        			BString playerName(str);
        			playerName.convert(BSTRType_Unicode16);

        			gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap", "", "", L"", 0, "", "", playerName);
        		}
        		else
        		{
        			gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_incap", "", "", L"", 0, defender->getSpeciesGroup(), defender->getSpeciesString());
        		}
        	}
        }

        if (defender->isDead())
        {
        	PlayerObject* playerAttacker = dynamic_cast<PlayerObject*>(attacker);
        	if (playerAttacker && playerAttacker->isConnected())
        	{
        		if (defender->getType() == ObjType_Player)
        		{
        			int8 str[128];
        			if (defender->getLastName().getLength())
        			{
        				sprintf(str,"%s %s", defender->getFirstName().getAnsi(), defender->getLastName().getAnsi());
        			}
        			else
        			{
        				sprintf(str,"%s", defender->getFirstName().getAnsi());
        			}
        			BString playerName(str);
        			playerName.convert(BSTRType_Unicode16);
        			gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_dead", "", "", L"", 0, "", "", playerName);
        		}
        		else
        		{
        			gMessageLib->sendSystemMessage(playerAttacker,L"","base_player","prose_target_dead", "", "", L"", 0, defender->getSpeciesGroup(), defender->getSpeciesString());
        		}
        	}
        }
        */
    }

    // fly text and animations
    // default attack(s)
    // Assume we only use the default attack for now.
    // if (cmdProperties->mCmdCrc == 0xa8fef90a)
    {
        // This is just a temp fix, we need to solve how to differ creatures from human npc's.
        uint32 animCrc;
        if (gWorldConfig->isTutorial())
        {
            animCrc = gCombatManager->getDefaultAttackAnimation(weapon->getGroup());
        }
        else
        {
            // creature_attack_light
            animCrc = 0x8BF5B8B6;
        }
        // creature_attack_light 0xB6B8F58B (reversed from WIKI 0x8BF5B8B6)
        // creature_attack_medium 0x48CBE352 ( 0x52E3CB48 )
        // creature_attack_special_1_medium 0x24AEEF7A
        // creature_attack_special_1_light 0x13E6B2DE
        // creature_attack_special_2_medium 0x7ACB0D96
        // creature_attack_special_2_light 0x205E4B0F
        // creature_attack_ranged_light 0x8D49FC90
        // creature_attack_ranged_medium 0x59E0483C


        switch(attackResult)
        {
            // hit
        case 0:
        case 2:
        case 3:
        case 4:
        {
            gMessageLib->sendCombatAction(attacker,defender,animCrc,0,0,1);
        }
        break;

        // miss
        case 1:
        {
            gMessageLib->sendCombatAction(attacker,defender,animCrc);
        }
        break;
        }
    }
    // special attack
    /*
    else
    {
    	switch(attackResult)
    	{
    		// hit
    		case 0:case 2:case 3:case 4:
    		{
    			gMessageLib->sendCombatAction(attacker,defender,cmdProperties->mAnimationCrc,cmdProperties->mTrail1,cmdProperties->mTrail2,1);
    		}
    		break;

    		//miss
    		case 1:
    		{
    			gMessageLib->sendCombatAction(attacker,defender,cmdProperties->mAnimationCrc,cmdProperties->mTrail1,cmdProperties->mTrail2);
    		}
    		break;
    	}
    }
    */

    switch(attackResult)
    {
    case 0:
    {
        // Defender got hit.
    }
    break;

    case 1:
    {
        gMessageLib->sendFlyText(defender,"combat_effects","miss",255,255,255);
    }
    break;

    case 2:
        // We cant block yet, can we?
    {
        // gMessageLib->sendFlyText(defender,"combat_effects","block",0,255,0);
    }
    // break;

    case 3:
    {
        gMessageLib->sendFlyText(defender,"combat_effects","dodge",0,255,0);
        gMessageLib->sendCombatAction(defender,attacker,0xe430ff04);	// Dodge
    }
    break;

    case 4:
    {
        gMessageLib->sendFlyText(defender,"combat_effects","counterattack",0,255,0);	// I can's see this effect working?
    }
    break;
    }

    // send combat spam
    // default attack
    // if(cmdProperties->mCmdCrc == 0xa8fef90a)
    {
        // combatSpam = gCombatManager->getDefaultSpam(weapon->getGroup());
        combatSpam = "creature";
    }
    // special attack
    /*
    else
    {
    	if(cmdProperties->mCbtSpam.getLength())
    	{
    		combatSpam = cmdProperties->mCbtSpam.getAnsi();
    	}
    }
    */

    switch(attackResult)
    {
    case 0:
        combatSpam << "_hit";
        break;
    case 1:
        combatSpam << "_miss";
        break;
    case 2:
        combatSpam << "_block";
        break;
    case 3:
        combatSpam << "_evade";
        break;
    case 4:
        combatSpam << "_counter";
        break;

    default:
        break;
    }
    gMessageLib->sendCombatSpam(attacker,defender,-multipliedDamage,"cbt_spam",combatSpam);

    return(0);
}