Addition of Clan Stronghold Device AI.

Contributed by Index.
This commit is contained in:
MobiusDevelopment 2022-12-02 22:46:25 +00:00
parent 9bdbfcf21f
commit 87fc69962c
40 changed files with 1061 additions and 21 deletions

View File

@ -19,4 +19,5 @@ MobsSpawnNotRandom = 18812,18813,18814,22138,\
18221,18222,18226,18230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,\
18242,18243,18256,31452,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,31478,\
31479,31480,31481,31482,31483,31484,31485,31486,31487,\
22183
22183,\
34156

View File

@ -0,0 +1,3 @@
<html><body>Clan Stronghold Device:<br>
The Clan Capture effect is activated when you fight local monsters.
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
The Clan Stronghold Device has been captured.<br>
The Stronghold Device can be destroyed with a <font color="LEVEL">forced attack</font>.
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
In order to use the Clan Stronghold Device, you must <font color="LEVEL">join a clan</font>.<br>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest ClanStrongholdDevice back">Back</button>
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
Currently the device <font color="LEVEL">can be captured</font>. During a capture attempt the Clan Stronghold Effect is activated when you fight local monsters.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass Quest ClanStrongholdDevice capture">Capture the Stronghold</Button>
</body></html>

View File

@ -0,0 +1,217 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.others.ClanStrongholdDevice;
import java.util.HashMap;
import java.util.Map;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExChangeNpcState;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import org.l2jmobius.gameserver.network.serverpackets.NpcSay;
import ai.AbstractNpcAI;
/**
* @author Index
*/
public class ClanStrongholdDevice extends AbstractNpcAI
{
// NPCs
private static final int CLAN_STRONGHOLD_DEVICE = 34156;
private static final int[] NEARBY_MONSTER_IDS =
{
22200, // Porta
22201, // Excuro
22202, // Mordeo
22203, // Ricenseo
22204, // Krator
22205, // Catherok
22206, // Premo
22207, // Validus
22208, // Dicor
22209, // Perum
22210, // Torfe
22211, // Death Lord
};
// Skill
private static final SkillHolder CLAN_STRONGHOLD_EFFECT = new SkillHolder(48078, 1);
// Misc
private static final Map<Integer, Integer> CURRENT_CLAN_ID = new HashMap<>(); // Clan id key - NPC object id value (can be taken from npc.getScriptValue)
private static final Map<Integer, Long> LAST_ATTACK = new HashMap<>(); // NPC object id key - Time value
private static final Map<Integer, Location> DEVICE_LOCATION = new HashMap<>();
private ClanStrongholdDevice()
{
addCreatureSeeId(CLAN_STRONGHOLD_DEVICE);
addFirstTalkId(CLAN_STRONGHOLD_DEVICE);
addAttackId(CLAN_STRONGHOLD_DEVICE);
addSpawnId(CLAN_STRONGHOLD_DEVICE);
addTalkId(CLAN_STRONGHOLD_DEVICE);
addKillId(CLAN_STRONGHOLD_DEVICE);
addKillId(NEARBY_MONSTER_IDS);
}
@Override
public String onAdvEvent(String event, Npc npc, Player player)
{
if ((npc.getTemplate().getId() != CLAN_STRONGHOLD_DEVICE) || (player == null) || (event == null))
{
return super.onAdvEvent(event, npc, player);
}
if (event.equals("capture"))
{
if (npc.isAlikeDead())
{
return super.onAdvEvent(event, npc, player);
}
if (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()))
{
return "34156-02.htm";
}
if (player.getClan() == null)
{
return "34156-03.htm";
}
CURRENT_CLAN_ID.put(player.getClanId(), npc.getObjectId());
npc.setScriptValue(player.getClanId());
npc.setTitle(player.getClan().getName());
npc.setClanId(player.getClanId());
npc.setDisplayEffect(2);
npc.setInvul(false);
npc.broadcastInfo();
return "34156-01.htm";
}
else if (event.equals("back"))
{
if (npc.isAlikeDead())
{
return super.onAdvEvent(event, npc, player);
}
return npc.getId() + (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) ? "-02" : "") + ".htm";
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onFirstTalk(Npc npc, Player player)
{
if (npc.isAlikeDead())
{
return super.onFirstTalk(npc, player);
}
return npc.getId() + (CURRENT_CLAN_ID.getOrDefault(npc.getScriptValue(), 0) == 0 ? "" : "C") + ".htm";
}
@Override
public String onCreatureSee(Npc npc, Creature creature)
{
if (npc.getTemplate().getId() == CLAN_STRONGHOLD_DEVICE)
{
creature.sendPacket(new ExChangeNpcState(npc.getObjectId(), CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) ? 1 : 2));
}
return super.onCreatureSee(npc, creature);
}
@Override
public String onSpawn(Npc npc)
{
if (npc.getTemplate().getId() != CLAN_STRONGHOLD_DEVICE)
{
return super.onSpawn(npc);
}
npc.disableCoreAI(true);
npc.setAutoAttackable(false);
npc.setImmobilized(true);
npc.setDisplayEffect(1);
npc.setUndying(false);
npc.setScriptValue(0);
npc.setInvul(true);
npc.setClanId(0);
npc.setTitle("");
npc.broadcastInfo();
npc.broadcastPacket(new ExShowScreenMessage(NpcStringId.THE_CLAN_STRONGHOLD_DEVICE_CAN_BE_CAPTURED, 2, 5000, true));
DEVICE_LOCATION.put(npc.getObjectId(), npc.getLocation());
return super.onSpawn(npc);
}
@Override
public String onAttack(Npc npc, Player attacker, int damage, boolean isSummon)
{
if (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) && (LAST_ATTACK.getOrDefault(npc.getObjectId(), 0L) < (System.currentTimeMillis() - 5000L)))
{
npc.broadcastPacket(new NpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.AT_TACK_SIG_NAL_DE_TEC_TED_S1).addStringParameter(attacker.getName()));
LAST_ATTACK.put(npc.getObjectId(), System.currentTimeMillis());
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(Npc npc, Player killer, boolean isSummon)
{
if (npc.getTemplate().getId() == CLAN_STRONGHOLD_DEVICE)
{
npc.setClanId(0);
CURRENT_CLAN_ID.remove(npc.getScriptValue());
LAST_ATTACK.remove(npc.getObjectId());
DEVICE_LOCATION.remove(npc.getObjectId());
return super.onKill(npc, killer, isSummon);
}
if (CURRENT_CLAN_ID.getOrDefault(killer.getClanId(), 0) == 0)
{
return super.onKill(npc, killer, isSummon);
}
CLAN_STRONGHOLD_EFFECT.getSkill().activateSkill(npc, killer);
for (Player clanMate : World.getInstance().getVisibleObjects(killer, Player.class))
{
if (clanMate.getClanId() != killer.getClanId())
{
continue;
}
final Location deviceLocation = DEVICE_LOCATION.get(CURRENT_CLAN_ID.get(killer.getClanId()));
if ((clanMate.calculateDistance2D(deviceLocation) < 900) && (Math.abs(clanMate.getZ() - deviceLocation.getZ()) < 200))
{
clanMate.doCast(CLAN_STRONGHOLD_EFFECT.getSkill());
}
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new ClanStrongholdDevice();
}
}

View File

@ -1,7 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../xsd/spawns.xsd">
<spawn name="20_21">
<spawn name="CrumaTower">
<group>
<npc id="34156" x="14562" y="117276" z="-12088" heading="22517" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="20851" y="117298" z="-12088" heading="12995" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="20871" y="111005" z="-12088" heading="63162" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="14569" y="111074" z="-12088" heading="57456" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="12821" y="109976" z="-9064" heading="12293" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="12568" y="118313" z="-9064" heading="43746" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="22680" y="114122" z="-9064" heading="54696" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="30483" x="17289" y="114112" z="-3440" heading="32768" respawnTime="60sec" /> <!-- Carsus - Ivory Tower Wizard -->
<npc id="30484" x="17636" y="114744" z="-11680" heading="6843" respawnTime="60sec" /> <!-- Janssen - Ivory Tower Wizard -->
<npc id="30487" x="17811" y="114750" z="-11680" heading="25785" respawnTime="60sec" /> <!-- Rombel - Ivory Tower Wizard -->

View File

@ -1920,7 +1920,7 @@
<skill id="4045" level="1" /> <!-- Full Magic Attack Resistance -->
</skillList>
</npc>
<npc id="34156" level="75" type="Folk" name="Clan Stronghold Device">
<npc id="34156" level="75" type="Monster" name="Clan Stronghold Device" usingServerSideTitle="true">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
<race>CONSTRUCT</race>
<sex>MALE</sex>

View File

@ -467,8 +467,28 @@
</skill>
<skill id="48078" toLevel="1" name="Clan Stronghold Effect">
<!-- A clan stronghold effect activated by a clan member in Cruma Tower. For $s1, Acquired XP/ SP +$s2. -->
<icon>icon.skill0000</icon>
<operateType>A1</operateType>
<abnormalLevel>1</abnormalLevel>
<abnormalTime>300</abnormalTime>
<abnormalType>HERB_EXP</abnormalType>
<castRange>900</castRange>
<effectRange>900</effectRange>
<isMagic>1</isMagic> <!-- Magic Skill -->
<magicLevel>99</magicLevel>
<mpConsume>0</mpConsume>
<mpInitialConsume>0</mpInitialConsume>
<operateType>A2</operateType>
<basicProperty>NONE</basicProperty>
<targetType>TARGET</targetType>
<affectScope>SINGLE</affectScope>
<isTriggeredSkill>true</isTriggeredSkill>
<effects>
<effect name="ExpModify">
<amount>50</amount>
</effect>
<effect name="SpModify">
<amount>50</amount>
</effect>
</effects>
</skill>
<skill id="48079" toLevel="1" name="Triple Slash">
<!-- AUTO GENERATED SKILL TODO: FIX IT -->

View File

@ -184,7 +184,7 @@ public class NpcInfo extends AbstractMaskPacket<NpcInfoType>
if (npc.getClanId() > 0)
{
final Clan clan = ClanTable.getInstance().getClan(npc.getClanId());
if ((clan != null) && !npc.isMonster() && npc.isInsideZone(ZoneId.PEACE))
if ((clan != null) && ((npc.getTemplate().getId() == 34156 /* Clan Stronghold Device */) || (!npc.isMonster() && npc.isInsideZone(ZoneId.PEACE))))
{
_clanId = clan.getId();
_clanCrest = clan.getCrestId();

View File

@ -19,4 +19,5 @@ MobsSpawnNotRandom = 18812,18813,18814,22138,\
18221,18222,18226,18230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,\
18242,18243,18256,31452,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,31478,\
31479,31480,31481,31482,31483,31484,31485,31486,31487,\
22183,22324
22183,22324,\
34156

View File

@ -0,0 +1,3 @@
<html><body>Clan Stronghold Device:<br>
The Clan Capture effect is activated when you fight local monsters.
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
The Clan Stronghold Device has been captured.<br>
The Stronghold Device can be destroyed with a <font color="LEVEL">forced attack</font>.
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
In order to use the Clan Stronghold Device, you must <font color="LEVEL">join a clan</font>.<br>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest ClanStrongholdDevice back">Back</button>
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
Currently the device <font color="LEVEL">can be captured</font>. During a capture attempt the Clan Stronghold Effect is activated when you fight local monsters.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass Quest ClanStrongholdDevice capture">Capture the Stronghold</Button>
</body></html>

View File

@ -0,0 +1,217 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.others.ClanStrongholdDevice;
import java.util.HashMap;
import java.util.Map;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExChangeNpcState;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import org.l2jmobius.gameserver.network.serverpackets.NpcSay;
import ai.AbstractNpcAI;
/**
* @author Index
*/
public class ClanStrongholdDevice extends AbstractNpcAI
{
// NPCs
private static final int CLAN_STRONGHOLD_DEVICE = 34156;
private static final int[] NEARBY_MONSTER_IDS =
{
22200, // Porta
22201, // Excuro
22202, // Mordeo
22203, // Ricenseo
22204, // Krator
22205, // Catherok
22206, // Premo
22207, // Validus
22208, // Dicor
22209, // Perum
22210, // Torfe
22211, // Death Lord
};
// Skill
private static final SkillHolder CLAN_STRONGHOLD_EFFECT = new SkillHolder(48078, 1);
// Misc
private static final Map<Integer, Integer> CURRENT_CLAN_ID = new HashMap<>(); // Clan id key - NPC object id value (can be taken from npc.getScriptValue)
private static final Map<Integer, Long> LAST_ATTACK = new HashMap<>(); // NPC object id key - Time value
private static final Map<Integer, Location> DEVICE_LOCATION = new HashMap<>();
private ClanStrongholdDevice()
{
addCreatureSeeId(CLAN_STRONGHOLD_DEVICE);
addFirstTalkId(CLAN_STRONGHOLD_DEVICE);
addAttackId(CLAN_STRONGHOLD_DEVICE);
addSpawnId(CLAN_STRONGHOLD_DEVICE);
addTalkId(CLAN_STRONGHOLD_DEVICE);
addKillId(CLAN_STRONGHOLD_DEVICE);
addKillId(NEARBY_MONSTER_IDS);
}
@Override
public String onAdvEvent(String event, Npc npc, Player player)
{
if ((npc.getTemplate().getId() != CLAN_STRONGHOLD_DEVICE) || (player == null) || (event == null))
{
return super.onAdvEvent(event, npc, player);
}
if (event.equals("capture"))
{
if (npc.isAlikeDead())
{
return super.onAdvEvent(event, npc, player);
}
if (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()))
{
return "34156-02.htm";
}
if (player.getClan() == null)
{
return "34156-03.htm";
}
CURRENT_CLAN_ID.put(player.getClanId(), npc.getObjectId());
npc.setScriptValue(player.getClanId());
npc.setTitle(player.getClan().getName());
npc.setClanId(player.getClanId());
npc.setDisplayEffect(2);
npc.setInvul(false);
npc.broadcastInfo();
return "34156-01.htm";
}
else if (event.equals("back"))
{
if (npc.isAlikeDead())
{
return super.onAdvEvent(event, npc, player);
}
return npc.getId() + (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) ? "-02" : "") + ".htm";
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onFirstTalk(Npc npc, Player player)
{
if (npc.isAlikeDead())
{
return super.onFirstTalk(npc, player);
}
return npc.getId() + (CURRENT_CLAN_ID.getOrDefault(npc.getScriptValue(), 0) == 0 ? "" : "C") + ".htm";
}
@Override
public String onCreatureSee(Npc npc, Creature creature)
{
if (npc.getTemplate().getId() == CLAN_STRONGHOLD_DEVICE)
{
creature.sendPacket(new ExChangeNpcState(npc.getObjectId(), CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) ? 1 : 2));
}
return super.onCreatureSee(npc, creature);
}
@Override
public String onSpawn(Npc npc)
{
if (npc.getTemplate().getId() != CLAN_STRONGHOLD_DEVICE)
{
return super.onSpawn(npc);
}
npc.disableCoreAI(true);
npc.setAutoAttackable(false);
npc.setImmobilized(true);
npc.setDisplayEffect(1);
npc.setUndying(false);
npc.setScriptValue(0);
npc.setInvul(true);
npc.setClanId(0);
npc.setTitle("");
npc.broadcastInfo();
npc.broadcastPacket(new ExShowScreenMessage(NpcStringId.THE_CLAN_STRONGHOLD_DEVICE_CAN_BE_CAPTURED, 2, 5000, true));
DEVICE_LOCATION.put(npc.getObjectId(), npc.getLocation());
return super.onSpawn(npc);
}
@Override
public String onAttack(Npc npc, Player attacker, int damage, boolean isSummon)
{
if (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) && (LAST_ATTACK.getOrDefault(npc.getObjectId(), 0L) < (System.currentTimeMillis() - 5000L)))
{
npc.broadcastPacket(new NpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.AT_TACK_SIG_NAL_DE_TEC_TED_S1).addStringParameter(attacker.getName()));
LAST_ATTACK.put(npc.getObjectId(), System.currentTimeMillis());
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(Npc npc, Player killer, boolean isSummon)
{
if (npc.getTemplate().getId() == CLAN_STRONGHOLD_DEVICE)
{
npc.setClanId(0);
CURRENT_CLAN_ID.remove(npc.getScriptValue());
LAST_ATTACK.remove(npc.getObjectId());
DEVICE_LOCATION.remove(npc.getObjectId());
return super.onKill(npc, killer, isSummon);
}
if (CURRENT_CLAN_ID.getOrDefault(killer.getClanId(), 0) == 0)
{
return super.onKill(npc, killer, isSummon);
}
CLAN_STRONGHOLD_EFFECT.getSkill().activateSkill(npc, killer);
for (Player clanMate : World.getInstance().getVisibleObjects(killer, Player.class))
{
if (clanMate.getClanId() != killer.getClanId())
{
continue;
}
final Location deviceLocation = DEVICE_LOCATION.get(CURRENT_CLAN_ID.get(killer.getClanId()));
if ((clanMate.calculateDistance2D(deviceLocation) < 900) && (Math.abs(clanMate.getZ() - deviceLocation.getZ()) < 200))
{
clanMate.doCast(CLAN_STRONGHOLD_EFFECT.getSkill());
}
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new ClanStrongholdDevice();
}
}

View File

@ -2,6 +2,13 @@
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../xsd/spawns.xsd">
<spawn name="CrumaTower">
<group>
<npc id="34156" x="14562" y="117276" z="-12088" heading="22517" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="20851" y="117298" z="-12088" heading="12995" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="20871" y="111005" z="-12088" heading="63162" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="14569" y="111074" z="-12088" heading="57456" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="12821" y="109976" z="-9064" heading="12293" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="12568" y="118313" z="-9064" heading="43746" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="22680" y="114122" z="-9064" heading="54696" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="30483" x="17289" y="114112" z="-3440" heading="32768" respawnTime="60sec" /> <!-- Carsus - Ivory Tower Wizard -->
<npc id="30484" x="17636" y="114744" z="-11680" heading="6843" respawnTime="60sec" /> <!-- Janssen - Ivory Tower Wizard -->
<npc id="30487" x="17811" y="114750" z="-11680" heading="25785" respawnTime="60sec" /> <!-- Rombel - Ivory Tower Wizard -->

View File

@ -1919,7 +1919,7 @@
<skill id="4045" level="1" /> <!-- Full Magic Attack Resistance -->
</skillList>
</npc>
<npc id="34156" level="75" type="Folk" name="Clan Stronghold Device">
<npc id="34156" level="75" type="Monster" name="Clan Stronghold Device" usingServerSideTitle="true">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
<race>CONSTRUCT</race>
<sex>MALE</sex>

View File

@ -467,8 +467,28 @@
</skill>
<skill id="48078" toLevel="1" name="Clan Stronghold Effect">
<!-- Buff for the members of the clan that secured the Cruma Tower Clan Stronghold Device. For $s1 Acquired XP $s2 Acquired SP $s2 -->
<icon>icon.skill0000</icon>
<operateType>A1</operateType>
<abnormalLevel>1</abnormalLevel>
<abnormalTime>300</abnormalTime>
<abnormalType>HERB_EXP</abnormalType>
<castRange>900</castRange>
<effectRange>900</effectRange>
<isMagic>1</isMagic> <!-- Magic Skill -->
<magicLevel>99</magicLevel>
<mpConsume>0</mpConsume>
<mpInitialConsume>0</mpInitialConsume>
<operateType>A2</operateType>
<basicProperty>NONE</basicProperty>
<targetType>TARGET</targetType>
<affectScope>SINGLE</affectScope>
<isTriggeredSkill>true</isTriggeredSkill>
<effects>
<effect name="ExpModify">
<amount>50</amount>
</effect>
<effect name="SpModify">
<amount>50</amount>
</effect>
</effects>
</skill>
<skill id="48079" toLevel="1" name="Triple Slash">
<!-- AUTO GENERATED SKILL TODO: FIX IT -->

View File

@ -184,7 +184,7 @@ public class NpcInfo extends AbstractMaskPacket<NpcInfoType>
if (npc.getClanId() > 0)
{
final Clan clan = ClanTable.getInstance().getClan(npc.getClanId());
if ((clan != null) && !npc.isMonster() && npc.isInsideZone(ZoneId.PEACE))
if ((clan != null) && ((npc.getTemplate().getId() == 34156 /* Clan Stronghold Device */) || (!npc.isMonster() && npc.isInsideZone(ZoneId.PEACE))))
{
_clanId = clan.getId();
_clanCrest = clan.getCrestId();

View File

@ -19,4 +19,5 @@ MobsSpawnNotRandom = 18812,18813,18814,22138,\
18221,18222,18226,18230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,\
18242,18243,18256,31452,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,31478,\
31479,31480,31481,31482,31483,31484,31485,31486,31487,\
22183,22324
22183,22324,\
34156

View File

@ -0,0 +1,3 @@
<html><body>Clan Stronghold Device:<br>
The Clan Capture effect is activated when you fight local monsters.
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
The Clan Stronghold Device has been captured.<br>
The Stronghold Device can be destroyed with a <font color="LEVEL">forced attack</font>.
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
In order to use the Clan Stronghold Device, you must <font color="LEVEL">join a clan</font>.<br>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest ClanStrongholdDevice back">Back</button>
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
Currently the device <font color="LEVEL">can be captured</font>. During a capture attempt the Clan Stronghold Effect is activated when you fight local monsters.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass Quest ClanStrongholdDevice capture">Capture the Stronghold</Button>
</body></html>

View File

@ -0,0 +1,217 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.others.ClanStrongholdDevice;
import java.util.HashMap;
import java.util.Map;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExChangeNpcState;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import org.l2jmobius.gameserver.network.serverpackets.NpcSay;
import ai.AbstractNpcAI;
/**
* @author Index
*/
public class ClanStrongholdDevice extends AbstractNpcAI
{
// NPCs
private static final int CLAN_STRONGHOLD_DEVICE = 34156;
private static final int[] NEARBY_MONSTER_IDS =
{
22200, // Porta
22201, // Excuro
22202, // Mordeo
22203, // Ricenseo
22204, // Krator
22205, // Catherok
22206, // Premo
22207, // Validus
22208, // Dicor
22209, // Perum
22210, // Torfe
22211, // Death Lord
};
// Skill
private static final SkillHolder CLAN_STRONGHOLD_EFFECT = new SkillHolder(48078, 1);
// Misc
private static final Map<Integer, Integer> CURRENT_CLAN_ID = new HashMap<>(); // Clan id key - NPC object id value (can be taken from npc.getScriptValue)
private static final Map<Integer, Long> LAST_ATTACK = new HashMap<>(); // NPC object id key - Time value
private static final Map<Integer, Location> DEVICE_LOCATION = new HashMap<>();
private ClanStrongholdDevice()
{
addCreatureSeeId(CLAN_STRONGHOLD_DEVICE);
addFirstTalkId(CLAN_STRONGHOLD_DEVICE);
addAttackId(CLAN_STRONGHOLD_DEVICE);
addSpawnId(CLAN_STRONGHOLD_DEVICE);
addTalkId(CLAN_STRONGHOLD_DEVICE);
addKillId(CLAN_STRONGHOLD_DEVICE);
addKillId(NEARBY_MONSTER_IDS);
}
@Override
public String onAdvEvent(String event, Npc npc, Player player)
{
if ((npc.getTemplate().getId() != CLAN_STRONGHOLD_DEVICE) || (player == null) || (event == null))
{
return super.onAdvEvent(event, npc, player);
}
if (event.equals("capture"))
{
if (npc.isAlikeDead())
{
return super.onAdvEvent(event, npc, player);
}
if (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()))
{
return "34156-02.htm";
}
if (player.getClan() == null)
{
return "34156-03.htm";
}
CURRENT_CLAN_ID.put(player.getClanId(), npc.getObjectId());
npc.setScriptValue(player.getClanId());
npc.setTitle(player.getClan().getName());
npc.setClanId(player.getClanId());
npc.setDisplayEffect(2);
npc.setInvul(false);
npc.broadcastInfo();
return "34156-01.htm";
}
else if (event.equals("back"))
{
if (npc.isAlikeDead())
{
return super.onAdvEvent(event, npc, player);
}
return npc.getId() + (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) ? "-02" : "") + ".htm";
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onFirstTalk(Npc npc, Player player)
{
if (npc.isAlikeDead())
{
return super.onFirstTalk(npc, player);
}
return npc.getId() + (CURRENT_CLAN_ID.getOrDefault(npc.getScriptValue(), 0) == 0 ? "" : "C") + ".htm";
}
@Override
public String onCreatureSee(Npc npc, Creature creature)
{
if (npc.getTemplate().getId() == CLAN_STRONGHOLD_DEVICE)
{
creature.sendPacket(new ExChangeNpcState(npc.getObjectId(), CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) ? 1 : 2));
}
return super.onCreatureSee(npc, creature);
}
@Override
public String onSpawn(Npc npc)
{
if (npc.getTemplate().getId() != CLAN_STRONGHOLD_DEVICE)
{
return super.onSpawn(npc);
}
npc.disableCoreAI(true);
npc.setAutoAttackable(false);
npc.setImmobilized(true);
npc.setDisplayEffect(1);
npc.setUndying(false);
npc.setScriptValue(0);
npc.setInvul(true);
npc.setClanId(0);
npc.setTitle("");
npc.broadcastInfo();
npc.broadcastPacket(new ExShowScreenMessage(NpcStringId.THE_CLAN_STRONGHOLD_DEVICE_CAN_BE_CAPTURED, 2, 5000, true));
DEVICE_LOCATION.put(npc.getObjectId(), npc.getLocation());
return super.onSpawn(npc);
}
@Override
public String onAttack(Npc npc, Player attacker, int damage, boolean isSummon)
{
if (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) && (LAST_ATTACK.getOrDefault(npc.getObjectId(), 0L) < (System.currentTimeMillis() - 5000L)))
{
npc.broadcastPacket(new NpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.AT_TACK_SIG_NAL_DE_TEC_TED_S1).addStringParameter(attacker.getName()));
LAST_ATTACK.put(npc.getObjectId(), System.currentTimeMillis());
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(Npc npc, Player killer, boolean isSummon)
{
if (npc.getTemplate().getId() == CLAN_STRONGHOLD_DEVICE)
{
npc.setClanId(0);
CURRENT_CLAN_ID.remove(npc.getScriptValue());
LAST_ATTACK.remove(npc.getObjectId());
DEVICE_LOCATION.remove(npc.getObjectId());
return super.onKill(npc, killer, isSummon);
}
if (CURRENT_CLAN_ID.getOrDefault(killer.getClanId(), 0) == 0)
{
return super.onKill(npc, killer, isSummon);
}
CLAN_STRONGHOLD_EFFECT.getSkill().activateSkill(npc, killer);
for (Player clanMate : World.getInstance().getVisibleObjects(killer, Player.class))
{
if (clanMate.getClanId() != killer.getClanId())
{
continue;
}
final Location deviceLocation = DEVICE_LOCATION.get(CURRENT_CLAN_ID.get(killer.getClanId()));
if ((clanMate.calculateDistance2D(deviceLocation) < 900) && (Math.abs(clanMate.getZ() - deviceLocation.getZ()) < 200))
{
clanMate.doCast(CLAN_STRONGHOLD_EFFECT.getSkill());
}
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new ClanStrongholdDevice();
}
}

View File

@ -2,6 +2,13 @@
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../xsd/spawns.xsd">
<spawn name="CrumaTower">
<group>
<npc id="34156" x="14562" y="117276" z="-12088" heading="22517" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="20851" y="117298" z="-12088" heading="12995" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="20871" y="111005" z="-12088" heading="63162" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="14569" y="111074" z="-12088" heading="57456" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="12821" y="109976" z="-9064" heading="12293" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="12568" y="118313" z="-9064" heading="43746" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="22680" y="114122" z="-9064" heading="54696" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="30483" x="17289" y="114112" z="-3440" heading="32768" respawnTime="60sec" /> <!-- Carsus - Ivory Tower Wizard -->
<npc id="30484" x="17636" y="114744" z="-11680" heading="6843" respawnTime="60sec" /> <!-- Janssen - Ivory Tower Wizard -->
<npc id="30487" x="17811" y="114750" z="-11680" heading="25785" respawnTime="60sec" /> <!-- Rombel - Ivory Tower Wizard -->

View File

@ -1919,7 +1919,7 @@
<skill id="4045" level="1" /> <!-- Full Magic Attack Resistance -->
</skillList>
</npc>
<npc id="34156" level="75" type="Folk" name="Clan Stronghold Device">
<npc id="34156" level="75" type="Monster" name="Clan Stronghold Device" usingServerSideTitle="true">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
<race>CONSTRUCT</race>
<sex>MALE</sex>

View File

@ -467,8 +467,28 @@
</skill>
<skill id="48078" toLevel="1" name="Clan Stronghold Effect">
<!-- Buff for the members of the clan that secured the Cruma Tower Clan Stronghold Device. For $s1 Acquired XP $s2 Acquired SP $s2 -->
<icon>icon.skill0000</icon>
<operateType>A1</operateType>
<abnormalLevel>1</abnormalLevel>
<abnormalTime>300</abnormalTime>
<abnormalType>HERB_EXP</abnormalType>
<castRange>900</castRange>
<effectRange>900</effectRange>
<isMagic>1</isMagic> <!-- Magic Skill -->
<magicLevel>99</magicLevel>
<mpConsume>0</mpConsume>
<mpInitialConsume>0</mpInitialConsume>
<operateType>A2</operateType>
<basicProperty>NONE</basicProperty>
<targetType>TARGET</targetType>
<affectScope>SINGLE</affectScope>
<isTriggeredSkill>true</isTriggeredSkill>
<effects>
<effect name="ExpModify">
<amount>50</amount>
</effect>
<effect name="SpModify">
<amount>50</amount>
</effect>
</effects>
</skill>
<skill id="48079" toLevel="1" name="Triple Slash">
<!-- AUTO GENERATED SKILL TODO: FIX IT -->

View File

@ -184,7 +184,7 @@ public class NpcInfo extends AbstractMaskPacket<NpcInfoType>
if (npc.getClanId() > 0)
{
final Clan clan = ClanTable.getInstance().getClan(npc.getClanId());
if ((clan != null) && !npc.isMonster() && npc.isInsideZone(ZoneId.PEACE))
if ((clan != null) && ((npc.getTemplate().getId() == 34156 /* Clan Stronghold Device */) || (!npc.isMonster() && npc.isInsideZone(ZoneId.PEACE))))
{
_clanId = clan.getId();
_clanCrest = clan.getCrestId();

View File

@ -19,4 +19,5 @@ MobsSpawnNotRandom = 18812,18813,18814,22138,\
18221,18222,18226,18230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,\
18242,18243,18256,31452,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,31478,\
31479,31480,31481,31482,31483,31484,31485,31486,31487,\
22183,22324
22183,22324,\
34156

View File

@ -0,0 +1,3 @@
<html><body>Clan Stronghold Device:<br>
The Clan Capture effect is activated when you fight local monsters.
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
The Clan Stronghold Device has been captured.<br>
The Stronghold Device can be destroyed with a <font color="LEVEL">forced attack</font>.
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
In order to use the Clan Stronghold Device, you must <font color="LEVEL">join a clan</font>.<br>
<Button ALIGN=LEFT ICON="RETURN" action="bypass -h Quest ClanStrongholdDevice back">Back</button>
</body></html>

View File

@ -0,0 +1,4 @@
<html><body>Clan Stronghold Device:<br>
Currently the device <font color="LEVEL">can be captured</font>. During a capture attempt the Clan Stronghold Effect is activated when you fight local monsters.<br>
<Button ALIGN=LEFT ICON="NORMAL" action="bypass Quest ClanStrongholdDevice capture">Capture the Stronghold</Button>
</body></html>

View File

@ -0,0 +1,217 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ai.others.ClanStrongholdDevice;
import java.util.HashMap;
import java.util.Map;
import org.l2jmobius.gameserver.enums.ChatType;
import org.l2jmobius.gameserver.model.Location;
import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
import org.l2jmobius.gameserver.model.actor.Player;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.network.NpcStringId;
import org.l2jmobius.gameserver.network.serverpackets.ExChangeNpcState;
import org.l2jmobius.gameserver.network.serverpackets.ExShowScreenMessage;
import org.l2jmobius.gameserver.network.serverpackets.NpcSay;
import ai.AbstractNpcAI;
/**
* @author Index
*/
public class ClanStrongholdDevice extends AbstractNpcAI
{
// NPCs
private static final int CLAN_STRONGHOLD_DEVICE = 34156;
private static final int[] NEARBY_MONSTER_IDS =
{
22200, // Porta
22201, // Excuro
22202, // Mordeo
22203, // Ricenseo
22204, // Krator
22205, // Catherok
22206, // Premo
22207, // Validus
22208, // Dicor
22209, // Perum
22210, // Torfe
22211, // Death Lord
};
// Skill
private static final SkillHolder CLAN_STRONGHOLD_EFFECT = new SkillHolder(48078, 1);
// Misc
private static final Map<Integer, Integer> CURRENT_CLAN_ID = new HashMap<>(); // Clan id key - NPC object id value (can be taken from npc.getScriptValue)
private static final Map<Integer, Long> LAST_ATTACK = new HashMap<>(); // NPC object id key - Time value
private static final Map<Integer, Location> DEVICE_LOCATION = new HashMap<>();
private ClanStrongholdDevice()
{
addCreatureSeeId(CLAN_STRONGHOLD_DEVICE);
addFirstTalkId(CLAN_STRONGHOLD_DEVICE);
addAttackId(CLAN_STRONGHOLD_DEVICE);
addSpawnId(CLAN_STRONGHOLD_DEVICE);
addTalkId(CLAN_STRONGHOLD_DEVICE);
addKillId(CLAN_STRONGHOLD_DEVICE);
addKillId(NEARBY_MONSTER_IDS);
}
@Override
public String onAdvEvent(String event, Npc npc, Player player)
{
if ((npc.getTemplate().getId() != CLAN_STRONGHOLD_DEVICE) || (player == null) || (event == null))
{
return super.onAdvEvent(event, npc, player);
}
if (event.equals("capture"))
{
if (npc.isAlikeDead())
{
return super.onAdvEvent(event, npc, player);
}
if (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()))
{
return "34156-02.htm";
}
if (player.getClan() == null)
{
return "34156-03.htm";
}
CURRENT_CLAN_ID.put(player.getClanId(), npc.getObjectId());
npc.setScriptValue(player.getClanId());
npc.setTitle(player.getClan().getName());
npc.setClanId(player.getClanId());
npc.setDisplayEffect(2);
npc.setInvul(false);
npc.broadcastInfo();
return "34156-01.htm";
}
else if (event.equals("back"))
{
if (npc.isAlikeDead())
{
return super.onAdvEvent(event, npc, player);
}
return npc.getId() + (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) ? "-02" : "") + ".htm";
}
return super.onAdvEvent(event, npc, player);
}
@Override
public String onFirstTalk(Npc npc, Player player)
{
if (npc.isAlikeDead())
{
return super.onFirstTalk(npc, player);
}
return npc.getId() + (CURRENT_CLAN_ID.getOrDefault(npc.getScriptValue(), 0) == 0 ? "" : "C") + ".htm";
}
@Override
public String onCreatureSee(Npc npc, Creature creature)
{
if (npc.getTemplate().getId() == CLAN_STRONGHOLD_DEVICE)
{
creature.sendPacket(new ExChangeNpcState(npc.getObjectId(), CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) ? 1 : 2));
}
return super.onCreatureSee(npc, creature);
}
@Override
public String onSpawn(Npc npc)
{
if (npc.getTemplate().getId() != CLAN_STRONGHOLD_DEVICE)
{
return super.onSpawn(npc);
}
npc.disableCoreAI(true);
npc.setAutoAttackable(false);
npc.setImmobilized(true);
npc.setDisplayEffect(1);
npc.setUndying(false);
npc.setScriptValue(0);
npc.setInvul(true);
npc.setClanId(0);
npc.setTitle("");
npc.broadcastInfo();
npc.broadcastPacket(new ExShowScreenMessage(NpcStringId.THE_CLAN_STRONGHOLD_DEVICE_CAN_BE_CAPTURED, 2, 5000, true));
DEVICE_LOCATION.put(npc.getObjectId(), npc.getLocation());
return super.onSpawn(npc);
}
@Override
public String onAttack(Npc npc, Player attacker, int damage, boolean isSummon)
{
if (CURRENT_CLAN_ID.containsKey(npc.getScriptValue()) && (LAST_ATTACK.getOrDefault(npc.getObjectId(), 0L) < (System.currentTimeMillis() - 5000L)))
{
npc.broadcastPacket(new NpcSay(npc, ChatType.NPC_GENERAL, NpcStringId.AT_TACK_SIG_NAL_DE_TEC_TED_S1).addStringParameter(attacker.getName()));
LAST_ATTACK.put(npc.getObjectId(), System.currentTimeMillis());
}
return super.onAttack(npc, attacker, damage, isSummon);
}
@Override
public String onKill(Npc npc, Player killer, boolean isSummon)
{
if (npc.getTemplate().getId() == CLAN_STRONGHOLD_DEVICE)
{
npc.setClanId(0);
CURRENT_CLAN_ID.remove(npc.getScriptValue());
LAST_ATTACK.remove(npc.getObjectId());
DEVICE_LOCATION.remove(npc.getObjectId());
return super.onKill(npc, killer, isSummon);
}
if (CURRENT_CLAN_ID.getOrDefault(killer.getClanId(), 0) == 0)
{
return super.onKill(npc, killer, isSummon);
}
CLAN_STRONGHOLD_EFFECT.getSkill().activateSkill(npc, killer);
for (Player clanMate : World.getInstance().getVisibleObjects(killer, Player.class))
{
if (clanMate.getClanId() != killer.getClanId())
{
continue;
}
final Location deviceLocation = DEVICE_LOCATION.get(CURRENT_CLAN_ID.get(killer.getClanId()));
if ((clanMate.calculateDistance2D(deviceLocation) < 900) && (Math.abs(clanMate.getZ() - deviceLocation.getZ()) < 200))
{
clanMate.doCast(CLAN_STRONGHOLD_EFFECT.getSkill());
}
}
return super.onKill(npc, killer, isSummon);
}
public static void main(String[] args)
{
new ClanStrongholdDevice();
}
}

View File

@ -2,6 +2,13 @@
<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../xsd/spawns.xsd">
<spawn name="CrumaTower">
<group>
<npc id="34156" x="14562" y="117276" z="-12088" heading="22517" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="20851" y="117298" z="-12088" heading="12995" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="20871" y="111005" z="-12088" heading="63162" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="14569" y="111074" z="-12088" heading="57456" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="12821" y="109976" z="-9064" heading="12293" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="12568" y="118313" z="-9064" heading="43746" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="34156" x="22680" y="114122" z="-9064" heading="54696" respawnTime="15sec" /> <!-- Clan Stronghold Device -->
<npc id="30483" x="17289" y="114112" z="-3440" heading="32768" respawnTime="60sec" /> <!-- Carsus - Ivory Tower Wizard -->
<npc id="30484" x="17636" y="114744" z="-11680" heading="6843" respawnTime="60sec" /> <!-- Janssen - Ivory Tower Wizard -->
<npc id="30487" x="17811" y="114750" z="-11680" heading="25785" respawnTime="60sec" /> <!-- Rombel - Ivory Tower Wizard -->

View File

@ -1919,7 +1919,7 @@
<skill id="4045" level="1" /> <!-- Full Magic Attack Resistance -->
</skillList>
</npc>
<npc id="34156" level="75" type="Folk" name="Clan Stronghold Device">
<npc id="34156" level="75" type="Monster" name="Clan Stronghold Device" usingServerSideTitle="true">
<!-- AUTO GENERATED NPC TODO: FIX IT -->
<race>CONSTRUCT</race>
<sex>MALE</sex>

View File

@ -511,8 +511,28 @@
</skill>
<skill id="48078" toLevel="1" name="Clan Stronghold Effect">
<!-- A buff for the members of the clan that captured the Clan Stronghold Device in Cruma Tower. Duration: $s1 Acquired XP $s2 Acquired SP $s2 -->
<icon>icon.skill0000</icon>
<operateType>A1</operateType>
<abnormalLevel>1</abnormalLevel>
<abnormalTime>300</abnormalTime>
<abnormalType>HERB_EXP</abnormalType>
<castRange>900</castRange>
<effectRange>900</effectRange>
<isMagic>1</isMagic> <!-- Magic Skill -->
<magicLevel>99</magicLevel>
<mpConsume>0</mpConsume>
<mpInitialConsume>0</mpInitialConsume>
<operateType>A2</operateType>
<basicProperty>NONE</basicProperty>
<targetType>TARGET</targetType>
<affectScope>SINGLE</affectScope>
<isTriggeredSkill>true</isTriggeredSkill>
<effects>
<effect name="ExpModify">
<amount>50</amount>
</effect>
<effect name="SpModify">
<amount>50</amount>
</effect>
</effects>
</skill>
<skill id="48079" toLevel="1" name="Triple Slash">
<icon>icon.skill0000</icon>

View File

@ -184,7 +184,7 @@ public class NpcInfo extends AbstractMaskPacket<NpcInfoType>
if (npc.getClanId() > 0)
{
final Clan clan = ClanTable.getInstance().getClan(npc.getClanId());
if ((clan != null) && !npc.isMonster() && npc.isInsideZone(ZoneId.PEACE))
if ((clan != null) && ((npc.getTemplate().getId() == 34156 /* Clan Stronghold Device */) || (!npc.isMonster() && npc.isInsideZone(ZoneId.PEACE))))
{
_clanId = clan.getId();
_clanCrest = clan.getCrestId();