public virtual double TreasureMapChance{ get{ return TreasureMap.LootChance; } }
public virtual int TreasureMapLevel{ get{ return -1; } }
public override bool OnBeforeDeath()
{
int treasureLevel = TreasureMapLevel;
if ( treasureLevel == 1 && this.Map == Map.Trammel && TreasureMap.IsInHavenIsland( this ) )
{
Mobile killer = this.LastKiller;
if ( killer is BaseCreature )
killer = ((BaseCreature)killer).GetMaster();
Console.WriteLine("Paragon: {0}, chest chance: {100}.", m_Paragon, Paragon.ChestChance);
}
if ( !Summoned && !NoKillAwards && !IsBonded && treasureLevel >= 0 )
{
if ( m_Paragon && Paragon.ChestChance > Utility.RandomDouble() )
PackItem( new ParagonChest( this.Name, treasureLevel ) );
else if ( (Map == Map.Felucca || Map == Map.Trammel) && TreasureMap.LootChance >= Utility.RandomDouble() )
PackItem( new TreasureMap( treasureLevel, Map ) );
}
// if they are controlled by a pseudoseer, attempt to reconnect:
if (this.NetState != null && !CreaturePossession.AttemptReturnToOriginalBody(this.NetState))
{
this.NetState.Dispose();
}
// find out whether most recent aggressor is in factions & how many heros their town has
// and give a 10-40% gold bonus accordingly
// NOTE: if it is desired to make this gold bonus go for anyone in a party with a faction
// member, and not just when a faction member specifically gets the kill shot,
// then this should be handled in the same place gold is boosted for Adventurer bonus (see below)
PlayerMobile slayer = this.LastKiller as PlayerMobile;
if (!HasBeenPseudoseerControlled // plug gold duping potential
&& !(this is PackLlama) // plug gold duping potential
&& !(this is PackHorse) // plug gold duping potential
&& slayer != null
&& (slayer.FactionPlayerState != null
&& slayer.FactionPlayerState.Faction != null))
{
//Console.WriteLine("slayer=" + slayer);
//Console.WriteLine("slayer.FactionPlayerState=" + slayer.FactionPlayerState);
//Console.WriteLine("slayer.FactionPlayerState.Faction=" + slayer.FactionPlayerState.Faction);
double extraGoldFraction = 0.1; // free extra 10% for being in factions
CommonwealthState owningCommonwealthState = slayer.FactionPlayerState.Faction.OwningCommonwealth.State;
if (owningCommonwealthState.Hero != null
&& (owningCommonwealthState.Hero.IsHome))
{
extraGoldFraction += 0.1; // extra 10% if their own hero is ok
}
foreach (TownHero capturedHero in owningCommonwealthState.CapturedHeroes)
{
extraGoldFraction += 0.1; // extra 10% for every captured hero
}
//Console.WriteLine("extraGoldFraction=" + extraGoldFraction);
//Console.WriteLine("before TotalGold=" + TotalGold);
PackGold((int)(this.TotalGold * extraGoldFraction));
//Console.WriteLine("after TotalGold=" + TotalGold);
}
if (IsAnimatedDead)
Effects.SendLocationEffect(Location, Map, 0x3728, 13, 1, 0x461, 4);
InhumanSpeech speechType = this.SpeechType;
CurrentWayPoint = null;
if (speechType != null && Speaks)
speechType.OnDeath(this);
return base.OnBeforeDeath();
}
private bool m_NoKillAwards;
public bool NoKillAwards
{
get { return m_NoKillAwards; }
set { m_NoKillAwards = value; }
}
public int ComputeBonusDamage(List<DamageEntry> list, Mobile m)
{
int bonus = 0;
for (int i = list.Count - 1; i >= 0; --i)
{
DamageEntry de = list[i];
if (de.Damager == m || !(de.Damager is BaseCreature))
continue;
BaseCreature bc = (BaseCreature)de.Damager;
Mobile master = null;
master = bc.GetMaster();
if (master == m)
bonus += de.DamageGiven;
}
return bonus;
}
public Mobile GetMaster()
{
if (Controlled && ControlMaster != null)
return ControlMaster;
else if (Summoned && SummonMaster != null)
return SummonMaster;
return null;
}
private class FKEntry
{
public Mobile m_Mobile;
public int m_Damage;
public FKEntry(Mobile m, int damage)
{
m_Mobile = m;
m_Damage = damage;
}
}
public static List<DamageStore> GetLootingRights(List<DamageEntry> damageEntries, int hitsMax)
{
List<DamageStore> rights = new List<DamageStore>();
for (int i = damageEntries.Count - 1; i >= 0; --i)
{
if (i >= damageEntries.Count)
continue;
DamageEntry de = damageEntries[i];
if (de.HasExpired)
{
damageEntries.RemoveAt(i);
continue;
}
int damage = de.DamageGiven;
List<DamageEntry> respList = de.Responsible;
if (respList != null)
{
for (int j = 0; j < respList.Count; ++j)
{
DamageEntry subEntry = respList[j];
Mobile master = subEntry.Damager;
if (master == null || master.Deleted || !master.Player)
continue;
bool needNewSubEntry = true;
for (int k = 0; needNewSubEntry && k < rights.Count; ++k)
{
DamageStore ds = rights[k];
if (ds.m_Mobile == master)
{
ds.m_Damage += subEntry.DamageGiven;
needNewSubEntry = false;
}
}
if (needNewSubEntry)
rights.Add(new DamageStore(master, subEntry.DamageGiven));
damage -= subEntry.DamageGiven;
}
}
Mobile m = de.Damager;
if (m == null || m.Deleted || !m.Player)
continue;
if (damage <= 0)
continue;
bool needNewEntry = true;
for (int j = 0; needNewEntry && j < rights.Count; ++j)
{
DamageStore ds = rights[j];
if (ds.m_Mobile == m)
{
ds.m_Damage += damage;
needNewEntry = false;
}
}
if (needNewEntry)
rights.Add(new DamageStore(m, damage));
}
if (rights.Count > 0)
{
rights[0].m_Damage = (int)(rights[0].m_Damage * 1.25); //This would be the first valid person attacking it. Gets a 25% bonus. Per 1/19/07 Five on Friday
if (rights.Count > 1)
rights.Sort(); //Sort by damage
int topDamage = rights[0].m_Damage;
int minDamage;
if (hitsMax >= 3000)
minDamage = topDamage / 16;
else if (hitsMax >= 1000)
minDamage = topDamage / 8;
else if (hitsMax >= 200)
minDamage = topDamage / 4;
else
minDamage = topDamage / 2;
for (int i = 0; i < rights.Count; ++i)
{
DamageStore ds = rights[i];
ds.m_HasRight = (ds.m_Damage >= minDamage);
}
}
return rights;
}
public virtual void OnKilledBy(Mobile mob)
{
if (m_Paragon && Paragon.CheckArtifactChance(mob, this))
Paragon.GiveArtifactTo(mob);
}
public override void OnDeath(Container c)
{
MeerMage.StopEffect(this, false);
if (IsBonded)
{
int sound = this.GetDeathSound();
if (sound >= 0)
Effects.PlaySound(this, this.Map, sound);
Warmode = false;
Poison = null;
Combatant = null;
Hits = 0;
Stam = 0;
Mana = 0;
IsDeadPet = true;
ControlTarget = ControlMaster;
ControlOrder = OrderType.Follow;
ProcessDeltaQueue();
SendIncomingPacket();
SendIncomingPacket();
List<AggressorInfo> aggressors = this.Aggressors;
for (int i = 0; i < aggressors.Count; ++i)
{
AggressorInfo info = aggressors[i];
if (info.Attacker.Combatant == this)
info.Attacker.Combatant = null;
}
List<AggressorInfo> aggressed = this.Aggressed;
for (int i = 0; i < aggressed.Count; ++i)
{
AggressorInfo info = aggressed[i];
if (info.Defender.Combatant == this)
info.Defender.Combatant = null;
}
Mobile owner = this.ControlMaster;
if (owner == null || owner.Deleted || owner.Map != this.Map || !owner.InRange(this, 12) || !this.CanSee(owner) || !this.InLOS(owner))
{
if (this.OwnerAbandonTime == DateTime.MinValue)
this.OwnerAbandonTime = DateTime.Now;
}
else
{
this.OwnerAbandonTime = DateTime.MinValue;
}
CheckStatTimers();
}
else
{
if (!Summoned && !m_NoKillAwards)
{
int totalFame = Fame / 100;
int totalKarma = -Karma / 100;
if (Map == Map.Felucca)
{
totalFame += ((totalFame / 10) * 3);
totalKarma += ((totalKarma / 10) * 3);
}
List<DamageStore> list = GetLootingRights(this.DamageEntries, this.HitsMax);
List<Mobile> titles = new List<Mobile>();
List<int> fame = new List<int>();
List<int> karma = new List<int>();
bool givenQuestKill = false;
bool givenFactionKill = false;
for (int i = 0; i < list.Count; ++i)
{
DamageStore ds = list[i];
if (!ds.m_HasRight)
continue;
Party party = Engines.PartySystem.Party.Get(ds.m_Mobile);
//In Party
if (party != null)
{
int nearbyPartyMembers = 0;
//Determine Nearby Party Members
for (int j = 0; j < party.Members.Count; ++j)
{
PartyMemberInfo info = party.Members[j] as PartyMemberInfo;
//If Party Member is Valid and Within Maximum Distance of Corpse for Fame/Karma Sharing
if (info != null && info.Mobile != null && info.Mobile.GetDistanceToSqrt(this) <= FeatureList.FameKarma.PartyFameKarmaSharingDisance)
{
nearbyPartyMembers++;
}
}
//Set to 1 if Not Valid (Won't Be Distributed Anyways)
if (nearbyPartyMembers <= 0)
{
nearbyPartyMembers = 1;
}
int divedFame = totalFame / nearbyPartyMembers;
int divedKarma = totalKarma / nearbyPartyMembers;
//Divide Up Fame and Karma
for (int j = 0; j < party.Members.Count; ++j)
{
PartyMemberInfo info = party.Members[j] as PartyMemberInfo;
//If Party Member is Valid and Within Maximum Distance of Corpse for Fame/Karma Sharing
if (info != null && info.Mobile != null && info.Mobile.GetDistanceToSqrt(this) <= FeatureList.FameKarma.PartyFameKarmaSharingDisance)
{
int index = titles.IndexOf(info.Mobile);
if (index == -1)
{
titles.Add(info.Mobile);
fame.Add(divedFame);
karma.Add(divedKarma);
}
else
{
fame[index] += divedFame;
karma[index] += divedKarma;
}
}
}
}