All pastes #38325 Raw Edit

Anonymous

public text v1 · immutable
#38325 ·published 2006-01-24 11:00 UTC
rendered paste body
Index: D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/L2Summon.java
===================================================================
--- D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/L2Summon.java	(revision 2173)
+++ D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/L2Summon.java	(working copy)
@@ -196,6 +196,82 @@
 	
 	public synchronized void doDie(L2Character killer)
     {
+		// if a pet is killed by a player or another player's pet/summon,
+		// treat as if the player killed the pet's owner, in terms of pvp 
+		// flags, PK status and Karma.
+		// do NOT increase PvP or PK count when killing pets!!!
+		if (killer != null)
+		{
+			if ( !ZoneManager.getInstance().checkIfInZonePvP(this) )
+			{
+				// if killed by a Summon, we should calculate with the owner PcInstance
+				if(killer instanceof L2Summon)
+				{
+					killer = ((L2Summon)killer).getOwner();
+				}
+                if(getOwner().getClan()==null ||
+                		(killer instanceof L2PcInstance && ((L2PcInstance)killer).getClan()==null )|| 
+                		(killer instanceof L2PcInstance && !(((L2PcInstance)killer).getClan().isAtWarWith(getClanId()) ) && ((L2PcInstance)killer).getWantsPeace() == 0 && getWantsPeace() == 0))
+                {
+				// karma gain/loss is only done outside of a pvpzone, BUT, items can still drop in one!
+				if ( killer.getObjectId() != this.getObjectId())
+				{
+					// Calculate L2PcInstance attacker Karma increase
+					if (killer instanceof L2PcInstance )
+					{
+		        		L2PcInstance pk = (L2PcInstance) killer;
+
+						// Check if the L2PcInstance killed wasn't PvP Flagged
+						if (this.getPvpFlag() == 0 && this.getOwner().getPvpFlag() == 0 )
+						{
+							// Check if the owner of this killed summon haven't Karma
+							if (this.getKarma() == 0 && this.getOwner().getKarma() == 0)
+							{
+								// Get attacker level and PK counter
+								int pkLVL = pk.getLevel();
+								int pkPKCount = pk.getPkKills();
+
+								int targLVL = this.getLevel();
+								int baseKarma = Config.KARMA_MIN_KARMA;
+								int newKarma = baseKarma;
+								int karmaLimit = Config.KARMA_MAX_KARMA;
+
+								// Check if the attacker has a PK counter greater than 0
+								double pkCountMulti = 0;
+								if ( pkPKCount > 0 )
+									pkCountMulti = pkPKCount / 2.0;
+								else
+									pkCountMulti = 1;
+								if ( pkCountMulti < 1 ) pkCountMulti = 1;
+
+								// Calculate the level difference Multiplier between attacker and killed L2PcInstance
+								double lvlDiffMulti = 0.0;
+								if ( pkLVL > targLVL )
+									lvlDiffMulti = ((double)pkLVL) / targLVL;
+								else
+									lvlDiffMulti = 1.0;
+								if ( lvlDiffMulti < 1 ) lvlDiffMulti = 1.0;
+
+								// Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti
+								newKarma = (int)(newKarma*pkCountMulti*lvlDiffMulti);
+
+								// Make sure newKarma is less than karmaLimit and higher than baseKarma
+								if ( newKarma < baseKarma ) newKarma = baseKarma;
+								if ( newKarma > karmaLimit ) newKarma = karmaLimit;
+
+								// Add karma to attacker and increase its PK counter
+								pk.increaseKarma(newKarma);
+
+								// Send a Server->Client UserInfo packet to attacker with its Karma and PK Counter
+								pk.sendPacket(new UserInfo(pk));
+							}
+						}
+					}
+				}
+            }
+			}
+		}
+		
         DecayTask.getInstance().addDecayTask(this);
 		super.doDie(killer);
 	}
@@ -367,4 +443,51 @@
 	{
 		super.useMagic(skill);
 	}
+	
+	/**
+	 * Reduce the current HP of the L2PcInstance.<BR><BR>
+	 *
+	 * <B><U> Actions</U> :</B><BR><BR>
+	 * <li>Reduce the current HP of the L2PcInstance </li>
+	 * <li>If necessary, stand up the L2PcInstance and PvP Flag the attacker </li>
+	 * <li>Send a System Message to the L2PcInstance : S1_GAVE_YOU_S2_DMG </li><BR><BR>
+	 *
+	 * @param i The HP decrease value
+	 * @param attacker The L2Character who attacks
+	 *
+	 */
+	public void reduceCurrentHp(double i, L2Character attacker)
+	{
+		// Check if the L2Summon isn't Invulnerable
+		if (this.isInvul())
+			return;
+		
+		//hotfix: Summons can not lose HP intown via PvP, unless the town is a PvP zone in config
+		//todo: Better fix is to ensure 100%that such inappropriate attacks are prevented altogether.
+        if (attacker != null && attacker != this && (attacker instanceof L2PcInstance || attacker instanceof L2Summon)
+ 		{
+  			// Check if the attacked player is in a peace zone. 
+        	// only reds can be attacked in peace zones.
+   			L2Zone zone = ZoneManager.getInstance().getZone(L2ZoneType.getZoneTypeName(L2ZoneType.ZoneType.Peace), getX(), getY()); //checking if char is in peace zone
+   			if (zone != null && getKarma() == 0 )
+   				return;
+        	
+   			zone = ZoneManager.getInstance().getZone(L2ZoneType.getZoneTypeName(L2ZoneType.ZoneType.Town), getX(), getY()); //checking if char is in town zone
+        	if (zone != null && getKarma() == 0 && Config.ZONE_TOWN == 0)
+        		return;
+  		}
+
+		// Reduce the current HP of the L2PcInstance
+		super.reduceCurrentHp(i, attacker);
+
+		// Check if the L2Summon isn't dead
+		if (!isDead())
+		{
+			// Flag the attacker if it's a L2PcInstance outside a PvP area
+			if (attacker != null && attacker instanceof L2PcInstance)
+				((L2PcInstance)attacker).checkPvP(this);
+			if (attacker != null && attacker instanceof L2Summon)
+				((L2Summon)attacker).getOwner().checkPvP(this);
+		}
+	}
 }
Index: D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/actor/pc/PcStat.java
===================================================================
--- D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/actor/pc/PcStat.java	(revision 2173)
+++ D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/actor/pc/PcStat.java	(working copy)
@@ -37,7 +37,7 @@
             int karmaRemove = value;
             karmaRemove /= Config.KARMA_XP_DIVIDER;
 
-            if (karmaRemove < 0) karmaRemove = 0;
+            if (karmaRemove <= 0) karmaRemove = 1;
             if (karmaRemove > getActiveChar().getKarma()) karmaRemove = getActiveChar().getKarma();
             getActiveChar().setKarma(getActiveChar().getKarma() - karmaRemove);
         }
Index: D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/L2PcInstance.java
===================================================================
--- D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/L2PcInstance.java	(revision 2173)
+++ D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/L2PcInstance.java	(working copy)
@@ -2326,6 +2326,21 @@
 		// Check if the L2PcInstance isn't Invulnerable
 		if (this.isInvul())
 			return;
+		
+		//hotfix: Players can not lose HP intown via PvP, unless the town is a PvP zone in config
+		//todo: Better fix is to ensure 100%that such inappropriate attacks are prevented altogether.
+        if (attacker != null && attacker != this && (attacker instanceof L2PcInstance || attacker instanceof L2Summon)
+ 		{
+  			// Check if the attacked player is in a peace zone. 
+        	// only reds can be attacked in peace zones.
+   			L2Zone zone = ZoneManager.getInstance().getZone(L2ZoneType.getZoneTypeName(L2ZoneType.ZoneType.Peace), getX(), getY()); //checking if char is in peace zone
+   			if (zone != null && getKarma() == 0 )
+   				return;
+        	
+   			zone = ZoneManager.getInstance().getZone(L2ZoneType.getZoneTypeName(L2ZoneType.ZoneType.Town), getX(), getY()); //checking if char is in town zone
+        	if (zone != null && getKarma() == 0 && Config.ZONE_TOWN == 0)
+        		return;
+  		}
 
         // Check and calculate transfered damage
         if (attacker != null && attacker != this)
@@ -2400,16 +2415,17 @@
 	 *
 	 */
 	public void doDie(L2Character killer)
-	{
+	{	
+		int lostXP=0;	//useful for new karma reduction...Team Olympus.
 
 		// Reduce the Experience of the L2PcInstance in function of the calculated Death Penalty
 		if (Config.ALT_GAME_DELEVEL)
 		{
 			if (!ZoneManager.getInstance().checkIfInZonePvP(this) && getSkillLevel(L2Skill.SKILL_LUCKY) < 0)
                 if(killer != null && killer instanceof L2PcInstance && ((L2PcInstance)killer).getClan() != null && this.getClan() != null && this.getClan().isAtWarWith(((L2PcInstance)killer).getClanId()))
-					deathPenalty(true);
+                	lostXP = deathPenalty(true);
                 else
-                    deathPenalty(false);
+                	lostXP = deathPenalty(false);
 		}
 
 
@@ -2440,7 +2456,7 @@
                 if(getClan()==null ||(killer instanceof L2PcInstance && ((L2PcInstance)killer).getClan()==null )|| (killer instanceof L2PcInstance && !(((L2PcInstance)killer).getClan().isAtWarWith(getClanId()) ) && ((L2PcInstance)killer).getWantsPeace() == 0 && getWantsPeace() == 0))
                 {
 				// karma gain/loss is only done outside of a pvpzone, BUT, items can still drop in one!
-				if ( killer.getObjectId() != this.getObjectId() )
+				if ( killer.getObjectId() != this.getObjectId())
 				{
 					// if killed by a Summon, we should calculate with the owner PcInstance
 					if(killer instanceof L2Summon)
@@ -2468,24 +2484,23 @@
 								int karmaLimit = Config.KARMA_MAX_KARMA;
 
 								// Check if the attacker has a PK counter greater than 0
-								int pkCountMulti = 0;
+								double pkCountMulti = 0;
 								if ( pkPKCount > 0 )
-									pkCountMulti = pkPKCount / 2;
+									pkCountMulti = pkPKCount / 2.0;
 								else
 									pkCountMulti = 1;
 								if ( pkCountMulti < 1 ) pkCountMulti = 1;
 
 								// Calculate the level difference Multiplier between attacker and killed L2PcInstance
-								int lvlDiffMulti = 0;
+								double lvlDiffMulti = 0.0;
 								if ( pkLVL > targLVL )
-									lvlDiffMulti = pkLVL / targLVL;
+									lvlDiffMulti = ((double)pkLVL) / targLVL;
 								else
-									lvlDiffMulti = 1;
-								if ( lvlDiffMulti < 1 ) lvlDiffMulti = 1;
+									lvlDiffMulti = 1.0;
+								if ( lvlDiffMulti < 1 ) lvlDiffMulti = 1.0;
 
 								// Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti
-								newKarma *= pkCountMulti;
-								newKarma *= lvlDiffMulti;
+								newKarma = (int)(newKarma*pkCountMulti*lvlDiffMulti);
 
 								// Make sure newKarma is less than karmaLimit and higher than baseKarma
 								if ( newKarma < baseKarma ) newKarma = baseKarma;
@@ -2522,34 +2537,46 @@
 							pk.sendPacket(new UserInfo(pk));
 						}
 					}
+				}
 
-
 					// KARMA LOSS FOR DEAD PLAYER
-					// when a PKer gets killed by another player or a L2MonsterInstance, it loseq a certain amount of Karma based on their level.
-					// this (with defaults) results in a level 1 losing about ~2 karma per death, and a lvl 70 loses about 11760 karma per death...
-					// You lose karma as long as you were not in a pvp zone and you did not kill urself.
+				//new karma loss code by team Olympus:
+				//Lose karma as a fraction of the XP you lost upon dying (ignoring how much 
+				//of that XP might be returned by ressurection).
+				//NOTE: This also provides an elegant solution for no karma loss in PvP zones
+				//and for limitted karma loss in sieges (as specified in discussions from retail).
 					if ( this.getKarma() > 0 )
 					{
+						// since the new formula is dependent on XP loss, leave the old formula
+						//effective when the server's options dictate no XP loss.
+						if (Config.ALT_GAME_DELEVEL)
+						{
+							int karmaLost = lostXP/260;		//this 260 seems to work quite accurately.
+							if ( karmaLost <= 0 ) karmaLost = 1;
+							// Decrease Karma of the L2PcInstance and Send it a Server->Client StatusUpdate packet with Karma and PvP Flag if necessary
+							this.redreaseKarma(karmaLost);
+						}
+						else
+						{
+							// this formula seems to work relatively well:
+							// baseKarma * thisLVL * (thisLVL/100)
+							int finalKarma = 0;
+							double baseKarmaLost = Config.KARMA_LOST_BASE;
+							double karmaLost = baseKarmaLost;
+							double thisLVL = this.getLevel();
+							double tempMulti = thisLVL / 100;
 
-						// this formula seems to work relatively well:
-						// baseKarma * thisLVL * (thisLVL/100)
-						int finalKarma = 0;
-						double baseKarmaLost = Config.KARMA_LOST_BASE;
-						double karmaLost = baseKarmaLost;
-						double thisLVL = this.getLevel();
-						double tempMulti = thisLVL / 100;
 
+							// Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti
+							karmaLost *= thisLVL; // multiply by char lvl
+							karmaLost *= tempMulti; // divide by 0.charLVL
+							karmaLost = Math.round(karmaLost);
+							finalKarma = (int)karmaLost;
+							if ( finalKarma < 0 ) finalKarma = 1;
 
-						// Calculate the new Karma of the attacker : newKarma = baseKarma*pkCountMulti*lvlDiffMulti
-						karmaLost *= thisLVL; // multiply by char lvl
-						karmaLost *= tempMulti; // divide by 0.charLVL
-						karmaLost = Math.round(karmaLost);
-						finalKarma = (int)karmaLost;
-						if ( finalKarma < 0 ) finalKarma = 1;
-
-						// Decrease Karma of the L2PcInstance and Send it a Server->Client StatusUpdate packet with Karma and PvP Flag if necessary
-						this.redreaseKarma(finalKarma);
-
+							// Decrease Karma of the L2PcInstance and Send it a Server->Client StatusUpdate packet with Karma and PvP Flag if necessary
+							this.redreaseKarma(finalKarma);
+						}
 					}
 				}
                 }
@@ -2576,6 +2603,7 @@
 			Random rand = new Random();
 			boolean dropGM = Config.KARMA_DROP_GM; // do GMs drop gear or not? true = yes, false = no
 			int dropPKLim = Config.KARMA_PK_LIMIT; // you do not drop items if you have less than dropPKLim PKs
+		    int droptype = 0;
 
 			if ( thisKarma > 0 && !(this.getPkKills() < dropPKLim && killer instanceof L2NpcInstance) && !ZoneManager.getInstance().checkIfInZonePvP(this))
 			{
@@ -2583,7 +2611,7 @@
 				// Get drop settings
 				//boolean gmStat = false; // keeps track of if player is a gm or not and if they are able to drop items
 				int dropConstant = Config.KARMA_DROP_CONSTANT; // a constant used for drop chance calculation
-				//int dropLim = Config.KARMA_DROP_ITEM_LIMIT; // dropLim items dropped at most, equipped or unequipped doesnt matter.
+				int dropLim = Config.KARMA_DROP_ITEM_LIMIT; // dropLim items dropped at most, equipped or unequipped doesnt matter.
 				//int randDropLim = Config.KARMA_RANDOM_DROP_LOCATION_LIMIT; // max amount of x/y units a dropped item may be placed
 				double dropRate = Config.RATE_DROP_EQUIPMENT; // drop rate...
 				double dropChanceINIT = Config.KARMA_DROPCHANCE_INITIAL_CHECK; // dropChanceINIT% drop chance, initial check
@@ -2592,7 +2620,7 @@
 				double dropChanceUEQUIP = Config.KARMA_DROPCHANCE_UNEQUIPPED_ITEMS; // dropChanceUEQUIP% chance of dropping an equipped item, after initial check of dropChanceINIT
 
 
-			  //if player hav karma and pkkils>4 and chance of drop 70%
+			  //if player has karma and pkkils>4 and chance of drop 70% (using default settings)
 			  droppercent = (int)(dropChanceINIT + getKarma()/dropConstant*(100-dropChanceINIT));
 			  droppercent *= dropRate;
 			  dropitems = (int)dropChanceUEQUIP;
@@ -2600,106 +2628,124 @@
 			  dropequipweap = (int)dropChanceEQUIP_WEAP;
 			  count = 0;
 			  while (!(isGM() && !dropGM) &&
-			     this.getPkKills() >=  dropPKLim  && rand.nextInt(100)<droppercent){
-			    int droptype = rand.nextInt(dropitems+dropequip+dropequipweap);
-			    _log.warning(getName()+" have karma and will be lose of items: droptype="+droptype);
-			    //droptype
-				count = 0;
-				for (L2ItemInstance itemdrop : _inventory.getItems()){
-				    if (itemdrop.getItemId()!=57 && L2Item.TYPE2_QUEST != itemdrop.getItem().getType2() &&
-				    !noDropList.contains(itemdrop.getItemId()) && !petList.contains(itemdrop.getItemId()))
-				      if ((!itemdrop.isEquipped() && droptype < dropitems) ||
-					(itemdrop.isEquipped() && itemdrop.getItem().getType2() != L2Item.TYPE2_WEAPON && droptype < (dropitems + dropequip)) ||
-					(itemdrop.isEquipped() && itemdrop.getItem().getType2() == L2Item.TYPE2_WEAPON && droptype >= (dropitems + dropequip)))
-					count++;
+			     this.getPkKills() >=  dropPKLim  && rand.nextInt(100)<droppercent && count <= dropLim){
+			    //first check if the person is to drop a weapon
+           	 	int chance = rand.nextInt(dropitems+dropequip+dropequipweap); 
+           	 	if (chance<dropequipweap)
+           	 		//if yes, find and drop the equipped weapon.
+           	 		droptype = 1;
+           	 	// next, check if another equipped weapon is to be dropped.
+           	 	else if(chance<(dropequipweap+dropequip))
+           	 		//if yes, find and drop one equipped item
+           	 		droptype = 2;
+           	 	else //if(chance<(dropequiweap+dropequip+dropitems))
+           	 		//find and drop an item...(exclude quest items and adena)
+           	 		droptype = 3;
+				_log.warning(getName()+" have karma and will be lose of items: droptype="+droptype);
+				boolean itemFound = false;// initialize
+				while ((!itemFound) && (droptype < 3))
+				{
+
+       	 			for (L2ItemInstance itemdrop : _inventory.getItems())
+       	 			{
+       	 				//if drop = 1 and no item drop 2
+       	 				//if drop = 2 and no item check 1 if not drop 3
+       	 				//id drop = 3 and no check 1 if not check 2 if not NO DROP
+       	 				if (itemdrop.getItemId()!=57 && L2Item.TYPE2_QUEST != itemdrop.getItem().getType2() &&
+       	 					!noDropList.contains(itemdrop.getItemId()) && !petList.contains(itemdrop.getItemId()))
+       	 					if ((!itemdrop.isEquipped() && droptype == 3) ||
+       	 						(itemdrop.isEquipped() && itemdrop.getItem().getType2() != L2Item.TYPE2_WEAPON && droptype == 2) ||
+       	 						(itemdrop.isEquipped() && itemdrop.getItem().getType2() == L2Item.TYPE2_WEAPON && droptype == 1))
+       	 					{
+       	 						if (itemdrop.isEquipped())
+       	 							this.getInventory().unEquipItemInSlotAndRecord(itemdrop.getEquipSlot());
+       	 						int quantity = rand.nextInt(itemdrop.getCount())+1;
+       	 						itemdrop = this.getInventory().dropItem(itemdrop,quantity);
+       	 						itemdrop.dropMe(this, this.getClientX(), this.getClientY(), this.getClientZ() + 20);
+       	 						SystemMessage sm = new SystemMessage(298);
+       	 						sm.addItemName(itemdrop.getItemId());
+       	 						this.sendPacket(sm);
+       	 						InventoryUpdate iu = new InventoryUpdate(); // for inventory updating
+       	 						iu.addRemovedItem(itemdrop);
+       	 						this.sendPacket(iu);
+       	 						_log.warning(getName()+" have karma and dropped id="+itemdrop.getItemId()+", count="+itemdrop.getCount());
+       	 						itemFound = true;
+       	 						count++;
+       	 						break;
+       	 					}
+       	 			}
+       	 			//if no item can be found for this droptype, try the next droptype 
+       	 			//(the next most rare type after the one originally selected - see comments above)
+       	 			if (!itemFound)
+       	 				droptype ++;
 				}
-				// _log.warning("count:"+count);
-				//if have items to drop
-				if (count>0){
-				    int itemnrtodrop = rand.nextInt(count);
-				    count = 0;
-				  for (L2ItemInstance itemdrop : _inventory.getItems()){
-				    if (itemdrop.getItemId()!=57 && L2Item.TYPE2_QUEST != itemdrop.getItem().getType2() &&
-				    !noDropList.contains(itemdrop.getItemId()) && !petList.contains(itemdrop.getItemId()))
-				      if ((!itemdrop.isEquipped() && droptype < dropitems) ||
-					(itemdrop.isEquipped() && itemdrop.getItem().getType2() != L2Item.TYPE2_WEAPON && droptype < (dropitems + dropequip)) ||
-					(itemdrop.isEquipped() && itemdrop.getItem().getType2() == L2Item.TYPE2_WEAPON && droptype >= (dropitems + dropequip)))
-				      {
-					if (count == itemnrtodrop){
-					    if (itemdrop.isEquipped())
-						this.getInventory().unEquipItemInSlotAndRecord(itemdrop.getEquipSlot());
-					    itemdrop = this.getInventory().dropItem(itemdrop,itemdrop.getCount());
-					    itemdrop.dropMe(this, this.getClientX(), this.getClientY(), this.getClientZ() + 20);
-					    SystemMessage sm = new SystemMessage(298);
-					    sm.addItemName(itemdrop.getItemId());
-					    this.sendPacket(sm);
-					    InventoryUpdate iu = new InventoryUpdate(); // for inventory updating
-					    iu.addRemovedItem(itemdrop);
-	    				    this.sendPacket(iu);
-					    _log.warning(getName()+" have karma and dropped id="+itemdrop.getItemId()+", count="+itemdrop.getCount());
 
-					    break;
-					}
-					count++;
-				      }
-				  }
-				}
-			    droppercent /= 1.5;
+			    droppercent /= 1.5;   
 			  }
 			} else if (!ZoneManager.getInstance().checkIfInZonePvP(this) || !isFestivalParticipant() ){
 			  //if player haven't karma and lvl>4 and chance of drop 50%
 			  droppercent = Config.PLAYER_RATE_DROP;
 			  dropequip = Config.PLAYER_RATE_DROP_EQUIP;
 			  dropequipweap = Config.PLAYER_RATE_DROP_EQUIP_WEAPON;
-            		  dropitems = Config.PLAYER_RATE_DROP_ITEM;
-			  count = 0;
-			  while (!(isGM() && !dropGM) && killer instanceof L2NpcInstance
-			     && getLevel()>4 && rand.nextInt(100)<droppercent){
-			    int droptype = rand.nextInt(dropitems+dropequip+dropequipweap);
-			    _log.warning(getName()+" killed by npcid="+((L2NpcInstance)killer).getNpcId()+" and will be lose of items: droptype="+droptype);
-			    //droptype
-				count = 0;
-				for (L2ItemInstance itemdrop : _inventory.getItems()){
-				    if (itemdrop.getItemId()!=57 && L2Item.TYPE2_QUEST != itemdrop.getItem().getType2() &&
+			  dropitems = Config.PLAYER_RATE_DROP_ITEM;
+			  // whites should ONLY drop 1 item.
+             if(!(isGM() && !dropGM) && killer instanceof L2NpcInstance
+			     && getLevel()>4 && rand.nextInt(100)<droppercent)
+             {
+   			    _log.warning(getName()+" killed by npcid="+((L2NpcInstance)killer).getNpcId()+" and will be lose of items: droptype="+droptype);
+            	 //first check if the person is to drop a weapon
+            	 int chance = rand.nextInt(dropitems+dropequip+dropequipweap); 
+            	 if (chance<dropequipweap)
+            		 //if yes, find and drop the equipped weapon.
+            		 droptype = 1;
+            	 // next, check if another equipped weapon is to be dropped.
+            	 else if(chance<(dropequipweap+dropequip))
+            		 //if yes, find and drop one equipped item
+            		 droptype = 2;
+            	 else //if(chance<(dropequiweap+dropequip+dropitems))
+            		 //find and drop an item...(exclude quest items and adena)
+            		 droptype = 3;
+             
+            	 boolean itemFound = false;// initialize
+            	 while ((!itemFound) && (droptype < 3))
+            	 {
+				for (L2ItemInstance itemdrop : _inventory.getItems())
+				{
+				    //make a list of all weapons dropable
+					//make a list of all worn dropable
+					//make a list of all inventory dropable
+					
+					//if drop = 1 and no item drop 2
+					//if drop = 2 and no item check 1 if not drop 3
+					//id drop = 3 and no check 1 if not check 2 if not NO DROP
+					if (droptype == 3 && itemdrop.getItemId()!=57 && L2Item.TYPE2_QUEST != itemdrop.getItem().getType2() &&
 				    !noDropList.contains(itemdrop.getItemId()) && !petList.contains(itemdrop.getItemId()))
-				      if ((!itemdrop.isEquipped() && droptype < dropitems) ||
-					(itemdrop.isEquipped() && itemdrop.getItem().getType2() != L2Item.TYPE2_WEAPON && droptype < (dropitems + dropequip)) ||
-					(itemdrop.isEquipped() && itemdrop.getItem().getType2() == L2Item.TYPE2_WEAPON && droptype >= (dropitems + dropequip)))
-					count++;
-				}
-				 //_log.warning("count:"+count);
-				//if have items to drop
-				if (count>0){
-				    int itemnrtodrop = rand.nextInt(count);
-				    count = 0;
-				  for (L2ItemInstance itemdrop : _inventory.getItems()){
-				    if (itemdrop.getItemId()!=57 && L2Item.TYPE2_QUEST != itemdrop.getItem().getType2() &&
-				    !noDropList.contains(itemdrop.getItemId()) && !petList.contains(itemdrop.getItemId()))
-				      if ((!itemdrop.isEquipped() && droptype < dropitems) ||
-					(itemdrop.isEquipped() && itemdrop.getItem().getType2() != L2Item.TYPE2_WEAPON && droptype < (dropitems + dropequip)) ||
-					(itemdrop.isEquipped() && itemdrop.getItem().getType2() == L2Item.TYPE2_WEAPON && droptype >= (dropitems + dropequip)))
+				    if ((!itemdrop.isEquipped() && droptype == 3) ||
+					(itemdrop.isEquipped() && itemdrop.getItem().getType2() != L2Item.TYPE2_WEAPON && droptype == 2) ||
+					(itemdrop.isEquipped() && itemdrop.getItem().getType2() == L2Item.TYPE2_WEAPON && droptype == 1))
 				      {
-					if (count == itemnrtodrop){
-					    if (itemdrop.isEquipped())
-						this.getInventory().unEquipItemInSlotAndRecord(itemdrop.getEquipSlot());
-					    itemdrop = this.getInventory().dropItem(itemdrop,itemdrop.getCount());
-					    itemdrop.dropMe(this, this.getClientX(), this.getClientY(), this.getClientZ() + 20);
-					    SystemMessage sm = new SystemMessage(298);
-					    sm.addItemName(itemdrop.getItemId());
-					    this.sendPacket(sm);
-					    InventoryUpdate iu = new InventoryUpdate(); // for inventory updating
-					    iu.addRemovedItem(itemdrop);
-	    				    this.sendPacket(iu);
-					    _log.warning(getName()+" died and dropped id="+itemdrop.getItemId()+", count="+itemdrop.getCount());
-					    break;
-					}
-					count++;
+						    if (itemdrop.isEquipped())
+								this.getInventory().unEquipItemInSlotAndRecord(itemdrop.getEquipSlot());
+						    int quantity = rand.nextInt(itemdrop.getCount())+1;
+							itemdrop = this.getInventory().dropItem(itemdrop,quantity);
+							itemdrop.dropMe(this, this.getClientX(), this.getClientY(), this.getClientZ() + 20);
+							SystemMessage sm = new SystemMessage(298);
+							sm.addItemName(itemdrop.getItemId());
+							this.sendPacket(sm);
+							InventoryUpdate iu = new InventoryUpdate(); // for inventory updating
+							iu.addRemovedItem(itemdrop);
+			    			this.sendPacket(iu);
+							_log.warning(getName()+" died and dropped id="+itemdrop.getItemId()+", count="+quantity);
+							itemFound = true;
+							break;
 				      }
-				  }
 				}
-			    droppercent /= 5;
-			  }
-			}
+					//if no item can be found for this droptype, try the next droptype 
+					//(the next most rare type after the one originally selected - see comments above)
+					if (!itemFound)
+						droptype ++;
+            	 }
+             }
 		}
 
 		// Set the PvP Flag of the L2PcInstance
@@ -2760,9 +2806,9 @@
 	 * <li>Set the value of _expBeforeDeath </li>
 	 * <li>Set the new Experience value of the L2PcInstance and Decrease its level if necessary </li>
 	 * <li>Send a Server->Client StatusUpdate packet with its new Experience </li><BR><BR>
-	 *
+	 * <li>return the actual XP lost amount.
 	 */
-	public void deathPenalty(boolean atwar)
+	public int deathPenalty(boolean atwar)
     {
 	    // TODO Need Correct Penalty
 
@@ -2784,6 +2830,8 @@
 
 		// Set the new Experience value of the L2PcInstance
         getStat().addExp(-lostExp);
+        
+        return lostExp;
 	}
 
 
Index: D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/L2Character.java
===================================================================
--- D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/L2Character.java	(revision 2173)
+++ D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/model/L2Character.java	(working copy)
@@ -4148,9 +4148,12 @@
                    player.setAttackingChar(this);
                    player.setAttackingCharSkill(skill);
                    
-                   if(this instanceof L2PcInstance)
+                   if(this instanceof L2PcInstance || this instanceof L2Summon)
                    {
-                       L2PcInstance activeChar = (L2PcInstance) this;
+                	   if (this instanceof L2PcInstance)
+                		   L2PcInstance activeChar = (L2PcInstance) this;
+                	   else //if (this instanceof L2Summon)
+                		   L2PcInstance activeChar = (L2PcInstance) this.getOwner();
                        
                        // Check for PvP Flagging / Drawing Aggro
                        if (skill.isOffensive())
Index: D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/skills/Formulas.java
===================================================================
--- D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/skills/Formulas.java	(revision 2173)
+++ D:/Source/trunk/L2_Gameserver/java/net/sf/l2j/gameserver/skills/Formulas.java	(working copy)
@@ -1139,14 +1139,19 @@
 		{
     	case STUN:
     		// For normal Stun Attack, with skillType = STUN
-		pAtk = player.getPAtk(target);
-		pDef = target.getPDef(player);
-		pDef = target.calcStat(Stats.STUN_RES,pDef,target,null);
-		value = 30 * 100 + (int)(70 * 100 * ((float)skill.getLevel()/maxLevel));
-		if (pDef > 0 && pAtk > 0)
-		    value *= 0.6 * pAtk/pDef;
-        	modifier    = 100 * target.getCON()/30;
-    		break;
+    		int basechance = 50;
+    		int perLevelBonus = 1;
+    		if (skill.getId() == 92)  //Shield stun is stronger (only pure stun skill)
+    		{
+    			basechance = 80;
+    			perLevelBonus = 2;
+    		}
+    		pDef = target.calcStat(Stats.STUN_RES,0,target,null);
+    		value = 750 * (basechance + perLevelBonus * skill.getLevel());
+    		modifier = target.getLevel()*(target.getCON() + pDef);
+    		// CHANCE to stun gets no modifier from shots, whatsoever.
+    		//stun+damage skills get a modifier in the damage part ONLY.
+    		ssmodifier = 1;
     	case CONFUSION:
     	case MUTE:
     	case PARALYZE:
@@ -1178,18 +1183,17 @@
         	modifier    = 100 * target.getDEX()/30;
     		break;
     	default:
-    		// For normal Stun attack with skillType = PDAM
-        	pAtk = (int)skill.getPower();
-		pDef = target.getPDef(player);
-		pDef = target.calcStat(Stats.STUN_RES,pDef,target,null);
-//		value = 30 * 100 + (int)(70 * 100 * ((float)skill.getLevel()/maxLevel));
-		value = 100 * 100;
-		if (pDef > 0 && pAtk > 0)
-		    value *= 0.6 * pAtk/pDef;
-        	modifier    = 100 * target.getCON()/30;
-    		break;
+            basechance = 50;
+        	perLevelBonus = 1;
+        	pDef = target.calcStat(Stats.STUN_RES,0,target,null);
+        	value = 750 * (basechance + perLevelBonus * skill.getLevel());
+        	modifier = target.getLevel()*(target.getCON() + pDef);
+        	//CHANCE to stun gets no modifier from shots, whatsoever.
+        	//stun+damage skills get a modifier in the damage part ONLY.
+        	ssmodifier = 1;
+        	break;
 		}
-
+    		
         if (modifier == 0)
         {
             _log.warning("Name: "+target.getName()+" has bad base stat value. Fix datapack or notify dp ppl");