Noticias:

No tienes permiso para ver los enlaces. Para poder verlos Registrate o Conectate.

Menú Principal

Clan Stronghold Npc

Iniciado por Jerry, Ago 02, 2025, 08:08 PM

Tema anterior - Siguiente tema

Jerry

### Eclipse Workspace Patch 1.0
#P Orionwins
diff --git src/Base/ClanStrongold/ClanStrongholdDeviceSpawner.java src/Base/ClanStrongold/ClanStrongholdDeviceSpawner.java
new file mode 100644
index 0000000..e7d149a
--- /dev/null
+++ src/Base/ClanStrongold/ClanStrongholdDeviceSpawner.java
@@ -0,0 +1,187 @@
+package Base.ClanStrongold;
+
+import l2jwins.game.datatables.sql.NpcTable;
+import l2jwins.game.datatables.sql.SpawnTable;
+import l2jwins.game.model.actor.instance.L2NpcInstance;
+import l2jwins.game.model.spawn.L2Spawn;
+import l2jwins.game.templates.L2NpcTemplate;
+
+#Author Terius
+public class ClanStrongholdDeviceSpawner
+{
+	
+	private static final int CLAN_STRONGHOLD_DEVICE = 34156;
+	private static final int[][] _mobLoc =
+	{
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			20861,
+			117304,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			23739,
+			119992,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			23741,
+			117379,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			20636,
+			119935,
+			-12089,
+			243
+		},
+		
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			20875,
+			111002,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			14566,
+			111071,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			11739,
+			108219,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			11535,
+			119947,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			89382,
+			106388,
+			-3208,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			82701,
+			109007,
+			-3151,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			91746,
+			112823,
+			-2919,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			87909,
+			120040,
+			-3062,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			52484,
+			-79491,
+			-3117,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			20870,
+			108369,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			23773,
+			108412,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			113302,
+			109838,
+			-2974,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			14557,
+			117285,
+			-12089,
+			243
+		},
+		{
+			CLAN_STRONGHOLD_DEVICE,
+			101689,
+			111892,
+			-3672,
+			243
+		}
+	};
+	
+	private static ClanStrongholdDeviceSpawner _instance;
+	
+	public static ClanStrongholdDeviceSpawner getInstance()
+	{
+		if (_instance == null)
+		{
+			_instance = new ClanStrongholdDeviceSpawner();
+		}
+		return _instance;
+	}
+	
+	public void spawnNpcsOnServerStart()
+	{
+		for (int[] loc : _mobLoc)
+		{
+			spawnNpc(loc[0], loc[1], loc[2], loc[3], loc[4]);
+		}
+	}
+	
+	private static void spawnNpc(int npcId, int x, int y, int z, int heading)
+	{
+		try
+		{
+			final L2NpcTemplate tmpl = NpcTable.getInstance().getTemplate(npcId);
+			L2Spawn spawn = new L2Spawn(tmpl);
+			spawn.setLocx(x);
+			spawn.setLocy(y);
+			spawn.setLocz(z);
+			spawn.setAmount(1);
+			spawn.setRespawnDelay(1);
+			SpawnTable.getInstance().addNewSpawn(spawn, false);
+			spawn.init();
+			L2NpcInstance npc = spawn.getLastSpawn();
+			npc.setIsImobilised(true);
+			npc.setIsInvul(true);
+			npc.decayMe();
+			npc.spawnMe(npc.getX(), npc.getY(), npc.getZ());
+		}
+		catch (Exception e)
+		{
+			e.printStackTrace();
+		}
+	}
+}
diff --git src/l2jwins/Config.java src/l2jwins/Config.java
index cafe738..aaaf892 100644
--- src/l2jwins/Config.java
+++ src/l2jwins/Config.java
@@ -252,6 +252,12 @@
 	public static int LIMITE_CARRO_MASTER;
 	public static boolean RANK_SYSTEM_ENABLE;
 	
+	public static int CLAN_BUFF_ID;
+	
+	public static boolean CLAN_STRONGHOLD_SPAWN_ENABLED;
+	
 	// ===================================================================================================================================//
 	
 	public static void loadExtraSettingsConfig()
@@ -275,6 +281,10 @@
 			
 			AFK_TIMER = Integer.parseInt(ExtraSettings.getProperty("TimerAFK", "10"));
 			
+			CLAN_BUFF_ID = Integer.parseInt(ExtraSettings.getProperty("ClanBuffId", "1388"));
+			
 			ITEM_SPAWNID = Integer.parseInt(ExtraSettings.getProperty("ItemIdSpawn", "5072"));
 			NPC1_SPAWN_MAGIC_GEM = Integer.parseInt(ExtraSettings.getProperty("NpcIdSpawn1", "31228"));
 			NPC2_SPAWN_MAGIC_GEM = Integer.parseInt(ExtraSettings.getProperty("NpcIdSpawn2", "7077"));
@@ -294,6 +304,8 @@
 			
 			RANK_SYSTEM_ENABLE = Boolean.parseBoolean(ExtraSettings.getProperty("RankSystemEnable", "true"));
 			
+			CLAN_STRONGHOLD_SPAWN_ENABLED = Boolean.parseBoolean(ExtraSettings.getProperty("ClanStrongholdSpawnEnable", "true"));
+			
 			ALLOW_CUSTOM_CANCEL = Boolean.parseBoolean(ExtraSettings.getProperty("AllowCustomCancelTask", "True"));
 			CUSTOM_CANCEL_SECONDS = Integer.parseInt(ExtraSettings.getProperty("CustomCancelSeconds", "10"));
 			
diff --git src/l2jwins/game/GameServer.java src/l2jwins/game/GameServer.java
index 57ce5d4..345a80d 100644
--- src/l2jwins/game/GameServer.java
+++ src/l2jwins/game/GameServer.java
@@ -11,8 +11,9 @@
 import java.util.Date;
 import java.util.logging.LogManager;
 
+import Base.ClanStrongold.ClanStrongholdDeviceSpawner;
 import Base.Instance.InstanceManager;
 import Base.XML.XMLDocumentFactory;
 import Base.custom.DailyRewardManager;

@@ -532,6 +534,17 @@
 			LOG.info("Rank System Desactivado");
 		}
 		
+		if (Config.CLAN_STRONGHOLD_SPAWN_ENABLED)
+		{
+			Util.printSection("Clan Stronghold");
+			ClanStrongholdDeviceSpawner.getInstance().spawnNpcsOnServerStart();
+			LOG.info("Clan Stronghold Activado");
+		}
+		else
+		{
+			LOG.info("Clan Stronghold Desactivado");
+		}
+		
 		HistoriasTable.getInstance();
 		
 		Util.printSection("Handlers");
diff --git src/l2jwins/game/model/L2Attackable.java src/l2jwins/game/model/L2Attackable.java
index 591d05b..e306b59 100644
--- src/l2jwins/game/model/L2Attackable.java
+++ src/l2jwins/game/model/L2Attackable.java
@@ -643,6 +643,9 @@
 									exp += calculateOverhitExp(exp);
 								}
 								
+								exp = (long) ((exp * attacker.calcStat(Stats.XP_RATE, 100, null, null)) / 100);
+								sp = (int) ((sp * attacker.calcStat(Stats.SP_RATE, 100, null, null)) / 100);
+								
 								if (((L2PcInstance) attacker).getPremiumService() >= 1)
 								{
 									exp = (long) (exp * Config.PREMIUM_XPSP_RATE);
@@ -1154,7 +1157,9 @@
 				{
 					dropChance *= Config.PREMIUM_SPOIL_RATE;
 				}
+				
 			}
+			dropChance = (int) ((dropChance * lastAttacker.calcStat(Stats.SPOIL_RATE, 100, null, null)) / 100);
 		}
 		else
 		{
@@ -1229,6 +1234,7 @@
 			// Prepare for next iteration if dropChance > L2DropData.MAX_CHANCE
 			dropChance -= L2DropData.MAX_CHANCE;
 		}
+		itemCount = (int) ((itemCount * lastAttacker.calcStat(Stats.DROP_RATE, 100, null, null)) / 100);
 		
 		if (Config.L2JMOD_CHAMPION_ENABLE && isChampion())
 		{
@@ -3038,6 +3044,34 @@
 		}
 	}
 	

 	public void setSeeded()
 	{
 		if (_seedType != 0 && _seeder != null)
diff --git src/l2jwins/game/model/L2Character.java src/l2jwins/game/model/L2Character.java
index 9255274..76cc795 100644
--- src/l2jwins/game/model/L2Character.java
+++ src/l2jwins/game/model/L2Character.java
@@ -60,6 +60,7 @@
 import l2jwins.game.managers.TownManager;
 import l2jwins.game.model.L2Skill.SkillTargetType;
 import l2jwins.game.model.L2Skill.SkillType;
+import l2jwins.game.model.actor.instance.L2ClanStrongholdInstance;
 import l2jwins.game.model.actor.instance.L2ControlTowerInstance;
 import l2jwins.game.model.actor.instance.L2DoorInstance;
 import l2jwins.game.model.actor.instance.L2EffectPointInstance;

@@ -814,6 +823,7 @@
 						((L2Summon) this).getOwner().updatePvPStatus();
 					}
 				}
+				
 			}
 			
 			if (Config.GET_PVP_FLAG)
@@ -831,6 +841,21 @@
 				}
 			}
 			
+			if (Config.GET_PVP_FLAG)
+			{
+				if (target instanceof L2ClanStrongholdInstance)
+				{
+					if (this instanceof L2PcInstance)
+					{
+						((L2PcInstance) this).updatePvPStatus();
+					}
+					else if (this instanceof L2Summon)
+					{
+						((L2Summon) this).getOwner().updatePvPStatus();
+					}
+				}
+			}
+			
 			if (Config.GET_PVP_FLAG_FROM_CHAMP)
 			{
 				if (target.isChampion())

@@ -8580,4 +8631,13 @@
 	{
 		return this._IsDungeon;
 	}
+	
+	/**
+	 * @return
+	 */
+	public int getClanId()
+	{
+		// TODO Auto-generated method stub
+		return 0;
+	}
 }
\ No newline at end of file
diff --git src/l2jwins/game/model/actor/instance/L2ClanStrongholdInstance.java src/l2jwins/game/model/actor/instance/L2ClanStrongholdInstance.java
new file mode 100644
index 0000000..63b4b1e
--- /dev/null
+++ src/l2jwins/game/model/actor/instance/L2ClanStrongholdInstance.java
@@ -0,0 +1,343 @@
+package l2jwins.game.model.actor.instance;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledFuture;
+
+import l2jwins.Config;
+import l2jwins.game.ai.CtrlIntention;
+import l2jwins.game.datatables.SkillTable;
+import l2jwins.game.model.L2Character;
+import l2jwins.game.model.L2Clan;
+import l2jwins.game.model.L2Effect;
+import l2jwins.game.model.L2Skill;
+import l2jwins.game.model.L2World;
+import l2jwins.game.model.spawn.L2Spawn;
+import l2jwins.game.network.serverpackets.ActionFailed;
+import l2jwins.game.network.serverpackets.CreatureSay;
+import l2jwins.game.network.serverpackets.MagicSkillUser;
+import l2jwins.game.network.serverpackets.MoveToPawn;
+import l2jwins.game.network.serverpackets.MyTargetSelected;
+import l2jwins.game.network.serverpackets.NpcHtmlMessage;
+import l2jwins.game.network.serverpackets.NpcInfo;
+import l2jwins.game.network.serverpackets.NpcSay;
+import l2jwins.game.network.serverpackets.ValidateLocation;
+import l2jwins.game.skills.SkillHolder;
+import l2jwins.game.templates.L2NpcTemplate;
+import l2jwins.game.thread.ThreadPoolManager;
+
+#Author Terius
+public class L2ClanStrongholdInstance extends L2NpcInstance
+{
+	private static final Map<Integer, Integer> CURRENT_CLAN_ID = new ConcurrentHashMap<>(); // Clan id key - NPC object id value (can be taken from npc.getScriptValue)
+	private static final Map<Integer, Long> LAST_ATTACK = new ConcurrentHashMap<>(); // NPC object id key - Time value
+	
+	private String clanName; // Variable para almacenar el nombre del clan del jugador que lo mató
+	int clanId = 0;
+	int crestId = 0;
+	int messagemax = 0;
+	private ScheduledFuture<?> _aiTask;
+	
+	public static L2Spawn _npcSpawn;
+	
+	public L2ClanStrongholdInstance(final int objectId, final L2NpcTemplate template)
+	{
+		super(objectId, template);
+		if (_aiTask != null)
+		{
+			_aiTask.cancel(true);
+		}
+		
+		_aiTask = ThreadPoolManager.getInstance().scheduleAiAtFixedRate(new TeriusAI(this), 3000, 3000);
+		
+	}
+	
+	@Override
+	public void onAction(L2PcInstance player)
+	{
+		
+		if (this != player.getTarget())
+		{
+			player.setTarget(this);
+			player.sendPacket(new MyTargetSelected(getObjectId(), 0));
+			player.sendPacket(new ValidateLocation(this));
+		}
+		else
+		{
+			if (!canInteract(player))
+			{
+				player.getAI().setIntention(CtrlIntention.AI_INTENTION_INTERACT, this);
+			}
+			else
+			{
+				// Rotate the player to face the instance
+				player.sendPacket(new MoveToPawn(player, this, L2NpcInstance.INTERACTION_DISTANCE));
+				
+				if (hasRandomAnimation())
+				{
+					onRandomAnimation();
+				}
+				
+				showMainWindow(player);
+				
+				// Send ActionFailed to the player in order to avoid he stucks
+				player.sendPacket(ActionFailed.STATIC_PACKET);
+			}
+		}
+	}
+	
+	public void showMainWindow(L2PcInstance player)
+	{
+		
+		// Crear el HTML con la información de la historia
+		NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
+		html.setFile("data/html/mods/ClanStronghold.htm");
+		html.replace("%objectId%", String.valueOf(getObjectId()));
+		html.replace("%npcname%", getName());
+		
+		player.sendPacket(html);
+	}
+	
+	@Override
+	public void onBypassFeedback(L2PcInstance player, String command)
+	{
+		if (command.startsWith("capturar"))
+		{
+			if (isAlikeDead())
+			{
+				super.onBypassFeedback(player, command);
+				return;
+			}
+			// Obtén el nombre del clan del jugador que lo mató
+			clanName = player.getClan() != null ? player.getClan().getName() : ""; // Esto asume que la clase Player tiene un método para obtener el Clan al que pertenece
+			
+			if ((player.getClanId() == clanId && player.getClan().getCrestId() == crestId))
+			{
+				player.sendMessage("¡Ya has capturado este NPC!");
+				return;
+			}
+			
+			if (clanId > 0 && crestId > 0)
+			{
+				player.sendMessage("Este Npc Le Pertenece a un clan ahora mismo " + "Si Quieres Capturarme Tendras que matarme");
+				return;
+			}
+			
+			L2Clan playerClan = player.getClan();
+			if (playerClan == null)
+			{
+				player.sendMessage("Debes pertenecer a un clan para capturar este NPC.");
+				return;
+			}
+			
+			int playerClanId = playerClan.getClanId();
+			CURRENT_CLAN_ID.put(player.getClanId(), getObjectId());
+			setNpcValue(playerClanId);
+			setTitle("Clan: " + clanName);
+			
+			clanId = playerClan.getClanId();
+			crestId = playerClan.getCrestId();
+			setCrestId(playerClan.getCrestId());
+			setClanId(player.getClanId());
+			playerClan.setHasCrest(true);
+			broadcastTitleInfo();
+			setIsInvul(false);
+			player.sendMessage("¡Has capturado con exito este NPC!" + " Para Tu Clan " + clanName);
+			return;
+		}
+		
+		super.onBypassFeedback(player, command);
+	}
+	
+	/**
+	 * Sends a chat to all _knowObjects.
+	 * @param chat message to say
+	 */
+	public void broadcastChat(final String chat)
+	{
+		final Map<Integer, L2PcInstance> _knownPlayers = getKnownList().getKnownPlayers();
+		
+		if (_knownPlayers == null)
+		{
+			if (Config.DEVELOPER)
+			{
+				LOG.info("broadcastChat _players == null");
+			}
+			return;
+		}
+		
+		// we send message to known players only!
+		if (_knownPlayers.size() > 0 && messagemax <= 2)
+		{
+			CreatureSay cs = new CreatureSay(getObjectId(), 0, getName(), chat);
+			
+			// we interact and list players here
+			for (final L2PcInstance players : _knownPlayers.values())
+			{
+				
+				// finally send packet :D
+				players.sendPacket(cs);
+				messagemax++;
+				
+			}
+		}
+	}
+	
+	@Override
+	public boolean doDie(L2Character killer)
+	{
+		super.doDie(killer);
+		if (killer instanceof L2PcInstance)
+		{
+			
+			L2PcInstance activeChar = ((L2PcInstance) killer);
+			
+			// Obtén el nombre del clan del jugador que lo mató
+			clanName = activeChar.getClan() != null ? activeChar.getClan().getName() : ""; // Esto asume que la clase Player tiene un método para obtener el Clan al que pertenece
+			
+			L2Clan clan = ((L2PcInstance) killer).getClan();
+			if (clan != null)
+			{
+				clanId = 0;
+				crestId = 0;
+				messagemax--;
+				
+			}
+			else
+			{
+				
+				clanId = 0;
+				crestId = 0;
+				messagemax--;
+				
+				ThreadPoolManager.getInstance().scheduleGeneral(() -> doSpawn(), 1000);
+			}
+			
+		}
+		return true;
+	}
+	
+	public void setCrestId(int crestId)
+	{
+		this.crestId = crestId;
+	}
+	
+	public void doSpawn()
+	{
+		
+		spawnMe(getX(), getY(), getZ());
+		
+		onSpawn();
+	}
+	
+	// Método para enviar la información de título del NPC a los jugadores cercanos
+	@Override
+	void broadcastTitleInfo()
+	{
+		for (L2PcInstance player : L2World.getInstance().getAllPlayers().values())
+		{
+			player.sendPacket(new NpcInfo(this, player));
+		}
+	}
+	
+	// Método para enviar la información de título del NPC a los jugadores cercanos
+	void broadcastTitleInfoRadius()
+	{
+		for (L2PcInstance player : getKnownList().getKnownPlayersInRadius(1800))
+		{
+			player.sendPacket(new NpcInfo(this, player));
+		}
+	}
+	
+	private class TeriusAI implements Runnable
+	{
+		private final L2ClanStrongholdInstance _caster;
+		
+		protected TeriusAI(final L2ClanStrongholdInstance caster)
+		{
+			_caster = caster;
+		}
+		
+		private final SkillHolder[] CLAN_BUFFS =
+		{
+			new SkillHolder(Config.CLAN_BUFF_ID, 1),
+		};
+		
+		@Override
+		public void run()
+		{
+			for (final L2PcInstance player : getKnownList().getKnownPlayers().values())
+			{
+				
+				for (SkillHolder skills : CLAN_BUFFS)
+				{
+					TeriusCast(player, skills.getSkill());
+				}
+				
+			}
+			
+			for (L2PcInstance player : getKnownList().getKnownPlayersInRadius(900))
+			{
+				if (!isInsideRadius(player, 900, false, false) && messagemax >= 1)
+				{
+					messagemax--;
+					messagemax = 0;
+					player.sendMessage("test");
+				}
+			}
+			
+			// for (L2PcInstance player : getKnownList().getKnownPlayersInRadius(900))
+			// {
+			// if (!isInsideRadius(player, 900, false, false) && clanId > 0 && crestId > 0)
+			// {
+			// broadcastTitleInfoRadius();
+			// }
+			// }
+			
+		}
+		
+ //in case of using a buff with stats use this
+       private boolean TeriusCastStats(final L2PcInstance player, L2Skill skill)
+        {
+            if (player.isDead() || !player.isVisible() || !isInsideRadius(player, 900, false, false))
+            {
+                return false;
+            }
+            
+
+			if (clanId > 0 && crestId > 0)
+			{
+				broadcastTitleInfoRadius();
+			}
+			
+			L2Clan playerClan = player.getClan();
+			if (playerClan != null && playerClan.getClanId() == clanId){
+            if (player.getFirstEffect(skill) == null)
+           {
+                SkillTable.getInstance().getInfo(skill.getId(), skill.getLevel()).getEffects(player, player);
+                skill.getEffects(_caster, player, false, false, false);
+                broadcastPacket(new MagicSkillUser(_caster, player, skill.getId(), skill.getLevel(), 1000, 0));
+                
+                return true;
+            }
+            }
+            return false;
+        }
+
+
+
+
+
+		private boolean TeriusCast(final L2PcInstance player, L2Skill skill)
+		{
+			if (player.isDead() || !player.isVisible() || !isInsideRadius(player, 900, false, false))
+			{
+				return false;
+			}
+			
+			if (clanId > 0 && crestId > 0)
+			{
+				broadcastTitleInfoRadius();
+			}
+			
+			L2Clan playerClan = player.getClan();
+			if (playerClan != null && playerClan.getClanId() == clanId)
+			{
+				L2Effect firstEffect = player.getFirstEffect(skill);
+				if (firstEffect == null || firstEffect.getTime() < 180)
+				{
+					// player.stopSkillEffects(skill.getId()); // Detiene el efecto del buff anterior si el tiempo restante es menor a 1 segundo
+					
+					SkillTable.getInstance().getInfo(skill.getId(), skill.getLevel()).getEffects(player, player);
+					skill.getEffects(_caster, player, false, false, false);
+					broadcastPacket(new MagicSkillUser(_caster, player, skill.getId(), skill.getLevel(), 1000, 0));
+					return true;
+				}
+			}
+			
+			return false;
+		}
+		
+	}
+	
+}
diff --git src/l2jwins/game/model/actor/stat/CharStat.java src/l2jwins/game/model/actor/stat/CharStat.java
index fa97777..68bc1cb 100644
--- src/l2jwins/game/model/actor/stat/CharStat.java
+++ src/l2jwins/game/model/actor/stat/CharStat.java
@@ -92,6 +92,10 @@
 				case STAT_MEN:
 				case STAT_STR:
 				case STAT_WIT:
+				case XP_RATE:
+				case SP_RATE:
+				case DROP_RATE:
+				case SPOIL_RATE:
 					env.value = 1.0;
 			}
 		}
diff --git src/l2jwins/game/network/serverpackets/NpcInfo.java src/l2jwins/game/network/serverpackets/NpcInfo.java
index 9af0b29..5c3caea 100644
--- src/l2jwins/game/network/serverpackets/NpcInfo.java
+++ src/l2jwins/game/network/serverpackets/NpcInfo.java
@@ -24,6 +24,7 @@
 import l2jwins.game.model.L2Character;
 import l2jwins.game.model.L2Clan;
 import l2jwins.game.model.L2Summon;
+import l2jwins.game.model.actor.instance.L2ClanStrongholdInstance;
 import l2jwins.game.model.actor.instance.L2MonsterInstance;
 import l2jwins.game.model.actor.instance.L2NpcInstance;
 import l2jwins.game.model.actor.instance.L2PetInstance;
@@ -46,7 +47,6 @@
 	private int _collisionHeight, _collisionRadius;
 	private String _name = "";
 	private String _title = "";
-	
 	private int _clanCrest;
 	private int _clanId;
 	private int _allyCrest;
@@ -122,6 +122,32 @@
 		_y = _activeChar.getY();
 		_z = _activeChar.getZ();
 		
+		if (_activeChar instanceof L2ClanStrongholdInstance)
+		{
+			final L2Clan clan = ClanTable.getInstance().getClan(cha.getClanId());
+			if ((clan != null) && ((cha.getTemplate().getNpcId() == 34156 /* ID Npc Clan Stronghold Device */) || (!cha.isMonster())))
+			{
+				_clanCrest = clan.getCrestId();
+				_clanId = clan.getClanId();
+				_allyCrest = clan.getAllyCrestId();
+				_allyId = clan.getAllyId();
+				
+			}
+		}
+		
 		if (Config.SHOW_NPC_CREST)
 		{
 			if (cha.isInsideZone(ZoneId.ZONE_PEACE) && cha.getCastle().getOwnerId() != 0)
@@ -251,6 +277,7 @@
 			writeD(_clanCrest);
 			writeD(_allyId);
 			writeD(_allyCrest);
+			
 		}
 		else
 		{
diff --git src/l2jwins/game/skills/Stats.java src/l2jwins/game/skills/Stats.java
index b5e2fe1..50aff3b 100644
--- src/l2jwins/game/skills/Stats.java
+++ src/l2jwins/game/skills/Stats.java
@@ -218,6 +218,11 @@
 	HP_CONSUME_RATE("HpConsumeRate"),
 	MP_CONSUME("MpConsume"),
 	SOULSHOT_COUNT("soulShotCount"),
+	// custom
+	XP_RATE("xpGain"),
+	SP_RATE("spGain"),
+	DROP_RATE("dropRate"),
+	SPOIL_RATE("spoilRate"),
 	
 	// Skill mastery
 	SKILL_MASTERY("skillMastery");