public override void ReceivedDamage(IAttackerEntity attacker, CombatAmountType damageAmountType, int damage)
        {
            BaseCharacterEntity attackerCharacter = attacker as BaseCharacterEntity;

            // If summoned by someone, summoner is attacker
            if (attackerCharacter != null &&
                attackerCharacter is BaseMonsterCharacterEntity &&
                (attackerCharacter as BaseMonsterCharacterEntity).IsSummoned)
            {
                attackerCharacter = (attackerCharacter as BaseMonsterCharacterEntity).Summoner;
            }

            // Add received damage entry
            if (attackerCharacter != null)
            {
                ReceivedDamageRecord receivedDamageRecord = new ReceivedDamageRecord();
                receivedDamageRecord.totalReceivedDamage = damage;
                if (receivedDamageRecords.ContainsKey(attackerCharacter))
                {
                    receivedDamageRecord = receivedDamageRecords[attackerCharacter];
                    receivedDamageRecord.totalReceivedDamage += damage;
                }
                receivedDamageRecord.lastReceivedDamageTime = Time.unscaledTime;
                receivedDamageRecords[attackerCharacter]    = receivedDamageRecord;
            }

            base.ReceivedDamage(attackerCharacter, damageAmountType, damage);
        }
        public override void ReceivedDamage(IAttackerEntity attacker, CombatAmountType damageAmountType, int damage)
        {
            var attackerCharacter = attacker as BaseCharacterEntity;

            // If summoned by someone, summoner is attacker
            if (attackerCharacter != null &&
                attackerCharacter is BaseMonsterCharacterEntity &&
                (attackerCharacter as BaseMonsterCharacterEntity).IsSummoned)
            {
                attackerCharacter = (attackerCharacter as BaseMonsterCharacterEntity).Summoner;
            }

            // Add received damage entry
            if (attackerCharacter != null)
            {
                var receivedDamageRecord = new ReceivedDamageRecord();
                receivedDamageRecord.totalReceivedDamage = damage;
                if (receivedDamageRecords.ContainsKey(attackerCharacter))
                {
                    receivedDamageRecord = receivedDamageRecords[attackerCharacter];
                    receivedDamageRecord.totalReceivedDamage += damage;
                }
                receivedDamageRecord.lastReceivedDamageTime = Time.unscaledTime;
                receivedDamageRecords[attackerCharacter]    = receivedDamageRecord;
            }

            base.ReceivedDamage(attackerCharacter, damageAmountType, damage);

            // If dead destroy / respawn
            if (IsDead())
            {
                CurrentHp = 0;
                if (!IsSummoned)
                {
                    // If not summoned by someone, destroy and respawn it
                    DestroyAndRespawn();
                }
            }
        }
        public override sealed void Killed(BaseCharacterEntity lastAttacker)
        {
            base.Killed(lastAttacker);

            // If this summoned by someone, don't give reward to killer
            if (IsSummoned)
            {
                return;
            }

            Reward                    reward     = gameplayRule.MakeMonsterReward(monsterCharacter);
            HashSet <uint>            looters    = new HashSet <uint>();
            BasePlayerCharacterEntity lastPlayer = null;

            if (lastAttacker != null)
            {
                lastPlayer = lastAttacker as BasePlayerCharacterEntity;
            }
            GuildData tempGuildData;
            PartyData tempPartyData;
            BasePlayerCharacterEntity  tempPlayerCharacter;
            BaseMonsterCharacterEntity tempMonsterCharacter;
            bool  givenRewardExp;
            bool  givenRewardCurrency;
            float shareGuildExpRate;

            if (receivedDamageRecords.Count > 0)
            {
                float tempHighRewardRate = 0f;
                foreach (BaseCharacterEntity enemy in receivedDamageRecords.Keys)
                {
                    givenRewardExp      = false;
                    givenRewardCurrency = false;
                    shareGuildExpRate   = 0f;

                    ReceivedDamageRecord receivedDamageRecord = receivedDamageRecords[enemy];
                    float rewardRate = (float)receivedDamageRecord.totalReceivedDamage / (float)CacheMaxHp;
                    if (rewardRate > 1f)
                    {
                        rewardRate = 1f;
                    }

                    if (enemy is BasePlayerCharacterEntity)
                    {
                        bool makeMostDamage = false;
                        tempPlayerCharacter = enemy as BasePlayerCharacterEntity;
                        // Clear looters list when it is found new player character who make most damages
                        if (rewardRate > tempHighRewardRate)
                        {
                            tempHighRewardRate = rewardRate;
                            looters.Clear();
                            makeMostDamage = true;
                        }
                        // Try find guild data from player character
                        if (tempPlayerCharacter.GuildId > 0 && gameManager.TryGetGuild(tempPlayerCharacter.GuildId, out tempGuildData))
                        {
                            // Calculation amount of Exp which will be shared to guild
                            shareGuildExpRate = (float)tempGuildData.ShareExpPercentage(tempPlayerCharacter.Id) * 0.01f;
                            // Will share Exp to guild when sharing amount more than 0
                            if (shareGuildExpRate > 0)
                            {
                                // Increase guild exp
                                gameManager.IncreaseGuildExp(tempPlayerCharacter, (int)(reward.exp * shareGuildExpRate * rewardRate));
                            }
                        }
                        // Try find party data from player character
                        if (tempPlayerCharacter.PartyId > 0 && gameManager.TryGetParty(tempPlayerCharacter.PartyId, out tempPartyData))
                        {
                            BasePlayerCharacterEntity partyPlayerCharacter;
                            // Loop party member to fill looter list / increase gold / increase exp
                            foreach (SocialCharacterData member in tempPartyData.GetMembers())
                            {
                                if (gameManager.TryGetPlayerCharacterById(member.id, out partyPlayerCharacter))
                                {
                                    // If share exp, every party member will receive devided exp
                                    // If not share exp, character who make damage will receive non-devided exp
                                    if (tempPartyData.shareExp)
                                    {
                                        partyPlayerCharacter.RewardExp(reward, (1f - shareGuildExpRate) / (float)tempPartyData.CountMember() * rewardRate, RewardGivenType.PartyShare);
                                    }

                                    // If share item, every party member will receive devided gold
                                    // If not share item, character who make damage will receive non-devided gold
                                    if (tempPartyData.shareItem)
                                    {
                                        if (makeMostDamage)
                                        {
                                            // Make other member in party able to pickup items
                                            looters.Add(partyPlayerCharacter.ObjectId);
                                        }
                                        partyPlayerCharacter.RewardCurrencies(reward, 1f / (float)tempPartyData.CountMember() * rewardRate, RewardGivenType.PartyShare);
                                    }
                                }
                            }
                            // Shared exp has been given, so do not give it to character again
                            if (tempPartyData.shareExp)
                            {
                                givenRewardExp = true;
                            }
                            // Shared gold has been given, so do not give it to character again
                            if (tempPartyData.shareItem)
                            {
                                givenRewardCurrency = true;
                            }
                        }

                        // Add reward to current character in damage record list
                        if (!givenRewardExp)
                        {
                            // Will give reward when it was not given
                            int petIndex = tempPlayerCharacter.IndexOfSummon(SummonType.Pet);
                            if (petIndex >= 0)
                            {
                                tempMonsterCharacter = tempPlayerCharacter.Summons[petIndex].CacheEntity;
                                if (tempMonsterCharacter != null)
                                {
                                    // Share exp to pet, set multiplier to 0.5, because it will be shared to player
                                    tempMonsterCharacter.RewardExp(reward, (1f - shareGuildExpRate) * 0.5f * rewardRate, RewardGivenType.KillMonster);
                                }
                                // Set multiplier to 0.5, because it was shared to monster
                                tempPlayerCharacter.RewardExp(reward, (1f - shareGuildExpRate) * 0.5f * rewardRate, RewardGivenType.KillMonster);
                            }
                            else
                            {
                                // No pet, no share, so rate is 1f
                                tempPlayerCharacter.RewardExp(reward, (1f - shareGuildExpRate) * rewardRate, RewardGivenType.KillMonster);
                            }
                        }

                        if (!givenRewardCurrency)
                        {
                            // Will give reward when it was not given
                            tempPlayerCharacter.RewardCurrencies(reward, rewardRate, RewardGivenType.KillMonster);
                        }

                        if (makeMostDamage)
                        {
                            // Make current character able to pick up item because it made most damage
                            looters.Add(tempPlayerCharacter.ObjectId);
                        }
                    } // End is `BasePlayerCharacterEntity` condition
                }     // End for-loop
            }         // End count recived damage record count
            receivedDamageRecords.Clear();
            foreach (ItemDrop randomItem in monsterCharacter.randomItems)
            {
                if (Random.value <= randomItem.dropRate)
                {
                    Item  item   = randomItem.item;
                    short amount = randomItem.amount;
                    if (item != null && GameInstance.Items.ContainsKey(item.DataId))
                    {
                        // Drop item to the ground
                        if (amount > item.maxStack)
                        {
                            amount = item.maxStack;
                        }
                        CharacterItem dropData = CharacterItem.Create(item, 1);
                        dropData.amount = amount;
                        ItemDropEntity.DropItem(this, dropData, looters);
                    }
                }
            }

            if (lastPlayer != null)
            {
                // Increase kill progress
                lastPlayer.OnKillMonster(this);
            }

            if (!IsSummoned)
            {
                // If not summoned by someone, destroy and respawn it
                DestroyAndRespawn();
            }
        }