Преглед на файлове

Adding summonned npc list support.

Requested by: @ivantotov
Reviewed by: @UnAfraid, @NosBit
Zoey76 преди 10 години
родител
ревизия
cbcb5d7e42

+ 6 - 2
L2J_Server/java/com/l2jserver/gameserver/model/L2Spawn.java

@@ -643,13 +643,17 @@ public class L2Spawn implements IPositionable, IIdentifiable, INamable
 			}
 		}
 		
+		// Reset summoner
+		mob.setSummoner(null);
+		// Reset summoned list
+		mob.resetSummonedNpcs();
 		// Link the L2NpcInstance to this L2Spawn
 		mob.setSpawn(this);
 		
-		// Init other values of the L2NpcInstance (ex : from its L2CharTemplate for INT, STR, DEX...) and add it in the world as a visible object
+		// Spawn NPC
 		mob.spawnMe(newlocx, newlocy, newlocz);
 		
-		L2Spawn.notifyNpcSpawned(mob);
+		notifyNpcSpawned(mob);
 		
 		_spawnedNpcs.add(mob);
 		if (_lastSpawnPoints != null)

+ 72 - 0
L2J_Server/java/com/l2jserver/gameserver/model/actor/L2Npc.java

@@ -23,6 +23,8 @@ import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Level;
 
 import com.l2jserver.Config;
@@ -144,6 +146,8 @@ public class L2Npc extends L2Character
 	
 	private int _shotsMask = 0;
 	private int _killingBlowWeaponId;
+	/** Map of summoned NPCs by this NPC. */
+	private volatile Map<Integer, L2Npc> _summonedNpcs = null;
 	
 	public int getSoulShotChance()
 	{
@@ -1957,4 +1961,72 @@ public class L2Npc extends L2Character
 	{
 		return _killingBlowWeaponId;
 	}
+	
+	/**
+	 * Adds a summoned NPC.
+	 * @param npc the summoned NPC
+	 */
+	public final void addSummonedNpc(L2Npc npc)
+	{
+		if (_summonedNpcs == null)
+		{
+			synchronized (this)
+			{
+				if (_summonedNpcs == null)
+				{
+					_summonedNpcs = new ConcurrentHashMap<>();
+				}
+			}
+		}
+		
+		_summonedNpcs.put(npc.getObjectId(), npc);
+		
+		npc.setSummoner(this);
+	}
+	
+	/**
+	 * Removes a summoned NPC by object ID.
+	 * @param objectId the summoned NPC object ID
+	 */
+	public final void removeSummonedNpc(int objectId)
+	{
+		if (_summonedNpcs != null)
+		{
+			_summonedNpcs.remove(objectId);
+		}
+	}
+	
+	/**
+	 * Gets the summoned NPC by object ID.
+	 * @param objectId the summoned NPC object ID
+	 * @return the summoned NPC
+	 */
+	public final L2Npc getSummonedNpc(int objectId)
+	{
+		if (_summonedNpcs != null)
+		{
+			return _summonedNpcs.get(objectId);
+		}
+		return null;
+	}
+	
+	/**
+	 * Gets the summoned NPC count.
+	 * @return the summoned NPC count
+	 */
+	public final int getSummonedNpcCount()
+	{
+		return _summonedNpcs != null ? _summonedNpcs.size() : 0;
+	}
+	
+	/**
+	 * Resets the summoned NPCs list.
+	 */
+	public final void resetSummonedNpcs()
+	{
+		if (_summonedNpcs != null)
+		{
+			_summonedNpcs.clear();
+		}
+	}
 }

+ 10 - 13
L2J_Server/java/com/l2jserver/gameserver/model/entity/Hero.java

@@ -775,7 +775,6 @@ public class Hero
 								}
 							}
 						}
-						_heroes.remove(heroId);
 						_heroes.put(heroId, hero);
 						
 						_completeHeroes.put(heroId, hero);
@@ -928,21 +927,12 @@ public class Hero
 		}
 	}
 	
-	/**
-	 * @param objectId the player's object Id to verify.
-	 * @return {@code true} if there are heros and the player is in the list, {@code false} otherwise.
-	 */
-	public boolean isHero(int objectId)
-	{
-		return _heroes.containsKey(objectId) && _heroes.get(objectId).getBoolean(CLAIMED);
-	}
-	
 	/**
 	 * Verifies if the given object ID belongs to a claimed hero.
 	 * @param objectId the player's object ID to verify
-	 * @return {@code true} if the given object ID belongs to a claimed hero, {@code false} otherwise
+	 * @return {@code true} if there are heros and the player is in the list, {@code false} otherwise
 	 */
-	public boolean isClaimed(int objectId)
+	public boolean isHero(int objectId)
 	{
 		return _heroes.containsKey(objectId) && _heroes.get(objectId).getBoolean(CLAIMED);
 	}
@@ -953,7 +943,14 @@ public class Hero
 	 */
 	public void claimHero(L2PcInstance player)
 	{
-		_heroes.get(player.getObjectId()).set(CLAIMED, true);
+		StatsSet hero = _heroes.get(player.getObjectId());
+		if (hero == null)
+		{
+			hero = new StatsSet();
+			_heroes.put(player.getObjectId(), hero);
+		}
+		
+		hero.set(CLAIMED, true);
 		
 		final L2Clan clan = player.getClan();
 		if ((clan != null) && (clan.getLevel() >= 5))

+ 63 - 36
L2J_Server/java/com/l2jserver/gameserver/model/events/AbstractScript.java

@@ -1675,57 +1675,84 @@ public abstract class AbstractScript extends ManagedScript
 	 * @see #addSpawn(int, int, int, int, int, boolean, long, boolean)
 	 */
 	public static L2Npc addSpawn(int npcId, int x, int y, int z, int heading, boolean randomOffset, long despawnDelay, boolean isSummonSpawn, int instanceId)
+	{
+		return addSpawn(null, npcId, x, y, z, heading, randomOffset, despawnDelay, isSummonSpawn, instanceId);
+	}
+	
+	/**
+	 * Add a temporary spawn of the specified NPC.
+	 * @param summoner the NPC that requires this spawn
+	 * @param npcId the ID of the NPC to spawn
+	 * @param x the X coordinate of the spawn location
+	 * @param y the Y coordinate of the spawn location
+	 * @param z the Z coordinate (height) of the spawn location
+	 * @param heading the heading of the NPC
+	 * @param randomOffset if {@code true}, adds +/- 50~100 to X/Y coordinates of the spawn location
+	 * @param despawnDelay time in milliseconds till the NPC is despawned (0 - only despawned on server shutdown)
+	 * @param isSummonSpawn if {@code true}, displays a summon animation on NPC spawn
+	 * @param instanceId the ID of the instance to spawn the NPC in (0 - the open world)
+	 * @return the {@link L2Npc} object of the newly spawned NPC or {@code null} if the NPC doesn't exist
+	 * @see #addSpawn(int, IPositionable, boolean, long, boolean, int)
+	 * @see #addSpawn(int, int, int, int, int, boolean, long)
+	 * @see #addSpawn(int, int, int, int, int, boolean, long, boolean)
+	 */
+	public static L2Npc addSpawn(L2Npc summoner, int npcId, int x, int y, int z, int heading, boolean randomOffset, long despawnDelay, boolean isSummonSpawn, int instanceId)
 	{
 		try
 		{
-			L2NpcTemplate template = NpcData.getInstance().getTemplate(npcId);
+			final L2NpcTemplate template = NpcData.getInstance().getTemplate(npcId);
 			if (template == null)
 			{
-				_log.log(Level.SEVERE, "addSpawn(): no NPC template found for NPC #" + npcId + "!");
+				_log.severe("Couldn't find NPC template for ID:" + npcId + "!");
+				return null;
 			}
-			else
+			
+			if ((x == 0) && (y == 0))
 			{
-				if ((x == 0) && (y == 0))
-				{
-					_log.log(Level.SEVERE, "addSpawn(): invalid spawn coordinates for NPC #" + npcId + "!");
-					return null;
-				}
-				if (randomOffset)
+				_log.log(Level.SEVERE, "addSpawn(): invalid spawn coordinates for NPC #" + npcId + "!");
+				return null;
+			}
+			
+			if (randomOffset)
+			{
+				int offset = Rnd.get(50, 100);
+				if (Rnd.nextBoolean())
 				{
-					int offset = Rnd.get(50, 100);
-					if (Rnd.nextBoolean())
-					{
-						offset *= -1;
-					}
-					x += offset;
-					
-					offset = Rnd.get(50, 100);
-					if (Rnd.nextBoolean())
-					{
-						offset *= -1;
-					}
-					y += offset;
+					offset *= -1;
 				}
-				L2Spawn spawn = new L2Spawn(template);
-				spawn.setInstanceId(instanceId);
-				spawn.setHeading(heading);
-				spawn.setX(x);
-				spawn.setY(y);
-				spawn.setZ(z);
-				spawn.stopRespawn();
-				L2Npc result = spawn.spawnOne(isSummonSpawn);
+				x += offset;
 				
-				if (despawnDelay > 0)
+				offset = Rnd.get(50, 100);
+				if (Rnd.nextBoolean())
 				{
-					result.scheduleDespawn(despawnDelay);
+					offset *= -1;
 				}
-				
-				return result;
+				y += offset;
+			}
+			
+			final L2Spawn spawn = new L2Spawn(template);
+			spawn.setInstanceId(instanceId);
+			spawn.setHeading(heading);
+			spawn.setX(x);
+			spawn.setY(y);
+			spawn.setZ(z);
+			spawn.stopRespawn();
+			
+			final L2Npc npc = spawn.spawnOne(isSummonSpawn);
+			if (despawnDelay > 0)
+			{
+				npc.scheduleDespawn(despawnDelay);
 			}
+			
+			if (summoner != null)
+			{
+				summoner.addSummonedNpc(npc);
+			}
+			return npc;
 		}
-		catch (Exception e1)
+		catch (Exception e)
 		{
-			_log.warning("Could not spawn NPC #" + npcId + "; error: " + e1.getMessage());
+			_log.warning("Could not spawn NPC #" + npcId + "; error: " + e.getMessage());
 		}
 		
 		return null;